Tag: Newer

Newer Things to Know About Good Ol’ HTML Lists

HTML lists are boring. They don’t do much, so we don’t really think about them despite how widely used they are. And we’re still able to do the same things we’ve always done to customize them, like removing markers, reversing order, and making custom counters.

There are, however, a few “newer” things — including dangers — to know when using lists. The dangers are mostly minor, but way more common than you might think. We’ll get to those, plus some new stuff we can do with lists, and even new ways to approach old solutions.

To clarify, these are the HTML elements we’re talking about:

  • Ordered lists <ol>
  • Unordered lists <ul>
  • Description lists <dl>
  • Interactive lists <menu>

Ordered lists, unordered lists, and interactive lists contain list items (<li>) which are displayed according to what kind of list we’re dealing with. An ordered list (<ol>) displays numbers next to list items. Unordered lists (<ul>) and menu elements (<menu>) displays bullet points next to list items. We call these “list markers” and they can even be styled using the ::marker pseudo-element. Description lists use description terms (<dt>) and description details (<dd>) instead of <li> and don’t have list markers. They‘re supposed to be used to display metadata and glossaries, but I can’t say I’ve ever seen them in the wild.

Let’s start off with the easy stuff — how to correctly (at least in my opinion) reset list styles. After that, we’ll take a look at a couple of accessibility issues before shining a light on the elusive <menu> element, which you may be surprised to learn… is actually a type of list, too!

Resetting list styles

Browsers automatically apply their own User Agent styles to help with the visual structure of lists right out of the box. That can be great! But if we want to start with a blank slate free of styling opinions, then we have to reset those styles first.

For example, we can remove the markers next to list items pretty easily. Nothing new here:

/* Zap all list markers! */ ol, ul, menu {   list-style: none; }

But modern CSS has new ways to help us target specific list instances. Let’s say we want to clear markers from all lists, except if those lists appear in long-form content, like an article. If we combine the powers of newer CSS pseudo-class functions :where() and :not(), we can isolate those instances and allow the markers in those cases:

/* Where there are lists that are not articles where there are lists... */ :where(ol, ul, menu):not(article :where(ol, ul, menu)) {   list-style: none; }

Why use :where() instead of :is()? The specificity of :where() is always zero, whereas :is() takes the specificity of the most specific element in its list of selectors. So, using :where() is a less forceful way of overriding things and can be easily overridden itself.

UA styles also apply padding to space a list item’s content from its marker. Again, that’s a pretty nice affordance right out of the box in some cases, but if we’re already removing the list markers like we did above, then we may as well wipe out that padding too. This is another case for :where():

:where(ol, ul, menu) {   padding-left: 0; /* or padding-inline-start */ }

OK, that’s going to prevent marker-less list items from appearing to float in space. But we sort of tossed out the baby with the bathwater and removed the padding in all instances, including the ones we previously isolated in an <article>. So, now those lists with markers sorta hang off the edge of the content box.

Notice that UA styles apply an extra 40px to the <menu> element.

So what we want to do is prevent the list markers from “hanging” outside the container. We can fix that with the list-style-position property:

Or not… maybe it comes down to stylistic preference?

Newer accessibility concerns with lists

Unfortunately, there are a couple of accessibility concerns when it comes to lists — even in these more modern times. One concern is a result of applying list-style: none; as we did when resetting UA styles.

In a nutshell, Safari does not read ordered and unordered lists styled with list-style: none as actual lists, like when navigating content with a screen reader. In other words, removing the markers also removes the list’s semantic meaning. The fix for this fix it to apply an ARIA list role on the list and a listitem role to the list items so screen readers will pick them up:

<ol style="list-style: none;" role="list">   <li role="listItem">...</li>   <li role="listItem">...</li>   <li role="listItem">...</li> </ol>  <ul style="list-style: none;" role="list">   <li role="listItem">...</li>   <li role="listItem">...</li>   <li role="listItem">...</li> </ul>

Oddly, Safari considers this to be a feature rather than a bug. Basically, users would report that screen readers were announcing too many lists (because developers tend to overuse them), so now, only those with role="list" are announced by screen readers, which actually isn’t that odd after all. Scott O’Hara has a detailed rundown of how it all went down.

