CSS Day Online / AccessibilitΓ ... con stile
My face

Massimo Artizzu

Web dev & architect
at Antreem

Twitter logo / GitHub logo / dev.to logo @MaxArt2501

You can find these slides at

QR Code for the presentation's link maxart2501.github.io/css-accessibility-talk/css-day/

Do you know

display: contents ?

πŸ€”

Elements become ghosts! πŸ‘»

.wrapper {
  display: grid;
  grid-template-columns: 1fr 1fr;
}
.purple {
  display: contents;
}

It's like display: none for the element, but not its descendants

But… there's a problem.

Most browsers takes that too literally.

Caniuse.com screenshot showing that all browsers - except Firefox - remove the elements with display: contents from the accessibility tree. As of February 2020

How much does CSS affect accessibility?
πŸ€•

There's display: none, but what else?

πŸ‘‰ Let's see another example

<button>Add</button>

button {
  text-transform: uppercase;
}

“Add”

“A-D-D”

So, screen readers just inspect HTML+CSS?

Not really…

<nav>
  <ul>
    <li><a href="…">Home</a></li>
    <li><a href="…">Page</a></li>
    <li><a href="…">Site</a></li>
  </ul>
</nav>

ul {
  display: flex;
  list-style: none;
  ...
}

VoiceOver on Mac

chrome logo firefox logo safari logo
  • list
  • item count
  • link index
  • list
  • item count
  • link index
Β―\_(ツ)_/Β―
A confused man blinking his eyes

Screen readers inspect…

DOM+CSS
Representation of a DOM tree
The Accessibility Tree
Representation of an accessibility tree

The Accessibility Tree

Many elements are mapped 1-1:

The Accessibility Tree

Others are flattened:
It's <em>really</em> important
paragraph
  > text It's
  > text really
  > text important

The Accessibility Tree

And others are expanded:

video
  > button Play
  > button Mute
  > slider
  > graphic
chrome logo firefox logo safari logo 🌳 ♿️ πŸ‘† πŸ‘„ ⌨️ Accessibility feedback cycle

A good web developer should take care of the accessibility tree that comes out of the DOM

… but how is the tree generated?

Browsers and heuristics

  • πŸ‘‰ tables used for layouts;
  • πŸ‘‰ hidden content or…
  • πŸ‘‰ … placed far away;
  • πŸ‘‰ …

DevTools to the rescue 🦺

Chrome logo

Screenshot of Chrome DevTools accessibility panel

Firefox logo

Screenshot of Firefox DevTools accessibility panel

Safari logo

πŸ˜“

Did you know that…

Hz and kHz are CSS units?

Planned for…

Accessibility isn't just about blindness

It's also in the small things

… too small.

Asian man squinting his eyes trying to read a very small note

Is your font-size

big enough?

A stylized typewriter

In a nutshell…

  • πŸ“„ 2.54mm
  • πŸ–₯ 1.77mm
  • πŸ“±1.07mm

readability
>
legibility

Use sufficient line-height too!

normal ≈ 1.2

It's too low!

Do you pay for screen pixels?!

One last thing…

Drake 'bad' meme
:root {
  font-size: 20px;
  line-height: 30px;
}
Drake 'good' meme
:root {
  font-size: 125%;
  line-height: 1.5;
}

Speaking of content…

The oldest dev trick

<img src="image.png">
img:not([alt]) {
  &:not([role]), &:not([role=presentation]) {
  outline: 1px solid red;
}
}

But… have you ever used these images?

But what's behind that?

<i class="fa fa-home"></i>
.fa-home::before {
  content: '\f015';
}

Screen readers do announce generated content

(except for IE)

… but not that!

Or they use the Unicode name if available

So you either:

… but this isn't CSS!

Alternative text for CSS Generated Content

.icon-home::before {
  content: '\f015' / 'home';
}
Alternative text for CSS Generated Content

Meanwhile, in Safari…

.icon-home::before {
  content: '\f015';
  alt: 'home';
}
brucelawson.co.uk/2014/notes-on-draft-css-alt-property

Just two gotchas 🀫

Use with moderation

CSS Generated Content shouldn't usually contain… content!

It can disrupt your build task

CSS isn't the right place for translations

Although…

<i class="icon icon-home" data-meaning="Home"></i>

.icon-home::before {
  content: '\f015' / attr(data-meaning);
}
(Too bad this should work, but doesn't…) (Just use aria-label, then.)

How do screen readers read a page?

@media screen and (min-width: 1025px) {
  #app {
    display: grid;
    grid-template-columns: 15% auto 20%;
    grid-template-area: "head head head"
                        "nav  main side"
                        "nav  main ads";
  }
}
<div id="app">
  <header>...</header>
  <nav>...</nav>
  <aside>...</aside>
  <aside class="ads">...</aside>
  <main>...</main>
  <footer>...</footer>
</div>

One more reason to build mobile-first!

Media Queries Level 5

prefers-reduced-motion

Values: reduce | no-preference

prefers-reduced-motion

prefers-color-scheme

Values: light | dark | no-preference

… also nice for everyone!

Reading an article on medium

Spongebob's plancton with eyes burning on bright light
prefers-color-scheme

prefers-contrast

Values: high | low | no-preference

prefers-reduced-transparency

Values: reduce | no-preference

forced-colors

Values: active | none

light-level

Values: normal | dim | washed

… those media features

inverted-colors

Values: active | none

Safari 9.1 was released on March 2016 inverted-colors

It's still just a draft

😞

About colors…

Are you sure your text has enough

contrast? contrast?

You might know that…

Contrast ratio for:

But what's this "contrast ratio"?

Dudes yelling aggressively at each other, from asdfmovie 3
Formula to convert a color from the RGB space to sRGB Formula to get the luminance from a color in the sRGB space Formula to compute the RGB space to sRGB

We have hsl()

Why do we need luminance?

50% 50% 50% 50% 50% 50% 33% 94% 79% 85% 16% 43%
βœ… 8.59
🚫 2.44
🚫 1.37
βœ… 15.3
🚫 4.00
βœ… 5.25
A confused Vincent Vega, from Pulp Fiction
'Woman yelling at a cat' meme

There are other things to consider…

WCAG 2.1 requirements

“Large” text?

Animation of a disappointed guy

Toss a coin to your witcher,
o valley of plenty

Toss a coin to your witcher,
o valley of plenty

DevTools can help!

But DevTools have more tricks under their sleeves…

Try to use the emulation on this page

Visual deficiencies emulation (chrome logo 83+)

Lighthouse Accessibility report

Screenshot of Lighthouse in Chrome DevTools

There are extensions too

Links

That's all, folks!
πŸ‘‹

@each $question in $questions {
  @include answer($question);
}