About The Author
Stephanie Eckles is a front-end focused software engineer. She’s the author of ModernCSS.dev which provides modern solutions to old CSS problems. She is the … More about Stephanie ↬
As the author of ModernCSS.dev, I’m a big proponent of CSS solutions. And, I love seeing the clever ways people use CSS for really out-of-the-box designs and interactivity! However, I’ve noticed a trend toward promoting “CSS-only” components using methods like the “checkbox hack”. Unfortunately, hacks like these leave a significant amount of users unable to use your interface.
If you’re using a framework or component library, you can use this article to help evaluate if the provided components meet accessibility requirements. It’s important to know that many of the items noted are not going to be fully covered by automated accessibility testing tools like aXe, and therefore need some manual testing. Or, you can use a testing framework like Cypress to create tests for the required functionality.
Meet Smashing Online Workshops on front-end & UX, with practical takeaways, live sessions, video recordings and a friendly Q&A. On design systems, CSS/JS and UX. With Brad Frost, Stephanie Eckles, Carie Fisher and so many others.
Determining If CSS-Only Is An Appropriate Solution
Here are a few questions to ask before you proceed with a CSS-only solution. We’ll cover some of the terms presented here in more context alongside their related components.
Quick tip: Another reference when you’re creating any kind of customized control is the Custom Control Accessible Development Checklist from the W3 “Using ARIA” guide. This mentions several points above, with a few additional design and semantic considerations.
Narrowing the definition of a tooltip is a bit tricky, but for this section we’re talking about small text labels that appear on mouse hover near a triggering element. They overlay other content, do not require interaction, and disappear when a user removes hover or focus.
The CSS-only solution here may seem completely fine, and can be accomplished with something like:
However, this ignores quite a list of accessibility concerns and excludes many users from accessing the tooltip content.
A large group of excluded users are those using touch screens where
:hover will possibly not be triggered since on touch screens, a
:hover event triggers in sync with a
:focus event. This means that any related action connected to the triggering element — such as a button or link — will fire alongside the tooltip being revealed. This means the user may miss the tooltip, or not have time to read its contents.
In the case that the tooltip is attached to an interactive element with no events, the tooltip may show but not be dismissible until another element gains focus, and in the meantime may block content and prevent a user from doing a task.
Additionally, users who need to use zoom or magnification software to navigate also experience quite a barrier to using tooltips. Since tooltips are revealed on hover, if these users need to change their field of view by panning the screen to read the tooltip it may cause it to disappear. Tooltips also remove control from the user as there is often nothing to tell the user a tooltip will appear ahead of time. The overlay of content may prevent them from doing a task. In some circumstances such as a tooltip tied to a form field, mobile or other on-screen keyboards can obscure the tooltip content. And, if they are not appropriately connected to the triggering element, some assistive technology users may not even know a tooltip has appeared.
Guidance for the behavior of tooltips comes from WCAG Success Criterion 1.4.13 — Content on Hover or Focus. This criterion is intended to help low vision users and those using zoom and magnification software. The guiding principles for tooltip (and other content appearing on hover and focus) include:
Alternatives To Tooltips
Tooltips should be a last resort. Sarah Higley — an accessibility expert who has a particular passion for dissuading the use of tooltips — offers this simple test:
Based on research Sarah was involved with for her role at Microsoft, an alternative solution is a dedicated “toggletip”. Essentially, this means providing an additional element to allow a user to intentionally trigger the showing and hiding of extra content. Unlike tooltips, toggletips can retain semantics of elements within the revealed content. They also give the user back the control of toggling them, and retain discoverability and operability by more users and in particular touch screen users.
If you’ve remembered the
title attribute exists, just know that it suffers all the same issues we noted from our CSS-only solution. In other words — don’t use
title under the assumption it’s an acceptable tooltip solution.
For more information, check out Sarah’s presentation on YouTube as well as her extensive article on tooltips. To learn more about tooltips versus toggletips and a bit more info on why not to use
title, review Heydon Pickering’s article from Inclusive Components: Tooltips and Toggletips.
Modals — aka lightboxes or dialogs — are in-page windows that appear after a triggering action. They overlay other page content, may contain structured information including additional actions, and often have a semi-transparent backdrop to help distinguish the modal window from the rest of the page.
I have seen a few variations of a CSS-only modal (and am guilty of making one for an older version of my portfolio). They may use the “checkbox hack”, make use of the behavior of
:target, or try to fashion it off of
:focus (which is probably really an overlarge tooltip in disguise).
As for the HTML
dialog element, be aware that it is not considered to be comprehensively accessible. So, while I absolutely encourage folks to use native HTML before custom solutions, unfortunately this one breaks that idea. You can learn more about isn’t accessible.
Unlike tooltips, modals are intended to allow structured content. This means potentially a heading, some paragraph content, and interactive elements like links, buttons or even forms. In order for the most users to access that content, they must be able to use keyboard events, particularly tabbing. For longer modal content, arrow keys should also retain the ability to scroll. And like tooltips, they should be dismissible with the Esc key — and there’s no way to enable that with CSS-only.
Modal Focus Decision Tree
Based on the WAI-ARIA Authoring Practices Modal Dialog Example, here is a simplified decision tree for where to place focus once a modal is opened. Context will always dictate the choice here, and ideally focus is managed further than simply “the first focusable element”. In fact, sometimes non-focusable elements need to be selected.
Quick tip: In the case of needing to focus a non-focusable element, such as a heading or paragraph, add
tabindex="-1" which allows the element to become programmatically focusable with JS but does not add it to the DOM tab order.
For a ready-to-go solution, Kitty Giraudel has created a11y-dialog which includes the feature requirements we discussed. Adrian Roselli also has researched managing focus of modal dialogs and created a demo and compiled information on how different browser and screen reader combinations will communicate the focused element.
Tabbed interfaces involve a series of triggers that display corresponding content panels one at a time. The CSS “hacks” you may find for these involve using stylized radio buttons, or
:target, which both allow only revealing a single panel at a time.
Optionally, you can make tab selection follow focus — meaning when a tab is focused its also then selected and shows its associated tab panel. The WAI-ARIA Authoring Practices offers this guide to making a choice for whether selection should follow focus.
The concept of a roving tabindex is that the value of the
tabindex value is programmatically controlled to manage the focus order of elements. In regards to tabs, this means that only the selected tab is part of the focus order by way of setting
tabindex="0", and unselected tabs are set to
tabindex="-1" which removes them from the natural keyboard focus order.
The reason for this is so that when a tab is selected, the next tab will land a user’s focus within the associated tab panel. You may choose to make the element that is the tab panel focusable by assigning it
tabindex="0", or that may not be necessary if there’s a guarantee of a focusable element within the tab panel. If you tab panel content will be more variable or complex, you may consider managing focus according to the decision tree we reviewed for modals.
Example Tab Patterns
Here are some reference patterns for creating tabs:
Also called slideshows or sliders, carousels involve a series of rotating content panels (aka “slides”) that include control mechanisms. You will find these in many configurations with a wide range of content. They are somewhat notoriously considered a bad design pattern.
The tricky part about CSS-only carousels is that they may not offer controls, or they may use unexpected controls to manipulate the carousel movement. For example, you can again use the “checkbox hack” to cause the carousel to transition, but checkboxes impart the wrong type of information about the interaction to users of assistive tech. Additionally, if you style the checkbox labels to visually appear as forward and backward arrows, you are likely to give users of speech recognition software the wrong impression of what they should say to control the carousel.
More recently, native CSS support for scroll snap has landed. At first, this seems like the perfect CSS-only solution. But, even automated accessibility checking will flag these as un-navigable by keyboard users in case there is there no way to navigate them via interactive elements. There are other accessibility and user experience concerns with the default behavior of this feature, some of which I’ve included in my scroll snap demo on SmolCSS.
Despite the wide range in how carousels look, there are some common traits. One option is to create a carousel using tab markup since effectively it’s the same underlying interface with an altered visual presentation. Compared to tabs, carousels may offer extra controls for previous and next, and also pause if the carousel is auto-playing.
Resources For Building Accessible Carousels
This refers to a component where a button toggles open a list of links, typically used for navigation menus. CSS implementations that stop at showing the menu on
:focus only miss some important details.
I’ll admit, I even thought that by using the newer
Quick tip: Ensure the correct implementation of the dropdown menu by associating the menu display to the selector of
] + .dropdown rather than basing the menu display on the presence of an additional JS-added class like
active. This removes some complexity from your JS solution, too!
This is also referred to as a “disclosure pattern” and you can find more details in the WAI-ARIA Authoring Practices’s Example Disclosure Navigation Menu.
Additional resources on creating accessible components
This content was originally published here.