a11y

speak

The speak property in CSS is for specifying how a browser should speak the content it reads, such as through a screen reader.

In other words, it's kind of like styling speech the way other CSS properties style visual elements of a webpage.

.module {
  speak: none;
}

(more…)

Maintaining Accessibility in a Responsive World

There a bit of a CSS trick is Scott Jehl's latest article. Perhaps you've used an "accessible hiding" technique? That's where you are deliberately avoiding display: none; because you want the element to be focusable, but not seen visually.

But... that can be awkward for anyone who uses the keyboard to navigate the site and also looks at the screen.

To avoid this, we try to remember that any accessibly-hidden content should be visible when it gains focus. For example, this CSS would place a focused element at the top of the viewport

.accessible-hidden {
  position: absolute;
  top: 0;
  left: -999px;
  height: 1px;
  width: 1px;
  clip: rect(1px, 1px, 1px, 1px);
  white-space: nowrap;
}
.accessible-hidden:focus {
  position: fixed;
  top: 0;
  left: 0;
  background: #fff;
  padding: 10px;
  /* etc etc... */
}

Scott credits Joe Watkins for the idea.

An Introduction to the Reduced Motion Media Query

The open web's success is built on interoperable technologies. The ability to control animation now exists alongside important features such as zooming content, installing extensions, enabling high contrast display, loading custom stylesheets, or disabling JavaScript.

Sites all too often inundate their audiences with automatically playing, battery-draining, resource-hogging animations. The need for people being able to take back control of animations might be more prevalent than you may initially think.

(more…)

The Art of Labeling

There's a lot of neat tricks in this video by Rob Dodson where he focuses on accessibility tricks in Chrome's DevTools. A few notes:

  • Chrome DevTools has an experimental feature to help with accessibility testing that you can unlock if you head to chrome://flags/ and turn on in the DevTools settings.
  • Wrapping an <input type="checkbox"> in a <label> gives the input a name of the text in the label, even without a for attribute.
  • The aria-labelledby attribute overrides the name of the element with the text taken from a different element, referenced by ID. It can even compose a name together from multiple elements, including itself.
  • Adding tabindex='0' to an element will make it focusable.

High Contrast, A PostCSS Plugin Story*

*Based on true events

It’s hard to imagine life without internet today. Many people’s lives are less or more tied with internet. Think about everything we rely on it for: communication, education, shopping, business control, home management, entertainment, etc. It’s like a world inside another world, with it’s own rules and diversity.

Around 80 million people in the EU are disabled and this number is growing. The unfortunate truth is that many of them can't use all the opportunity of the internet, because so many of them don't care about accessibility.

What can we do about this?

It’s a good question. We live in a time when technologies can help us to take care of people who need special care. More and more organizations, companies, even governments are getting involved to help people with disabilities.

Web Accessibility Law

Not so long ago the EU passed a law about web accessibility. This law covers public sector websites and mobile apps, like administrations, police departments, public hospitals, universities, and libraries. It will require them to be accessible for all citizens - in particular for the blind, the hard of hearing, the deaf, and those with low vision and with functional disabilities.

New rules accepted in the EU web accessibility directive are:

  • All websites or web applications owned by EU-member governments must be fully accessible to people with disabilities. New websites must be accessible and existing content must be updated.
  • Archival content and documents will be available on demand in accessible form.
  • Government videos must be closed captioned. Live video has a window of 14 days since first broadcast to get captions.
  • Online services, like paying fines or fees, will have to be accessible.
  • EU government websites must indicate if (and why) parts of their website are inaccessible.
  • EU member states must regularly monitor and report to both the public and the European Commission on the accessible status of their web services.

In a press release, Günther H. Oettinger, Commissioner for the Digital Economy and Society, stated:

It is not acceptable that millions of European citizens are left behind in the digital society. The agreement that we have just reached will ensure that everyone has the same opportunity to enjoy the benefits of the internet and mobile apps, to participate in society to a fuller extent and to lead a more independent life.

Echoing that sentiment, Andrus Ansip, Vice-President for the Digital Single Market, said:

Internet access should be a reality for everyone. Leaving millions of Europeans behind is not an option. Tonight’s agreement is an important step towards a Digital Single Market, which is about removing barriers so that all Europeans can get the best from the digital world.

I think it’s very important to understand that internet is the place where everyone is equal. And I think that nowadays, internet de facto should be accessible, in one or another form, for as more users as possible.

I would like to share our story about how we developed a tool that helps to develop a high contrast version of a website.

Contrast Matters

Contrast makes it easy to distinguish one thing from another. In web design, contrast usually refers to the difference between the foreground and background of text. In other words, how different are the words on the screen from the background they sit on.

