DEV Community

Stacey
Stacey

Posted on • Edited on

axe-con 2022 takeaways: CSS

This year’s axe-con featured two talks about new and upcoming CSS changes and their potential impacts on accessibility, Rachel Andrew‘s “New CSS with accessibility in mind” and Stephanie Eckles’ "Modern CSS Upgrades To Improve Accessibility.” Both were great and absolutely worth the watch (registering with the con for free gets you access to previous sessions). Here are a few of the key takeaways I noted from the talks.

display: contents

The contents value was discussed by Rachel Andrew in “New CSS with accessibility in mind.” Supported by modern browsers, display: contents drops the wrapping “box” from elements to allow the children to inherit the flex behavior of their grandparent.

Take the following example:

<div class="container" style="display: flex">
    <div class="nested-div">A direct child div</div>
    <ul style="display: contents">
        <li>One List Item</li>
        <li>A Second List Item</li>
    </ul>
</div>
Enter fullscreen mode Exit fullscreen mode

Here we have a div with a class “container” that has two directly nested elements: another div, and an unordered list. If we give the container a display: flex and the unordered list the display: contents property and value, the list items contained therein will appear inline with the nested div as if they were immediate children of the container div.

Here’s a Codepen example if you’d like to play with it yourself.

Note that this specifically applies to the display of the children and not necessarily other properties. If I were to include a style like .container > * { margin-left: 5rem } the immediate child div would have a margin-left of 5rem, but the more deeply nested li elements would not.

From an accessibility perspective, from Andrew’s talk, I learned this was originally implemented incorrectly by browsers where the element was set to display: none and children were “put back” on the page—but they were all effectively hidden from screen readers. As of 2020, According to a blog post by Adrian Roselli, this was fixed in Chromium browsers, while Firefox and Safari still had issues when this was applied to tables. The lesson here being that whenever a fun new contents value is released, check how it is interpreted by assistive technologies to make sure the browser isn’t stripping the element’s role or removing it completely.

color-contrast()

The new bit of CSS I was most excited about from the talk was the one with the least amount of support. The functional notation color-contrast() is currently only implemented in Safari Technology Preview but has awesome potential! It compares one color with a list of other potential colors and picks the one match with the highest contrast. MDN Web Docs give the following example:

color: color-contrast(wheat vs tan, sienna, #d2691e)

Here, the color wheat is compared against a list containing two named colors and a hex value— tan, sienna and #d2691e —where it will ultimately return sienna as the color on the element.

This will be especially helpful when combined with CSS custom properties and the new prefers-color-scheme media query, also discussed in the talk. prefers-color-scheme detects the user’s OS preference for a light or dark theme, allowing you to customize your website to accommodate those preferences while still using brand colors. This means you could potentially do something like this in the near future:

:root {
  --background-color: #eeb4b3;
}

@media (prefers-color-scheme: dark) {
  :root {
    --background-color: #2f242c;
  }
}

body {
  background-color: var(--background-color);
  color: color-contrast(var(--background-color) vs #c179b9, #a42cd6, #502274);
}
Enter fullscreen mode Exit fullscreen mode

(try it on Codepen)

To test this, you will need to make sure you have Experimental Features → CSS color-contrast() enabled in your Safari Technology Preview.

prefers-color-scheme and prefers-contrast vs forced-colors

Touched on above, prefers-color-scheme is a newer media query supported by most modern browsers that checks for the user’s OS preference for dark or light theme, and allows us to adjust styles based on the users preference. However, as Andrew noted in her talk, just because a user prefers a dark color scheme on their OS does not mean your dark color scheme will be the most accessible combination for the user, so it is important to give users an option to toggle between your website’s light and dark themes.

By... contrast, prefers-contrast checks for the user’s color contrast settings at the OS level. This experimental media feature introduced in Stephanie Eckles’ talk, Modern CSS Upgrades to Improve Accessibility, accepts the values less, more, or no-preference (not set in OS). In her talk, Eckles also cited custom , meaning the user set preferences in the OS, though that is not currently listed on MDN Web Docs. These primarily help to serve users with light sensitivity where less will decrease the contrast and more will increase the contrast to help users better distinguish details.

Interestingly, Eckles said that these queries can be chained (once support is more universal, of course). In this case, a user can define a style for someone with a dark color scheme who prefers high contrast like so:

@media (prefers-color-scheme: dark) and (prefers-contrast: more) {
    .container {
        background-color: "darkslategray";
        color: "white"
    }
}
Enter fullscreen mode Exit fullscreen mode

On the same token, there is another new media query, forced-colors which is meant to specifically check for Windows’ users High Contrast setting. It has two potential values: none or active, where active indicates that forced colors mode is active on the user's machine.

Helpfully, Eckles explained the primary difference betweenprefers-contrast and force-colors: prefers-contrast presumes that the user still wants to see your design and colors, where force-colors requires you to use the user’s set color palette.

spacing with min() and clamp()

Moving back from the experimental to something more applicable in code today, Eckles gave some great tips for harnessing more modern CSS methods for responsive spacing.

clamp(), from Eckles’ example, is a great way to control the padding and keep it proportionate at different breakpoints/zoom levels. The example she uses is this:

padding: clamp(1rem, 5%, 1.5rem)

In this example, the padding value will be no smaller than 1rem, no larger than 1.5rem, and maintain 5% as an “ideal.” This saves us the trouble of having to define “pixel-perfect” padding tweaks at every breakpoint to ensure the boxes still look as expected in browser resize.

Similarly, for spacing between boxes, such as a series of <section> elements, she gives the following example:

section + section {
    margin-top: min(128px, 15vh)
}
Enter fullscreen mode Exit fullscreen mode

Full disclosure: math functions like min() generally make my brain hurt. My rudimentary understanding is that the browser will interpret the lowest of the comma-separated expressions to use when applicable. web.dev has a great demo of how this can work on Codepen. The tricky bit is that despite most examples using 2, min() can actually take any number of arguments, though it gets much harder to parse what is happening with more arguments added.

For accessibility specifically, the main takeaway here is that as users adjust their zoom or browser window size to accommodate their needs, the CSS will preserve the desired ratio between elements. If we were to instead define margin between sections with a set pixel measurement, the space between elements would appear larger and larger as users zoom, perhaps even pushing elements out of the viewport and thus making users unaware that more content even exists.

Take more away

While these were the new tricks that arguably blew my mind the most, these are absolutely not the end all be all of either talk. I highly recommend catching the recordings if you can. As of writing, you can still register for free even though the live event has passed, and view these sessions (as well as some great sessions from 2021!)

this post was cross-posted from my site and edited to fix typos

Top comments (0)