A second accessibility concern isn’t one of our own making (hooray!). So, you know how you’re supposed to add an aria-label to <section> elements without headings? Well, it sometimes makes sense to do the same with a list that doesn’t contain a heading element that helps describe the list.

<!-- This list is somewhat described by the heading --> <section>   <h2>Grocery list</h2>   <ol role="list">      <!-- ... -->   </ol> </section>  <!-- This list is described by the aria-label --> <ol role="list" aria-label="Grocery list">   <!-- ... --> </ol>

You absolutely don’t have to use either method. Using a heading or an ARIA label is just added context, not a requirement — be sure to test your websites with screen readers and do what offers the best user experience for the situation.

In somewhat related news, Eric Bailey wrote up an excellent piece on why and how he considers aria-label to be a code smell.

Wait, <menu> is a list, too?

OK, so, you’re likely wondering about all of the <menu> elements that I’ve been slipping into the code examples. It’s actually super simple; menus are unordered lists except that they’re meant for interactive items. They’re even exposed to the accessibility tree as unordered lists.

In the early days of the semantic web, I mistakenly believed that menus were like <nav>s before believing that they were for context menus (or “toolbars” as the spec says) because that’s what early versions of the HTML spec said. (MDN has an interesting write-up on all of the deprecated stuff related to <menu> if you’re at all interested.)

Today, however, this is the semantic way to use menus:

<menu aria-label="Share article">   <li><button>Email</button></li>   <li><button>Twitter</button></li>   <li><button>Facebook</button></li> </menu>

Personally, I think there are some good use-cases for <menu>. That last example shows a list of social sharing buttons wrapped up in a labeled <menu> element, the notable aspect being that the “Share article” label contributes a significant amount of context that helps describe what the buttons do.

Are menus absolutely necessary? No. Are they HTML landmarks? Definitely not. But they’re there if you enjoy fewer <div>s and you feel like the component could use an aria-label for additional context.

Anything else?

Yes, there’s also the aforementioned <dl> (description list) element, however, MDN doesn’t seem to consider them lists in the same way — it’s a list of groups containing terms — and I can’t say that I’ve really seen them in use. According to MDN, they’re supposed to be used for metadata, glossaries, and other types of key-value pairs. I would just avoid them on the grounds that all screen readers announce them differently.

But let’s not end things on a negative note. Here’s a list of super cool things you can do with lists:


Newer Things to Know About Good Ol’ HTML Lists originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

CSS-Tricks

, , , , , , ,

Beyond Media Queries: Using Newer HTML & CSS Features for Responsive Designs

Beyond using media queries and modern CSS layouts, like flexbox and grid, to create responsive websites, there are certain overlooked things we can do well to make responsive sites. In this article, we’ll dig into a number tools (revolving around HTML and CSS) we have at the ready, from responsive images to relatively new CSS functions that work naturally whether we use media queries or not.

In fact, media queries become more of a complement when used with these features rather than the full approach. Let’s see how that works.

Truly responsive images

Remember when we could just chuck width: 100% on images and call it a day? That still works, of course, and does make images squishy, but there are a number of downsides that come with it, the most notable of which include:

  • The image might squish to the extent that it loses its focal point.
  • Smaller devices still wind up downloading the full size image.

When using images on the web, we have to make sure they’re optimized in terms of their resolution and size. The reason is to ensure that we have the right image resolution to fit the right device, so we don’t end up downloading really large and heavy images for smaller screens which could end up reducing the performance of a site. 

In simple terms, we’re making sure that larger, high-resolution images are sent to larger screens, while smaller, low-resolution variations are sent to smaller screens, improving both performance and user experience.

HTML offers the <picture> element that allows us specify the exact image resource that will be rendered based on the media query we add. As described earlier, instead of having one image (usually a large, high-resolution version) sent to all screen sizes and scaling it to the viewport width, we specify a set of images to serve in specific situations.

<picture>   <source media="(max-width:1000px)" srcset="picture-lg.png">   <source media="(max-width:600px)" srcset="picture-mid.png">   <source media="(max-width:400px)" srcset="picture-sm.png">   <img src="picture.png" alt="picture""> </picture>

