axe-con 2022 takeaways: CSS
Tags: a11y, css
Published: 2022-03-22 23:04:31

---
title: axe-con 2022 takeaways: CSS
published: true
description: A brief summary of some of the new CSS features I learned about at axe-con and can’t wait to use.
tags: accessibility, css
---

This year’s [axe-con](https://www.deque.com/axe-con/schedule/) featured two talks about new and upcoming CSS changes and their potential impacts on accessibility, [Rachel Andrew](https://noti.st/rachelandrew)‘s “New CSS with accessibility in mind” and  [Stephanie Eckles](https://thinkdobecreate.com/)’ "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](https://noti.st/rachelandrew) 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: 

```html
<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>
```

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](https://codepen.io/heyitsstacey/pen/MWryMZp) 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](https://adrianroselli.com/2018/02/tables-css-display-properties-and-aria.html), 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](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color-contrast) 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:

```css
: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);
}
```

([try it on Codepen](https://codepen.io/heyitsstacey/pen/abENevK))

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](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-contrast). 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:

```css
@media (prefers-color-scheme: dark) and (prefers-contrast: more) {
	.container {
		background-color: "darkslategray";
		color: "white"
	}
}
```

On the same token, there is another new media query, `forced-colors` which is [meant to specifically check](https://chromestatus.com/feature/5757293075365888) 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 between`prefers-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:

```css
section + section {
	margin-top: min(128px, 15vh)
}
```

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](http://web.dev) has a great demo of how this can work on [Codepen](https://codepen.io/una/pen/rNeGNVL). 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](https://www.deque.com/axe-con/) 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*