Text contrast is an important accessibility criterion. When people use websites or apps, they don’t read, they scan. When most people scan or read quickly, they rely on word and character shapes rather than more explicitly conscious strategies like analyzing each letter and the order in which it appears. You’re probably doing that right now, by using good contrast text that makes those shapes easy to immediately recognize.

High Contrast

In some countries government requires from public websites special high contrast version of the website with inverted colors. You may know them by this kind of icon:

This high contrast setting benefits users with low vision or other visual disabilities.

The Challenge

Not so long ago our team has faced the project that required high contrast version. And it was a big challenge for all of us.

First of all we were digging all over the internet researching information about what is high contrast and how should it work. Unfortunately, we didn’t find enough information. Everything was very abstract and poor. But some information we did find useful. The background should be dark (black), text - opposite color of the background (white), links - yellow or green.

Some websites may even invert images, some may completely remove images from high-contrast version.

CSS Preprocessors

One way to build a high contrast version of a site is by using preprocessors like Less, Sass, or Stylus. Preprocessors also give us a lot of ways to compile two versions of website. For example it can be variables:

$high-contrast: true;
$background-color: #fff;
$background-high-contrast-color: #000;
$text-color: #000;
$text-high-contrast-color: #fff;

body {
  …
  @if $high-contrast == true {
    background-color: $background-high-contrast-color;
  } else {
    background-color: $background-color;
  }
  …
}
…
.text {
  @if $high-contrast == true {
    color: $text-color;
  } else {
    color: $text-high-contrast-color;
  }
}

This might make our CSS a bit complicated and hard to maintain. Here's another way, @mixins:

$high-contrast: true;
$background-color: #fff;
$background-high-contrast-color: #000;
$text-color: #000;
$text-high-contrast-color: #fff;

@mixin background-color {
  @if $high-contrast == true {
    background-color: $background-high-contrast-color;
  } @else {
    background-color: $background-color;
  }
}

@mixin text-color {
  @if $high-contrast == true {
    color: $text-high-contrast-color;
  } @else {
    color: $text-color;
  }
}

body {
  …
  @include background-color;
  …
}
…
.text {
  @include text-color;
}

This method is a little bit better, but still has disadvantages. There are tons of other ways how to develop high contrast version. Each one has its own advantages and disadvantages.

But what if you don’t use a preprocessor? Or what if your project is already under development and variables or mixins are not used properly or missing at all?

We have faced this problem. While one part of the team was researching high contrast and ways to integrate it into the development process, another part of the team already was developing the project. Plus, unfortunately, they didn't use a preprocessor at all.

A Plugin Idea!

Fortunately for us, we already knew about PostCSS and all its possibilities. The great thing about PostCSS for us was that we could just modify or replace those properties or values that we needed, everything else could stay untouched. Isn’t that great? This is why we decided to create the PostCSS High Contrast plugin.

Developing The PostCSS Plugin

At first, it seemed like one more challenge for us. No one had no idea how to write a PostCSS Plugin. We were surprised how easy it was. PostCSS has great documentation and community and this is very helpful especially for newbies like us.

After an hour of looking through PostCSS documentation, we were able to start with our plugin. PostCSS has really great API. Look at these few lines of js:

css.walkRules( function (rule) {
  if (rule.selector === 'body') {
    // do something…
  }
});

They speak for themselves!

But still, we faced a bunch of other problems:

  • What colors to change and what colors leave untouched?
  • What if colors are inherited from parent elements?
  • What if colors are already high contrast?
  • What if it is complex element, which is not that easy to modify, change it’s color or background-color?

We had a lot of questions. We didn’t know how to move forward.

First of all we had to decide what colors to change and what colors leave untouched. We tried to find out if each color is high contrast enough or not by checking it’s brightness and saturation:

 var declColor = color(decl.value).hsl();    
if (declColor.s > 50 && declColor.l > 50){
  decl.value = '#000';
}

But after some testing of this approach, we decided it didn’t fit very well for us. It was very complicated, sometimes it didn’t work as we expected, and it took more time to compile our CSS. We realized that the best way would be just to replace all the colors no matter what:

if (decl.prop === 'background-color') {
  decl.value = #000;
}

if (decl.prop === 'color') {
  decl.value = #fff;
}

This seemed to work great. After celebrating our another small win, we noticed that not all elements were affected. Investigation of the problem showed that not all elements have color properties. CSS inheritance! To solve this issue we decided to create “aggressive mode”.

“Aggressive mode” accepts a list of selectors that will get color property no matter what.

postcss([
  require('postcss-high-contrast')({
    aggressiveHC: true,
    aggressiveHCDefaultSelectorList: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'li', 'th', 'td'],
    aggressiveHCCustomSelectorList: ['div', 'span'],
  })
])