In this example, picture.png is the full-size image. From there, we define the next-largest version of the image, picture-lg.png, and the size reduces in descending order until the smallest version, picture-sm.png. Note that we’re still using media queries in this approach, but it’s the <picture> element itself that is driving the responsive behavior rather than defining breakpoints in the CSS.

The media queries are added appropriately to scale with the sizes of the picture:

  • Viewports that are 1000px and above get picture.png.
  • Viewports that are between 601px and 999px get picture-lg.png.
  • Viewports that are between 401px and 600px get picture-sm.png.
  • Any thing smaller than 400px gets picture-sm.png.

Interestingly, we can also label each image by image density —  1x, 2x, 3x and so forth — after the URL. This works if we have made the different images in proportion to each other (which we did). This allows the browser to determine which version to download based on the screen’s pixel density in addition to the viewport size. But note how many images we wind up defining:

<picture>   <source media="(max-width:1000px)" srcset="picture-lg_1x.png 1x, picture-lg_2x.png 2x, picture-lg_3x.png 3x">   <source media="(max-width:600px)" srcset="picture-mid_1x.png 1x, picture-mid_2x.png 2x, picture-mid_3x.png 3x">   <source media="(max-width:400px)" srcset="picture-small_1x.png 1x, picture-small_2x.png 2x, picture-small_1x.png 3x">   <img src="picture.png" alt="picture""> </picture>

Let’s look specifically at the two tags nested inside the <picture> element: <source> and <img>.

The browser will look for the first <source> element where the media query matches the current viewport width, and then it will display the proper image (specified in the srcset attribute). The <img> element is required as the last child of the <picture> element, as a fallback option if none of the initial source tags matches.

We can also use image density to handle responsive images with just the <img> element using the srcset attribute:

<img  srcset="   flower4x.png 4x,   flower3x.png 3x,   flower2x.png 2x,   flower1x.png 1x  "  src="flower-fallback.jpg" >

Another thing we can do is write media queries in the CSS based on the screen resolution (usually measured in dots per inch, or dpi) of the device itself and not just the device viewport. What this means is that instead of:

@media only screen and (max-width: 600px) {   /* Style stuff */ }

We now have:

@media only screen and (min-resolution: 192dpi) {   /* Style stuff */ }

This approach lets us dictate what image to render based the screen resolution of the device itself, which could be helpful when dealing with high resolution images. Basically, that means we can display high quality pictures for screens that support higher resolutions and smaller versions at lower resolutions. It’s worth noting that, although mobile devices have small screens, they’re usually high resolution. That means it’s probably not the best idea rely on resolution alone when determining which image to render. It could result in serving large, high-resolution images to really small screens, which may not be the version we really want to display at such a small screen size.

body {   background-image : picture-md.png; /* the default image */ } 
 @media only screen and (min-resolution: 192dpi) {   body {     background-image : picture-lg.png; /* higher resolution */   } }

What <picture> gives us is basically the ability to art direct images. And, in keeping with this idea, we can leverage CSS features, like the object-fit property which, when used with object-position, allows us to crop images for better focal points while maintaining the image’s aspect ratio.

So, to change the focal point of an image:

@media only screen and (min-resolution: 192dpi) {   body {     background-image : picture-lg.png;     object-fit: cover;     object-position: 100% 150%; /* moves focus toward the middle-right */   } }

Setting minimum and maximum values in CSS

The min() function specifies the absolute smallest size that an element can shrink to. This function proves really useful in terms of helping text sizes to properly scale across different screen sizes, like never letting fluid type to drop below a legible font size:

html {   font-size: min(1rem, 22px); /* Stays between 16px and 22px */ }

min() accepts two values, and they can be relative, percentage, or fixed units. In this example, we’re telling the browser to never let an element with class .box go below 45% width or 600px, whichever is smallest based on the viewport width:

.box {   width : min(45%, 600px) }

If 45% computes to a value smaller than 600px, the browser uses 45% as the width. Conversely, if  45% computes to a value greater than 600px, then 600px will be used for the element’s width.

The same sort of thing goes for the max() function. It also accepts two values, but rather than specifying the smallest size for an element, we’re defining the largest it can get.

.box {   width : max(60%, 600px) }

If 60% computes to a value smaller than 600px, the browser uses 60% as the width. On the flip side, if 60% computes to a value greater than 600px, then 600px will be used as the element’s width.