After few more different tests, it seemed that our plugin was finished.

How does it work?

Before I finish our story, I would like to describe how to use PostCSS High Contrast Plugin. I hope you are already familiar with PostCSS and its ecosystem. If not check out PostCSS website. No matter what your preprocessor preference, you can additionally use PostCSS. This means that PostCSS High Contrast plugin will work with any CSS.

Here’s an example configuration:

postcss([
  require('postcss-high-contrast')({
    aggressiveHC: true,
    aggressiveHCDefaultSelectorList: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'li', 'th', 'td'],
    aggressiveHCCustomSelectorList: ['div', 'span'],

    backgroundColor: '#000',
    altBgColor: '#fff',

    textColor: '#fff',

    linkColor: '#fcff3c',
    linkHoverColor: '#fcff3c',

    borderColor: '#fff',
    disableShadow: true,

    imageFilter: 'invert(100%)',
    imageSelectors: ['img'],

    removeCSSProps: false,
    CSSPropsWhiteList: ['background', 'background-color', 'color', 'border', 'border-top', 'border-bottom',
      'border-left', 'border-right', 'border-color', 'border-top-color', 'border-right-color',
      'border-bottom-color', 'border-left-color', 'box-shadow', 'filter', 'text-shadow']
  })
])

Normal mode example:

/* Before */
body {
  background: #fff;
  color: #000;
}

a {
  color: #0b39e1;
}

/* After */
body {
  background: #000;
  color: #fff;
}

a {
  color: #fcff3c;
}

Aggressive mode example:

/* Before */
h1 {
  font-size: 48px;
  margin: 0;
  padding: 0 24px;
  width: 100%;
}

p {
  font-size: 48px;
  margin: 0 0 24px;
}

/* After */
h1 {
  color: #fff;
  font-size: 48px;
  margin: 0;
  padding: 0 24px;
  width: 100%;
}

p {
  color: #fff;
  font-size: 48px;
  margin: 0 0 24px;
}

The End

It was great experience for us to develop the PostCSS High Contrast Plugin. I would like to thank the PostCSS team for the great tool, documentation, and API. We never imagined it would be so easy.

We live in a wonderful time. We have so many technologies that help us everyday and the internet is one of the most important. So let’s try to make it more accessible to everyone.

FormLinter

I absolutely love this idea from Thoughtbot. Just like automated tools that check your HTML for syntax, formatting, validity, or whatever else, FormLinter checks your <form> HTML for best practices. Things like every input having a label, using correct input types, required fields, and more.

Ben Orenstein:

Doing all these things right is worth the effort: improvements like these improve accessibility and increase conversions. However, checking this sort of thing by hand is tedious and error-prone.

We were testing some forms in the ol' CSS-Tricks team chat and it was doing what it said on the box. On Geoff's personal site, it gave his contact form a "B" for not having matching labels for inputs and not having any fields required (seems like a fairly high grade?). The form was output from the mega-popular "Contact Form 7" for WordPress, also a bit surprising.

Many of the forms we tested bombed the app though. No word on that. Might be an HTTPS thing?

Beware Smushed Off-Screen Accessible Text

J. Renée Beach:

Over a few sessions, Matt mentioned that the string of text “Show more reactions” was being smushed together and read as “Showmorereactions”.

Turns out a popular technique for hiding content visually (but not hiding it for assistive technology) involved setting width: 1px; which was forcing words to wrap one-word-per-line with "line feed" breaks, which the AT didn't treat the same as spaces.

Facebook had to update their accessible hiding class to include white-space: nowrap; to fix that. Gaël Poupard suggests replacing the deprecated clip value with the newer clip, except for the fallback.

.accessible_elem {
  clip: rect(1px 1px 1px 1px); /* IE 6/7 */
  clip: inset(50%); /* fix */
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap; /* fix */
  width: 1px;
}

Will we be flattening our HTML for CSS Grids?

I was watching Rachel Andrew talk about CSS Grid Layout yesterday at An Event Apart. Grid is amazing and the day will soon come where it's a dominant web layout tool of choice. That day isn't here yet though, as no stable browser is shipping the latest version of the spec (it's behind a flag at best).

The good news is that, as of just a few days ago, the spec is really stable and has entered "Candidate Recommendation" status. Since all browsers have been developing against the spec, it's likely that widespread non-prefixed ready-to-go support will drop in all stable browsers fairly soon.

The bad news is that it will probably do-so without subgrid support, a point that Rachel underscored well in her talk.

(more…)

icon-anchoricon-closeicon-emailicon-linkicon-logo-staricon-menuicon-nav-guideicon-searchicon-staricon-tag