And, hey, we can even set a minimum and maximum range instead using the minmax() function:

.box {   width : minmax( 600px, 50% ); /* at least 600px, but never more than 50% */ }

Clamping values

Many of us have been clamoring for clamp() for some time now, and we actually have broad support across all modern browsers (sorry, Internet Explorer). clamp() is the combination of the min() and max() functions, accepting three parameters:

  1. the minimum value,
  2. the preferred value, and
  3. the maximum value

For example:

.box {   font-size : clamp(1rem, 40px, 4rem) }

The browser will set the font at 1rem until the computed value of 1rem is larger than 40px. And when the computed value is above 40px? Yep, the browser will stop increasing the size after it hits 4rem. You can see how clamp() can be used to make elements fluid without reaching for media queries.

Working with responsive units

Have you ever built a page with a large heading or sub-heading and admired how great it looked on a desktop screen, only to check it on a mobile device and find out that’s it’s too large? I have definitely been in this situation and in this section I’ll be explaining how to handle such problems.

In CSS, you can determine sizes or lengths of elements using various units of measurements, and the most used units of measurements includes: px, em, rem, %, vw, and vh. Although, there are several more units that aren’t used as frequently. What’s of interest to us is that px can be considered an absolute unit, while the rest are considered relative units.

Absolute units

A pixel (px) is considered an absolute unit mainly because it’s fixed and does not change based on the measurement of any other element. It can be considered as the base, or root, unit that some other relative units use. Trying to use pixels for responsive behavior can bump into issues because it’s fixed, but they’re great if you have elements that should not be resized at all.

Relative units

Relative units, like %, em, and rem, are better suited to responsive design mainly because of their ability to scale across different screen sizes.

vw: Relative to the viewport’s width
vh: Relative to the viewport’s height
rem: Relative to the root (<html>) element (default font-size is usually 16px )
em: Relative to the parent element
%: Relative to the parent element

Again, the default font size for most browsers is 16px and and that’s what rem units use to generate their computed values. So, if a user adjusts the font size on the browser, everything on the page scales properly depending on the root size. For example, when dealing a root set at 16px, the number you specify will multiply that number times the default size. For example:

.8rem = 12.8px (.8 * 16) 1rem = 16px (1 * 16) 2rem = 32px (2 * 16)

What if either you or the user changes the default size? As we said already, these are relative units and the final size values will be based off of the new base size. This proves useful within media queries, where you just change the font size and the entire page scales up or down accordingly.

For example, if you changed the font-size to 10px within the CSS, then the calculated sizes would end up being:

html {   font-size : 10px; }
1rem = 10px (1 * 10) 2rem = 20px (2 * 10) .5rem = 5px (.5 * 10)

Note: This also applies to percentage %. For instance:

100% = 16px; 200% = 32px;  50% = 8px;

And what’s the difference between rem and em units? It’s what the unit uses as its base element. rem calculates values using the font size of the root (<html>) element, whereas an element declaring em values references the font size of the parent element that contains it. If the size of specified parent element is different from the root element (e.g. the parent elements is 18px but the root element is 16px) then em and rem will resolve to different computed values. This gives us more fine-grained control of how our elements respond in different responsive contexts.

vh is an acronym for viewport height, or the viewable screen’s height. 100vh represent 100% of the viewport’s height (depending on the device). In the same vein, vw stands for viewport width, meaning the viewable screen’s width of the device, and 100vw literally represents 100% of the viewport’s width.

Moving beyond media queries

See that? We just looked at a number of really powerful and relatively new HTML and CSS features that give us additional (and possible more effective) ways to build for responsiveness. It’s not that these new-fangled techniques replace what we’ve been doing all along. They are merely more tools in our developer tool belt that give us greater control to determine how elements behave in different contexts. Whether it’s working with font sizes, resolutions, widths, focal points, or any number of things, we have more fine-grain control of the user experience than ever before.

So, next time you find yourself working on a project where you wish you had more control over the exact look and feel of the design on specific devices, check out what native HTML and CSS can do to help — it’s incredible how far things have come along.


The post Beyond Media Queries: Using Newer HTML & CSS Features for Responsive Designs appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , , , , , , ,
[Top]