A Complete Guide To Accessible Front-End Components — Smashi…

In a new short series of posts, we highlight some of the useful tools and techniques for developers and designers. Recently we’ve covered CSS Auditing Tools and CSS Generators, and this time we look into reliable accessible components: from tabs and tables to toggles and tooltips.

Table of Contents

Below you’ll find an alphabetical list of all accessible components. Skip the table of contents, or just scroll down to explore them one-by-one.

Accessible :focus Styles

Every browser has default focus styles, yet out of the box, they aren’t very accessible. The goal of :focus is to give the user guidance on where exactly they are in the document and help them navigate through it. To achieve that, we need to avoid a focus that’s too subtle or not visible at all. In fact, removing outline is a bad idea as it removes any visible indication of focus for keyboard users. The more obvious the focus is, the better.

Better :focus Styles
Better :focus Styles (Large preview)

There are ways of designing better :focus styles. In her article Tips For Focus Styles, Nic Chan highlights a few helpful tips on how to improve focus styles with better affordance and a bit of padding, offset, and proper outlines. Need more fun with :focus styles? Lari Maza has got your back, too.

We can also use :focus-within to style the parent element of a focused element, and :focus-visible to not show focus styles when interacting with a mouse/pointer  if it causes any issues in your design.

It’s important co consider the accessibility concerns around :focus-visible: as Hidde de Vries has noted, not all people who rely on focus styles use a keyboard and making focus styles keyboard-only takes away an affordance for mouse users too, as focus also indicates that something is interactive (thanks to Jason Webb for the tip!).

Finally, it’s worth noting that most recently Chrome, Edge, and other Chromium-based browsers stopped displaying a focus indicator (focus ring) when the user clicks or taps a button (thanks to Kim Johannesen for the tip!).

Accessible Autocomplete

Every time you have to deal with a larger data set, be it a map, a data visualization, or just a country selector in checkout, autocomplete can boost customer’s input massively. But just as it helps with the input, it needs to help with announcing the options and the selection to the screen reader users as well.

A fully accessible autocomplete JavaScript component that follows WAI-ARIA best practices., the team behind the Government Digital Service in UK, has open-sourced accessible-autocomplete (among many other things), a JavaScript component that follows WAI-ARIA best practices. You can choose when to start displaying suggestions, and allows to display the menu as an absolutely positioned overlay, or select the first suggestion by default. The team also provides a demo page, with a dozen of accessible autocomplete examples and implementations.

It’s not uncommon to have a link or button that visually has no text but consists only of an icon — a compact navbar, for example, or social icons. But how do you make sure that these kinds of icon links are fully accessible? As it turns out, it’s not as straightforward as one might think.

Accessible icon links
A code example from a post on accessible icon links by Kitty Giraudel. (Large preview)

To show how we can do better, Kitty Giraudel dedicated an article “Accessible Icon Links” to the issue. They use an icon link consisting of an SVG with the iconic Twitter bird to illustrate the point, and shows step by step how to make it accessible: with a descriptive text that is visually hidden, then removing the SVG markup from the accessibility tree with aria-hidden, and, finally, correcting the fact that svg elements can be focused on Internet Explorer by adding the focusable attribute. At the end of the article, Kitty also shows how to turn all of this into a little React component.

A small detail that will make a huge difference for a lot of users.

(Large preview)

In Creating Accessible Icon Buttons and Inclusively Hidden, Sara Soueidan and Scott O’Hara go into all the fine intricacies and details of icon buttons, exploring a number of techniques to make it work. Sara and Scott explore a number techniques, suggesting to use an appropriate technique for accessible visually hidden text — the text that will be visually hidden but accessible to screen readers. This could be done with a .sr-only utility class, or hidden and aria-labelledby, or aria-label alone. Sara wouldn’t recommend to use the SVG icon itself to provide a label for the button when I can provide one on the button itself directly.

In general though, there is still quite a bit of confusion which element to use for user interaction: when do we use links, and when do we use buttons? Marcy Sutton has written a detailed piece on Links vs. Buttons in Modern Applications. With a link, the visitor navigates to a new resource, taking them away from the current context. But a button prompts a change in the interface.

When a button is not a button: a guide by Vadim Makeev on yours truly Smashing Magazine. (Large preview)

Marcy outlines use cases for both links and buttons in single-page applications, showing that a button is a perfect element for opening a modal window, triggering a pop-up, toggling an interface or playing media content. You can also check Vadim Makeev’s article on “When Is A Button Not A Button?”.

Inaccessible Disabled Buttons

It has become quite common for lengthy web forms to keep the “Continue” button disabled until the customer has provided all data correctly. This behavior acts as an indicator that something is wrong with the form, and it can’t be completed without reviewing the input. This works if the inline validation for every input field is working well, and it doesn’t work at all when it’s glitchy or buggy.

Disabled Buttons
An alternative to disabled buttons, by Jordan Moore. (Large preview)

In “Disabled Buttons Suck”, Hampus Sethfors highlights the downsides of disabled buttons. With them in place, we do communicate that something is wrong, but we don’t really explain what is wrong, or how to fix it. So if the customer has overlooked an error message — be it in a lengthy form on desktop, or even in a short form on mobile, they’ll be lost. In many ways, keeping buttons active and communicating errors is more efficient.

And if it’s not possible, at least provide a way out with a button “I can’t complete the form, please help”, so customer support can get back to customers in case they get into trouble. If you need a more detailed refresher on web forms, “Form Design From One to Zero” will keep you busy.

Accessible Carousels and Content Sliders

An accessible carousel sounds a bit like oxymoron — while there are plenty of scripts that provide the functionality, only few of them are accessible. Now there are, of course, accessible range sliders, but carousels are a slightly different component. As Alison Walden notices in her article on “If you must use a carousel, make it accessible”, the sighted person is not forced to use the carousel at all, but keyboard users are forced to navigate through the carousel in its entirety. At the very least, a hidden “skip” link could appear on keyboard focus. Also, once the person has tabbed through all the panel sets, focus should move to the next interactive element that follows the carousel.

Shows path of screen reader user in browse mode, into the slider and from one item to the next
Shows path of screen reader user in browse mode, into the slider and from one item to the next (Large preview)

Heydon Pickering suggests to use list markup to group the slides together, include previous and next buttons, snap points, and use invisible linked items removed from focus. The article also provides a code sample which uses IntersectionObserver, so you might need a polyfill for it.

Accessible Close Buttons

“Close” buttons are everywhere — in modals, ads, confirmation messages, cookie prompts and any overlays that will appear in your interface. Unfortunately, the functionality is often limited to mouse users, leaving screen reader users and keyboard-users out. We can fix it.

(Large preview)

In “Accessible Close Buttons” Manuel Matuzovic goes into deep details highlighting 11 examples and patterns of inaccessible close buttons as well as 5 examples of close buttons that work fairly well. The easiest way to solve the problem is to provide a button with visible text and only visually accessible icon and ensure that the description by screen readers isn’t polluted by the icon’s description. Manuel also provides code examples of 5 close buttons that you can apply to your work right away.

Accessible Checkboxes And Radio Buttons

The good ol’ issue: how do we style checkboxes and radio-buttons to ensure that they look, well, at least similar, in most browsers — while ensuring that they stay accessible as well? In her article, Sara Soueidan covers a few techniques to keep in mind to achieve the desired result.

Sara covers the different techniques for hiding elements, how each of them affects the accessibility of the content, and how to visually hide them, so they can be replaced with a more styleable alternative: the SVG.

Styling Checkboxes And Radio Buttons In CSS
Styling Checkboxes And Radio Buttons In CSS (Large preview)

When hiding an interactive element, we need to make sure we choose a hiding technique that keeps it screen reader-accessible, position it on top of whatever is visually replacing it, so that a user navigating by touch can find it where they expect to, and then make it transparent. Sara also provides live demos that we can use right away, along with useful references to articles for further reading.

Accessible Color Systems

Getting color contrast right is an essential part of making sure that not only people with visual impairments can easily use your product but also everyone else when they are in low-light environments or using older screens. However, if you’ve ever tried to create an accessible color system yourself, you probably know that this can be quite a challenge.

Color system for icons consisting of nine colors
Color system for icons consisting of nine colors. (Large preview)

The team at Stripe recently decided to tackle the challenge and redesign their existing color system. The benefits it should provide out of the box: pass accessibility guidelines, use clear and vibrant hues that users can easily distinguish from one another, and have a consistent visual weight without a color appearing to take priority over another. If you’re curious to find out more about their approach, their blog post on accessible color systems will give you valuable insights.

Accessible Color Palettes

Finding the perfect tint or shade of a color is not only a matter of taste but also accessibility. After all, if color contrast is lacking, a product could, in the worst case, even become unusable for people with vision impairments. WCAG 2.0 level AA requires a contrast ratio of at least 4.5:1 for normal text.) and 3:1 for large text, and WCAG 2.1 requires a contrast ratio of at least 3:1 for graphics and UI components (such as form input borders). AAA requires a contrast ratio of at least 7:1 for normal text and 4.5:1 for large text. A very detailed contrast checker to help you detect potential pitfalls ahead of time comes from Gianluca Gini: Geenes.

Creating accessible color palettes with Geenes (Large preview)

The tool lets you tinker with hue ranges and saturation and apply the color palettes to one of three selectable UI mockups. Once applied, you can trigger different kinds of vision impairments to see how affected people see the colors and, finally, make an informed decision on the best tones for your palette. To use the colors right away, just copy and paste their code or export them to Sketch. You can also emulate vision deficiencies in DevTools.

Accessible Comics

When we use slightly more complex shapes and layouts on the web, sometimes it appears to be so much easier to just save it as a foreground or background image and serve different images to small and large screens. This holds true for complicated charts and graphs as well as good old comics with speaking bubbles, but what if we could re-imagine the experience altogether?

Comics Accessibility
Comics Accessibility (Large preview)

Comica11y is an experiment by Paul Spencer that aims to achieve an all-inclusive online comic reading experience. What if we could have different reading modes for the comic, e.g. with closed captions, proper focus management to navigate between panels, high-contrast mode, SVG color blindness filters, programatic bubbles, selectable and translatable text, LTR and RTL support, and even adjustable font sizes? A wonderful initiative that shows just how far we can take UI challenges and use the web to enhance the experience greatly.

Accessible Component Libraries

While many of the component libraries we create are trying to cover all the usual suspects (the accordions, the tables, the carousels, the drop-downs, along with typography, colors and box shadows), No Style Design System by Adam Silver is focused primarily around accessibility and web forms.

An accessible component library No Style Design System, by Adam Silver.

As a system created for and used in his book on Form Design Patterns, Adam’s library provides a set of accessible components for everything from autocomplete, checkboxes and password reveal to radios, select boxes and steppers. Most of them have a minimal CSS styling with clean, accessible markup.

And if you need slightly more advanced components, Heydon Pickering’s Inclusive Components — we mentioned some examples from it above — has got your back: with comprehensive tutorials on accessible cards, data tables, notifications, sliders, tabbed interfaces, tooltips, menus and toggles.

Overlays and pop-ups are always problematic. But especially for screen reader users, sometimes those prompts are incredibly difficult to deal with to set any settings or even confirm the usage of cookies on the site. In her 15-mins talk on “Screen readers and cookie consents”, Leonie Watson goes into detail explaining the poor experiences that compliance pop-ups have for accessibility. In some cases, users glide past consent prompts without being aware of them, in the others, the prompt are impossible to accept, resulting in an inability to use the site at all.

(Large preview)

So how can we make them better? In Cookie banners and accessibility, Sheri Byrne-Haber highlights common issues that cookie prompts usually have: from how they visually appear to focus traps, the appearance in the tab order, the type of acceptance and alternate formats of consent disclosure. Quentin Bellanger provides a basic code example of a cookie consent modal and a tutorial along with it. There are also free open-source solutions: Osano Cookie Consent and cookie-consent-box, but they might require some accessibility work.

A Complete Guide To Dark Mode On The Web

Dark mode is quickly becoming a user preference with Apple, Windows, and Google having it implemented into their operating systems. But what about dark mode on the web? Adhuham wrote a comprehensive guide to dark mode that delves into different options and approaches to implementing a dark mode design on the web.

Light and dark mode on DuckDuckGo
Light and dark mode on DuckDuckGo (Large preview)

To start off, the guide looks at the technical considerations that implementing a dark mode entails, covering different approaches to toggling the themes and how to store a user’s preferences so that they will be applied consistently throughout the site and on subsequent visits. Tips for handling user agent styles with the color-scheme meta tag help avoid potential FOIT situations.

Design considerations are also tackled, of course, with valuable tips to get images, shadows, typography, icons, and colors ready for dark mode. While on it: to ensure we don’t unintentionally break the high contrast in mode, take a look at Styling for Windows High Contrast mode (thanks for the tip, Courtney Heitman!).

Accessible Data Charts

Data visualizations are a great way to make information stand out. However, they also come with their own accessibility challenges. When Sara Soueidan teamed up with SuperFriendly to create an accessible micro-site for Khan Academy’s annual report, she wanted to make sure that the way the data is presented and implemented is as accessible as possible, regardless of how a visitor explores the site. Her solution: SVG.

Chart from Khan Academy’s annual report showing US public school students by income level
Chart from Khan Academy’s annual report showing US public school students by income level. (Large preview)

In a case study on accessible data charts, Sara summarized everything you need to consider when you want to make your SVG charts and visualizations accessible — beginning with the most important step of choosing an appropriate embedding technique. It also covers why you should avoid trying to make an SVG chart accessible using ARIA roles and why Sara didn’t choose <figure> to embed them. A fantastic reference guide. Plus: especially on graphs we could also use better accessible text labels, and Sara covers them in a separate article as well.

Accessible Data Visualizations

Data visualizations often contain important information that users have to act upon. While sometimes we can use large numbers with short sentences instead, visualizations can help understand developments and large amount of information faster. But that means that the information has to be easy to understand, and that refers especially to the selection of colors, the way information is presented, labels, legends as well as patterns and shapes. In their series of articles on accessibility in data visualizations, Sarah L. Fossheim highlights useful guidelines and resources around the topic, along with examples, do’s and don’ts to keep in mind when designing accessible data visualizations.

Color should not be the only visual clue. It’s a good idea to use patterns as well as color in charts
Color should not be the only visual clue. It’s a good idea to use patterns as well as color in charts. Via: Keen (Large preview)

Sarah suggests to not rely on color to explain the data, and avoid bright and low-contrast colors in general. Using patterns and shapes in addition to color is useful, and clear language, labels and legends can help clearly explain the data visualization. Every article is packed with plenty of examples and resources for further reading. Also worth checking: Sarah’s review of US presidential election data visualizations (thanks to Stephanie Eckles for the tip!).

Accessible Date Pickers

There are dozens of date picker libraries out there, but it’s always great to have reliable workhorses that just work across browsers, don’t have heavy dependencies, are written reasonably well, and meet all major accessibility requirements.

A Reliable Date Picker Library
A Reliable Date Picker Library (Large preview)

Duet Date Picker is just like that. It’s an accessible, WCAG 2.1 compliant date picker that can be implemented and used across any JavaScript framework or no framework at all. It comes with built-in functionality that allows you to set a minimum and a maximum allowed date, and weighs around 10kb minified and Gzip’ed (this includes all styles and icons).

If you need an alternative, check out React Dates, a library released by Airbnb that’s optimized for internationalization, while also being accessible and mobile-friendly.

Accessible Cross-Browser Form Styles

Have you ever struggled with hiding and styling custom checkboxes and radio buttons? What about custom select-styles? Or perhaps an accessible dropdown-navigation menu? We tend to build and rebuild the same components all the time, so let’s get them right once and for all.

(Large preview)

Sarah Higley’s “<select> your poison” is a comprehensive two-part deep dive into all the challenges and intricacies of styling the <select> element, with editable and multi-select variants, their comparative usability (with data!) and practical recommendations of how to get it right.

Stephanie Eckles’ Modern CSS Solutions for Old CSS Problems highlights plenty of useful modern techniques to solve plenty of challenges, but some articles from her series are dedicated to forms: CSS custom checkboxes, styled radio buttons, select styles, inputs, and textareas.

On her blog, Sara Soueidan goes into detail explaining how to inclusively hide and style checkboxes and radio buttons. Bonus: Adrian Roselli’s code examples provides additional insights into under-engineered toggles. Fantastic resources to use right away and style forms accessibly.

Accessible Footnotes and Sidenotes

In their essence, footnotes aren’t much more than jump-links — links to the description of a source, either placed at the bottom of the document, or in the sidebar, or appearing inline, a little accordion. However, as footnotes are jump-links, we need to ensure that screen reader users understand when links are references to footnotes — and we can do it with the aria-describedby attribute. The counter for every link would be implemented via a CSS counter. With :target, we then highlight the row which the reader has jumped to, and we provide a back-link back to the actual footnote place in the content.

Inline footnotes on the Harvard Law Review website. (Large preview)

Kitty Giraudel goes into detail explaining how to build accessible footnotes, and you can also
check how to build accessible footnotes with React and use react-a11y-footnotes to build them in React with Eleventy (thanks to Kitty Giraudel for the tip!).

Accessible Inputs

In 2019, WebAIM analyzed the accessibility of the top one million websites, with a shocking conclusion: the percentage of error-free pages was estimated to be under one percent. To make our sites inclusive and usable for people who rely on assistive technology, we need to get the basics of semantic HTML right. With its credo of starting small, sharing, and working together, Oscar Braunert’s article on inclusive inputs is a great starting point to do so.

Inclusive Inputs
Inclusive Inputs (Large preview)

Starting off with the basics of WAI, ARIA, and WCAG, the article explores how to make inputs more accessible. The tips can be implemented without changing the user interface, and, as Oscar puts it: “If in doubt, just do it. Nobody will notice. Except some of your users. And they will thank you for it.”

Accessible App-Wide Keyboard Navigation

A well-thought-out concept for keyboard navigation benefits everyone: It enables people who can’t comfortably use a mouse, assists screen reader users in interacting with an application, and it provides power users with more shortcuts to work as efficiently as possible. Usually, keyboard support is limited to specific shortcuts, but the team at Discord decided to go a step further with their application and expand keyboard support to, well, everything.

How Discord Implemented App-Wide Keyboard Navigation
How Discord Implemented App-Wide Keyboard Navigation (Large preview)

The case study “How Discord Implemented App-Wide Keyboard Navigation” shares valuable insights into how they tackled the task — and the challenges they faced along the way, of course. One turned out to be particularly difficult: How to consistently indicate where focus is on the page? As existing solutions for Focus Rings didn’t work out, the team had to build their own solution from scratch and made the code open source. If you’re facing a similar challenge, this one’s for you.

Is it still a good idea to design mega-drop-downs opening on hover? Probably not. Hover menus have plenty of usability and accessibility issues, as they are inconsistent, confusing and of course need an alternative solution for mobile devices. In fact, Mark Root-Wiley suggests that it’s about time to drop hover menus in favor of unambiguous and accessible click menus.

(Large preview)

In his article, Mark goes into fine details of how to build an accessible click menu, along with useful pointers and references from his research. The idea is to start building the menu as a CSS-only hover menu that uses li:hover > ul and li:focus-within > ul to show the submenus. Then, we use JavaScript to create the <button> elements, set the aria attributes, and add the event handlers. The final result is available as a code example on CodePen and as a GitHub repo. This should be a good starting point for your menu as well.

Accessible Modals

You might have a simple modal or overlay on the page, perhaps to confirm customer’s input, or to show a couple of photos in a gallery, or just to confirm user’s preferences. In all these cases, building an accessible modal will turn out to become quite an adventure, also know as a focus trap.

As Eric Bailey explains in detail, you’ll need to identify the bounds of the trapped content, including the first and last focusable item, then remove everything that isn’t within it, move focus into the trapped content, listen for events that escape the boundary, restore previous state and move focus back to the interactive element that triggered the trapped content.

Accessible Modals aren’t easy to build. Eric Bailey explains in detail how it works
Accessible Modals aren’t easy to build. Eric Bailey explains in detail how it works. (Large preview)

Ideally, we’d use something as simple as the dialog element in HTML, but unfortunately it has massive accessibility issues. With the Shadow DOM, managing focus isn’t easy either. We can use the inert attribute to remove, and then restore the ability of interactive elements to be discovered and focused. For older browsers, we can use inert polyfills from Google Chrome and from WICG.

  • Scott O’Hara’s accessible-modal-window is a reliable fully accessible script to use.
  • Kitty Giraudel will shortly be releasing a11y-dialog Next, a lightweight (1.6 KB) script that traps and restores focus, toggles aria–* attributes and closes dialog on overlay click and Escape. It’s important not to confuse this version with previous version (6.1.0) as it relies on the <dialog> which which still lacks in implementation support, and has lingering accessibility issues.
  • You could look into Parvus, a simple, accessible, open-source image lightbox without dependencies. In a typical scenario, we’d have an image linked to larger version of the image. With Parvus,, it’s enough to add a class .lightbox to the link wrapping around an image, and the script does everything else for you automatically.

Support User Preferences With prefers-reduced-*

Not every user is the same, and while some users love animations, others may have medical issues concerning motion. The prefers-reduced-motion media query lets you toggle animations on and off, but there are even more solutions to manage animations depending on a user’s preference. In his blog post, Elijah Manor addresses different techniques such as @media, matchMedia, and a custom React hook to address CSS, SVG SMIL, and JavaScript animations.

Use the prefers-reduced-motion media query to toggle CSS and JavaScript animations
Use the prefers-reduced-motion media query to toggle CSS and JavaScript animations (Large preview)

When it comes to making your content accessible to everyone, there’s another prefers-reduced-* media query that is worth knowing about — even though it isn’t supported by browsers yet (but you can emulate it in Polypane and Chromium browsers): prefers-reduced-data. It indicates when a user wants to use as little data as possible — if their connection is slow, for example, or if data is limited.

Especially on pages with a large amount of navigation, moving between sections or around the page can be frustrating and annoying. That’s where “Skip” links can be very helpful. Unfortunately, it’s not uncommon to see “Skip” links being implemented but hidden away with display: none, and as such, unavailable to anybody (including screen reader users and keyboard users).

(Large preview)

In How To Create a “Skip content” Link, Paul Ryan provides a step-by-step tutorial on how to implement an accessible skip content link. Basically we use CSS transform to push the skip link off the screen, but bring it back on screen on :focus. In the comments to the article, Eric Bailey also noticed that we could provide skip-links before sections of content that contain lots of interactive items, or items that can be tough to navigate through (such as table of contents and iframes).

Accessible SVGs

Talking about SVGs: what we can do with SVGs today goes way beyond the basic shapes of yesteryear. Not only can we describe SVG icons, but also style and animate them. If true inclusiveness lies beyond patterns — what other factors should we consider when designing and developing accessible SVGs?

That’s exactly the question that Carie Fisher is answering in her piece on Accessible SVGs: Inclusiveness Beyond Patterns. In the article, Carie takes a closer look at SVG color and contrast, light and dark modes, SVG animation, reduced motion and plenty of tools focused all around accessibility. You’ll also find demos and code examples in the articles, along with detailed explanations and pointers for further reading.

(Large preview)

And if you’d like to dive deeper into the complex world of accessible components — not only related to SVGs — we’ve just published Carie’s piece on accessible code patterns.

Accessible Tabs

Your interface might be using tab panels, but to keep the content of these tabs accessible to keyboard-users and screen reader users, we need a very careful and deliberate exposition of visual design and ARIA semantics. In Tabbed Interfaces, Heydon Pickering goes into detail trying to figure out just the right solution to respect keyboard behavior and focus management. He suggests to progressively enhance sections into tab panels (code example) (thanks to Daniela Kubesch for the tip!).

Shows how a user can choose a new tab with the arrow keys or press tab to enter the tab panel and focus a link
Shows how a user can choose a new tab with the arrow keys or press tab to enter the tab panel and focus a link (Large preview)

As Adam Silver notes, screen reader users who are less savvy may not know to use arrow keys to switch tabs. There’s an argument to make all the tabs focusable in the normal tab sequence with little intervention from developers to change the way tabs work via keyboard.

Alternatively, TabPanelWidget is a responsive and accessible solution for tabs. It relies on plain old semantic HTML, and turns into an accordion whenever the tabs cannot fit entirely (thanks to ResizeObserver but there’s a polyfill for browsers that don’t support it yet).

Accessible Tabs
Accessible Tabs (Large preview)

The script is not only a semantic and accessible solution, but also a responsive and versatile one to help you create Tabpanel and accordion widgets for the web. It is keyboard-friendly and available as a vanilla JS library (or as a widget for Vue, React and Angular).

Accessible Tables

There are plenty of accessibility issues related to tables, but the biggest challenges is to turn a visual representation into a linear series that will be read aloud meaningfully by a screen reader, without omitting any important information. Fortunately, Adrian Roselli has been spending a lot of time exploring the challenges and solutions of accessible tables.

(Large preview)

In his post on accessible tables, Adrian suggests to wrap the table in a <div> with role="region", aria-labelledby and tabindex="0" to ensure that a keyboard-only user can tab to the container, that the table receives focus and <caption> within table to ensure that it’s properly announced to screen readers. Adrian also provides a code example for a responsive table, as well as tables with expandable rows, sortable table and fixed table headers.

How Screen Readers Navigate Data Tables

Have you ever tried to navigate a table with a screen reader? If not, you should check out Leonie Watson’s article on how screen readers navigate data tables. It shares precious insights and shows what matters to create frustration-free tables that can be used by anyone.

Data table showing the average daily tea and coffee consumption
Data table showing the average daily tea and coffee consumption (Large preview)

In the post, Leonie uses NVDA to move to a table, navigate its content, and find specific information. The appropriate HTML elements (or ARIA roles) inform her about the characteristics of the table and give her access to keyboard commands specifically for navigating the table’s content.

An interesting takeaway: Keyboard focus and screen reader focus are not the same thing. Contrary to what you might have heard, you do not need to make each cell of a table focusable with a keyboard to aid navigation. If the content inside the cell is non-interactive, you’ll likely make keyboard users work much harder to navigate the table than you intended. You can also watch a Smashing TV video with Léonie on How A Screen Reader User Accesses The Web (73 mins).

Accessible Toggle Switches

Whenever our forms provide a binary selection to our customers — on/off, dark/light mode etc. — we could use a toggle switch. The switch needs to serve a couple of purposes: it needs to clearly explain the current selection (and that’s clear not that often at all!), it needs to explain that there are two options, and it needs to be obvious enough for customers to understand how to switch between them. When Sara Soueidan was looking into how to build a toggle switch, she of course spent quite a bit of time looking into how to build an accessible toggle switch.

The Medium app’s theme customizer is a simple popup panel that includes a simple switch for switching from light to dark mode and vice versa. From Sara’s article.
The Medium app’s theme customizer is a simple popup panel that includes a simple switch for switching from light to dark mode and vice versa. From Sara’s article. (Large preview)

Sara’s solution uses two radio buttons, each with its own label, announced to assistive technologies as a couple of separate options, accessible via keyboard, and has no additional ARIA or JS requirements to function. The outcome is a theme switching toggle code example, and you can also take a look at Scott O’Hara’s code example.

It’s important to note that Sara’s radio button toggle switch is accessible because of its two labels. So if a toggle switch does not have two labels, this would not be a pattern to use. You can find markup patterns for toggle switches in Scott’s repo. (thanks to Scott O’Hara for the tip!).

Accessible Tooltips and Toggletips

A component that’s closely related to icon buttons is a tooltip. Literally “tips for tools”, they are little pieces of information that explain the purpose of a control, or a visual, that otherwise could be misunderstood. Every time we want to explain why we need a particular piece of personal information in a checkout, that’s where we’ll probably be using a good old tooltip. So, how do we get them right?

The left example says notifications and has the caption primary label. The right example has the longer view notifications and manage settings text and is captioned auxiliary description
The left example says notifications and has the caption primary label. The right example has the longer view notifications and manage settings text and is captioned auxiliary description. From: Inclusive Tooltips and Toggletips by Heydon Pickering. (Large preview)

Heydon Pickering’s Inclusive Tooltips and Toggletips provides a very thorough overview of pretty much everything needed to build an accessible tooltip. That means deciding whether the tip’s content should be provided as the label or description and choose ARIA properties accordingly, not relying on title attributes and avoiding putting interactive content such as close and confirm buttons or links in tooltips.

Accessible Video/Audio Players

It’s not uncommon to see viewers frequently using captions when watching a short clip or a lengthy movie these days. We might be consuming the video in a noisy environment, or perhaps we can better understand written language, or perhaps we are currently busy with something else and need to look up something quickly without having to resort to headphones. Beyond that, how often do we use keyboard’s <space> to prompt a pause, or key arrows to move back and forward? Still, many video players and custom solutions don’t provide this functionality out of the box.

(Large preview)

Accessible HTML5 Media Players provides an overview of accessible audio and video players. There are plenty of great open-source options, e.g. AblePlayer seems to be one of the reliable ones. It includes a full set of player controls that are keyboard-accessible, properly labelled for screen reader users, and controllable by speech recognition users, features high contrast, supports closed captions and subtitles, chapters, text-based audio description, an interactive transcript feature and automatic text highlighting. It supports YouTube and Vimeo videos. Hower, it depends on jQuery.

Alternatively, you could look into Vime.js as well: fully open-source, lightweight, fully customizable and without third-party dependencies. Other great options like Plyr and Accessible HTML5 Video Player by PayPal are similar. The latter is fully accessible to keyboard-only users and screen reader users, written in vanilla JavaScript, is additionally provided as a React component, and falls back to browser’s native controls if JavaScript is unavailable (thanks for the tip, @jamsandwich!).

Website Features That Annoy Screen Reader Users

A missing alt caption, an auto-playing video, unlabelled buttons, poor use of headings, inaccessible web forms — what might seem like a small issue for sighted users can make the difference between being able to use a website independently or not for blind and visually impaired people. Holly Tuke knows this from her own experience.

Hierarchy of headings - From heading 1 to heading 5
Hierarchy of headings. From heading 1 to heading 5. (Large preview)

To raise awareness for common accessibility issues, Holly summarized five annoying website features she faces as a screen reader user every single day, and, of course, how to fix them. Chris Ashton also published a piece explaining common issues that screen reader users have, which are often neglected in conversations focus on semantics and keyboard-accessibility alone. Little details that make a huge difference (thanks to Alex Chudesnov for the tip!).

But First, Accessibility Support

There are many different ways that assistive technologies interact with browsers and code. Since it’s still not possible to fully automate screen readers and voice control softwares, we are left with having to do manual tests. And that’s where comes into play.

Accessibility Support
Accessibility Support (Large preview)

Originally created by Michael Fairchild, this community-driven website aims to help inform developers about what is accessibility supported. It’s a project that is active and contributions are always welcome, so start testing away. Also, it’s always worth checking the WAI-ARIA authoring practices which describe essential semantics, roles, and ARIA necessary for common components and patterns (thanks to Stephanie Eckles for the tip!).

Accessibility Resources And Checklists

Accessibility is incredibly important, but, unfortunately, often overlooked. The community-driven A11Y Project attempts to make digital accessibility easier, providing designers and developers with the know-how they need to build beautiful, accessible, and inclusive experiences.

The A11Y Project
The A11Y Project (Large preview)

From the basic principles behind accessible design to conducting an accessibility audit, and cultivating community, The A11Y Project takes a 360 degree look at the topic. You’ll find articles just like quick tips, tips on books to read, newsletters to follow, as well as handy tools, groups committed to accessibility, and much more.

Repository Of Accessibility Tools

Do you ever get that itching feeling of forgetting something before shipping a project? Well, checklists are known to be the key to keeping an overview of things that need to be done and taken care of before the final showdown. When it comes to accessibility, there’s a growing list of tools and resources that are bound to help you keep an eye on things: A11y Resources.

Accessibility Tools And Resources
Accessibility Tools And Resources (Large preview)

Curated by Hannah Milan, this list was initially created to keep track of more than 200+ hand-curated accessibility plugins, tools, articles, case studies, design patterns, design resources, accessibility standards, and even checklists. Of course, you can always submit a tool if you see anything missing.

Wrapping Up

There are definitely dozens and hundreds of important guidelines by incredible people in the accessibility community, such as Steve Faulkner with a huge series of articles on semantics and accessibility and Leonie Watson with a huge series of articles on accessibility in general. It’s impossible to list everyone, but we are sincerely grateful to every contribution.

We probably have missed some important and valuable techniques and resources! So please leave a comment and refer to them — we’d love to update this post and keep it up-to-date for us all to be able to get back to it and build reliable, accessible components faster.

We sincerely hope that these tools and techniques will prove to be useful in your day-to-day work — and most importantly help you avoid some time-consuming, routine tasks.

Stay accessible!

Thank you! ❤️

A huge thanks to @jamsandwich, Courtney Heitman, Stephanie Eckles, Adam Silver, Daniela Kubesch, Tanisha Sabherwal, Manuel Matuzović, Vadim Makeev, Kitty Giraudel, Ian James, Juha Lehtonen, Heydon Pickering, Shivani Gupta, Jason Webb, Alex Kallinikos, Scott O’Hara, Sara Soueidan, Sasha Chudesnov, Adam Liptrot, Holger Bartel, Kim Johannesen and everybody else who has been passionately working all around accessibility for the contributions to this article. Community matters.

More On Accessibility

Smashing Editorial

Source link

TIL You can view Twitch client code via DevTools

TIL You can view Twitch client code via DevTools

TIL You can view Twitch client code via DevTools

Perhaps this is normal but I was surprised that I can see the Twitch JS source via Devtools in my Chrome browser. Is this because they left the source-maps in their build?

Interesting to see how a major website structures their code.

submitted by /u/tritiy

Source link

Nailing That Cool Dissolve Transition

Nailing That Cool Dissolve Transition

We’re going to create an impressive transition effect between images that’s, dare I say, very simple to implement and apply to any site. We’ll be using the kampos library because it’s very good at doing exactly what we need. We’ll also explore a few possible ways to tweak the result so that you can make it unique for your needs and adjust it to the experience and impression you’re creating.

Take one look at the Awwwards Transitions collection and you’ll get a sense of how popular it is to do immersive effects, like turning one media item into another. Many of those examples use WebGL for the job. Another thing they have in common is the use of texture mapping for either a displacement or dissolve effect (or both).

To make these effects, you need the two media sources you want to transition from and to, plus one more that is the map, or a grid of values for each pixel, that determines when and how much the media flips from one image to the next. That map can be a ready-made image, or a <canvas> that’s drawn upon, say, noise. Using a dissolve transition effect by applying a noise as a map is definitely one of those things that can boost that immersive web experience. That’s what we’re after.

Setting up the scene

Before we can get to the heavy machinery, we need a simple DOM scene. Two images (or videos, if you prefer), and the minimum amount of JavaScript to make sure they’re loaded and ready for manipulation.

      <canvas id="target">
        <img id="source-from" src="" alt="My first image" />
        <img id="source-to" data-src="" alt="My second image" />

This will give us some minimal DOM to work with and display our scene. The stage is ready; now let’s invite in our main actors, the two images:

// Notify when our images are ready
function loadImage (src) {
  return new Promise(resolve => {
    const img = new Image();
    img.onload = function () {
    img.src = src;
// Get the image URLs
const imageFromSrc = document.querySelector('#source-from').src;
const imageToSrc = document.querySelector('#source-to').dataset.src;
// Load images  and keep their promises so we know when to start
const promisedImages = [

Creating the dissolve map

The scene is set, the images are fetched — let’s make some magic! We’ll start by creating the effects we need. First, we create the dissolve map by creating some noise. We’ll use a Classic Perlin noise inside a turbulence effect which kind of stacks noise in different scales, one on top of the other, and renders it onto a <canvas> in grayscale:

const turbulence = kampos.effects.turbulence({ noise: kampos.noise.perlinNoise });

This effect kind of works like the SVG feTurbulence filter effect. There are some good examples of this in “Creating Patterns With SVG Filters” from Bence Szabó.

Second, we set the initial parameters of the turbulence effect. These can be tweaked later for getting the specific desired visuals we might need per case:

// Depending of course on the size of the target canvas
const WIDTH = 854;
const HEIGHT = 480;
const CELL_FACTOR = 2;

turbulence.frequency = {x: AMPLITUDE, y: AMPLITUDE};
turbulence.octaves = 1;
turbulence.isFractal = true;

This code gives us a nice liquid-like, or blobby, noise texture. The resulting transition looks like the first image is sinking into the second image. The CELL_FACTOR value can be increased to create a more dense texture with smaller blobs, while the octaves=1 is what’s keeping the noise blobby. Notice we also normalize the amplitude to at least the larger side of the media, so that texture is stretched nicely across our image.

Next we render the dissolve map. In order to be able to see what we got, we’ll use the canvas that’s already in the DOM, just for now:

const mapTarget = document.querySelector('#target'); // instead of document.createElement('canvas');
mapTarget.width = WIDTH;
mapTarget.height = HEIGHT;

const dissolveMap = new kampos.Kampos({
  target: mapTarget,
  effects: [turbulence],
  noSource: true


We are going to pause here and examine how changing the parameters above affects the visual results. Now, let’s tweak some of the noise configurations to get something that’s more smoke-like, rather than liquid-like, say:

const CELL_FACTOR = 4; // instead of 2

And also this:

turbulence.octaves = 8; // instead of 1

Now we have a more a dense pattern with eight levels (instead of one) superimposed, giving much more detail:

Fantastic! Now back to the original values, and onto our main feature…

Creating the transition

It’s time to create the transition effect:

const dissolve = kampos.transitions.dissolve(); = mapTarget;
dissolve.high = 0.03; // for liquid-like effect

Notice the above value for high? This is important for getting that liquid-like results. The transition uses a step function to determine whether to show the first or second media. During that step, the transition is done smoothly so that we get soft edges rather than jagged ones. However, we keep the low edge of the step at 0.0 (the default). You can imagine a transition from 0.0 to 0.03 is very abrupt, resulting in a rapid change from one media to the next. Think of it as clipping.

On the other hand, if the range was 0.0 to 0.5, we’d get a wider range of “transparency,” or a mix of the two images — like we would get with partial opacity — and we’ll get a smoke-like or “cloudy” effect. We’ll try that one in just a moment.

Before we continue, we must remember to replace the canvas we got from the document with a new one we create off the DOM, like so:

const mapTarget = document.createElement('canvas');

Plug it in, and… action!

We’re almost there! Let’s create our compositor instance:

const target = document.querySelector(‘#target’);
const hippo = new kampos.Kampos({target, effects: [dissolve]});

And finally, get the images and play the transition:

Promise.all(promisedImages).then(([fromImage, toImage]) => {
  hippo.setSource({media: fromImage, width, height}); = toImage; => {
    // a sin() to play in a loop
    dissolve.progress = Math.abs(Math.sin(time * 4e-4)); // multiply time by a factor to slow it down a bit


Special effects

OK, we got that blobby goodness. We can try playing a bit with the parameters to get a whole different result. For example, maybe something more smoke-like:

const CELL_FACTOR = 4;
turbulence.octaves = 8;

And for a smoother transition, we’ll raise the high edge of the transition’s step function:

dissolve.high = 0.3;

Now we have this:

And, for our last plot twist, let’s also animate the noise itself! First, we need to make sure kampos will update the dissolve map texture on every frame, which is something it doesn’t do by default:

dissolve.textures[1].update = true;

Then, on each frame, we want to advance the turbulence time property, and redraw it. We’ll also slow down the transition so we can see the noise changing while the transition takes place: => {
  turbulence.time = time * 2;
  // Notice that the time factor is smaller here
  dissolve.progress = Math.abs(Math.sin(time * 2e-4));

And we get this:

That’s it!

Exit… stage right

This is just one example of what we can do with kampos for media transitions. It’s up to you now to mix the ingredients to get the most mileage out of it. Here are some ideas to get you going:

  • Transition between site/section backgrounds
  • Transition between backgrounds in an image carousel
  • Change background in reaction to either a click or hover
  • Remove a custom poster image from a video when it starts playing

Whatever you do, be sure to give us a shout about it in the comments.

Source link

Create ASP.NET Core Web Application With Visual Studio Code

Create ASP.NET Core Web Application With Visual Studio Code

In this article, we will see how to create an empty ASP.NET Web Application with .NET CLI and Visual Studio Code. In the previous article of this series, we already covered the below articles:

I recommend you to go through these articles first if you are new to this series or new to .NET Core technology.

Setting Up

In order to create the .NET Core application, we must have .NET Core SDK installed in the system. (In this example, I am using .NET Core 3.1). Go to the Microsoft official website in order to download the .NET Core SDK.

.NET Core in Microsoft Store

Once SDK is installed, Open Visual Studio Code Editor. If you don’t have it already installed in your system, then go to the Microsoft official site in order to download it free of cost. Once downloaded and installed, Go to the Terminal menu, click on New Terminal.

Terminal > New Terminal

You will see the terminal as shown in the below image.


Getting Started

Change the directory to the location where you want to create your first ASP.NET Core Web Application with .NET CLI. In my case, I already created a folder on the desktop (and named it Project).

Changing directory location

Run the dotnet command in the terminal. If .NET Core is already installed in your system, then you will see the options as shown in the below image:

Running dotnet

Run the dotnet --version command in order to check the version of .NET Core SDK installed in your system. In my system, I have .NET Core 3.1.402 Version.

Checking version

You can use --help in order to check the options and commands in case of any help required. Use the dotnet new command in order to create a new project and pass the short name for the type of project/solution you want to create. You can use the --help in order to see the available projects as well as options related to .Net Core CLI.

dotnet new --help

As you can see, we can create several kinds of projects through .NET Core CLI. In this example, I am going to create an ASP.NET Core Empty project.

Project List

Run dotnet new web --name <NAME_OF_PROJECT> in order to create an empty ASP.NET Core web application. On executing the command, the ASP.NET Core Empty template will be created followed by the dotnet restore command.

dotnet restore

Now change the directory to the project location. In my case, I have created a project, i.e., AspNetCoreEmptyWebApp so I am changing the directory through the terminal to that folder as it contains the .csproj file which is required to run the .NET Core project through the CLI. Once the directory is changed, run dotnet run command in the terminal in order to launch the web application.

Launching web app

Once the application is launched successfully, copy or click on the URL on which your application is running. You can see Hello World! on the screen which is basically coming from the startup.cs class.

Hello World! localhost:5000

Visual Studio

Now let’s open that project into Visual Studio Code. We can directly open the folder through the File menu and clicking on the open folder menu option or by running code .in the terminal as shown in the below image.

code . command

On opening the project for the first time, A message is prompted to add the required assets to build and debug the application. Click on Yes. Upon clicking on Yes, a folder, i.e., .vscode will be created in the project.

Missing Elements Prompt

You can see that our ASP.NET Core project is opened in the Visual Studio Code editor with the structure as shown in the below image. (Please check Project Structure in ASP.NET Core 3.1 Web Application in case you want to understand the project as well as files structure and its role.)

Project Structure

Now, go to the Run menu, click on Run without debugging in order to run the application without debugging it. In a few seconds application is launched with the ports specified in the launchsettings.json file.

Run Without Debugging

Debug Console


In case you want to debug the application, add a breakpoint where you want to test and debug the application.

Add a breakpoint

And then go to the Run menu and then click on the Start Debugging option. Once the application reached the breakpoint, it will be highlighted (in a similar manner as in Visual Studio IDE). You can do step in, step out, add items to the watch window, etc.

Run > Start Debugging



I hope this article will help you in getting started with creating and managing the ASP.NET Core web application with .NET CLI and launching and debugging it through Visual Studio Code.

Source link

ShopTalk Patreon

ShopTalk Patreon

Dave and I launched a Patreon for ShopTalk Show. You get two completely priceless things for backing us:

  1. That great feeling you’re supporting the show, which has costs like editing, transcribing, developing, and hosting.
  2. Access to our backer-only Discord.

I think the Discord might be my favorite thing we ever done. Sorry if I’m stoking the FOMO there, but just saying, it’s a good gang. My personal intention is to be helpful in there, but everyone else is so helpful themselves that I’ve actually learned more than I’ve shared.

Direct Link to ArticlePermalink

The post ShopTalk Patreon appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Source link

HTML Inputs and Labels: A Love Story

HTML Inputs and Labels: A Love Story

Most inputs have something in common — they are happiest with a companion label! And the happiness doesn’t stop there. Forms with proper inputs and labels are much easier for people to use and that makes people happy too.

A happy label and input pair

In this post, I want to focus on situations where the lack of a semantic label and input combination makes it much harder for all sorts of people to complete forms. Since millions of people’s livelihoods rely on forms, let’s get into the best tips I know for creating a fulfilling and harmonious relationship between an input and a label.

Content warning: In this post are themes of love and relationships.

The love story starts here! Let’s cover the basics for creating happy labels and inputs.

How to pair a label and an input

There are two ways to pair a label and an input. One is by wrapping the input in a label (implicit), and the other is by adding a for attribute to the label and an id to the input (explicit).

Think of an implicit label as hugging an input, and an explicit label as standing next to an input and holding its hand.

  <input type="text" name="name" />

An explicit label’s for attribute value must match its input’s id value. For example, if for has a value of name, then id should also have a value of name.

<label for="name">Name: </label>
<input type="text" id="name" name="name" />

Unfortunately, an implicit label is not handled correctly by all assistive technologies, even if for and id attributes are used. Therefore, it is always the best idea to use an explicit label instead of an implicit label.

<!-- IMPLICIT LABEL (not recommended for use) - the label wraps the input. -->
  <input type="text" name="name" />

<!-- EXPLICIT LABEL (recommended for use) - the label is connected to an input via "for" and "id" -->
<label for="explicit-label-name">Name: </label>
<input type="text" id="explicit-label-name" name="name" />

Each separate input element should only be paired with one label. And a label should only be paired with one input. Yes, inputs and labels are monogamous. ♥️

Note: There’s one sort of exception to this rule: when we’re working with a group of inputs, say several radio buttons or checkboxes. In these cases, a <legend> element is used to group certain input elements, such as radio buttons, and serves as the accessible label for the entire group.

Not all inputs need labels

An input with a type="submit" or type="button" does not need a label — the value attribute acts as the accessible label text instead. An input with type="hidden" is also fine without a label. But all other inputs, including <textarea> and <select> elements, are happiest with a label companion.

What goes in a label

The content that goes inside of a label should:

  • Describe its companion input. A label wants to show everyone that it belongs with its input partner.
  • Be visible. A label can be clicked or tapped to focus its input. The extra space it provides to interact with the input is beneficial because it increases the tap or click target. We’ll go into that more in just a bit.
  • Only contain plain text. Don’t add elements like headings or links. Again, we’ll go into the “why” behind this further on down.

One useful thing you can do with the content in a label is add formatting hints. For example, the label for <input type="date" id="date"> will be <label for="date"> as we’d expect. But then we can provide a hint for the user that the date needs to be entered in a specific format, say DD-DD-YYYY, in the form of a <span> between the label and input that specifies that requirement. The hint not only specifies the date format, but has an id value that corresponds to an aria-describedby attribute on the input.

<!-- Describes what the input is for - should be plain text only -->
<label for="date">Start date</label>
<!-- Describes additional information, usually about formatting -->
<span id="date-format">(DD-MM-YYYY):</span>
<input type="date" id="date" aria-describedby="date-format" min="2021-03-01" max="2031-01-01" />

This way, we get the benefit of a clear label that describes what the input is for, and a bonus hint to the user that the input needs to be entered in a specific format.

Best practices for a healthy relationship

The following tips go beyond the basics to explain how to make sure a label and input are as happy as can be.

Do: Add a label in the right place

There is a WCAG success criterion that states the visual order of a page should follow the order in which elements appear in the DOM. That’s because:

A user with low vision who uses a screen magnifier in combination with a screen reader may be confused when the reading order appears to skip around on the screen. A keyboard user may have trouble predicting where focus will go next when the source order does not match the visual order.

Think about it. If we have some standard HTML where the label comes before the input:

<label for="orange">Orange</label>
<input type="checkbox" id="orange" name="orange">

That places the label before the input in the DOM. But now let’s say our label and form are inside a flexible container and we use CSS order to reverse things where the input visually comes before the label:

label { order: 2; }
input { order: 1; }

A screen reader user, who is navigating between elements, might expect the input to gain focus before the label because the input comes first visually. But what really happens is the label comes into focus instead. See here for the difference between navigating with a screen reader and a keyboard.

So, we should be mindful of that. It is conventional to place the label on the right-hand side of the input for checkboxes and radio buttons. This can be done by placing the label after the input in the HTML, ensuring the DOM and visual order match.

  <!-- Checkbox with label on the right -->
    <input type="checkbox" id="orange" name="orange">
    <label for="orange">Orange</label>
  <!-- Radio button with label on the right -->
    <input type="radio" id="banana" name="banana">
    <label for="banana">Banana</label>
  <!-- Text input with label on the left -->
    <label for="apple">How do you like them apples?</label>
    <input type="text" id="apple" name="apple">

Do: Check inputs with a screen reader

Whether an input is written from scratch or generated with a library, it is a good idea to check your work using a screen reader. This is to make sure that:

  • All relevant attributes exist — especially the matching values of the for and id attributes.
  • The DOM matches the visual order.
  • The label text sounds clear. For example, “dd-mm-yyyy” is read out differently to its uppercase equivalent (DD-MM-YYYY).
Screen reader reading out a lower case and upper case date input hint.
Just because the letters are the same doesn’t mean that they get read the same way by a screen reader.

Over the last few years, I have used JavaScript libraries, like downshift, to build complex form elements such as autocomplete or comboboxes on top of native HTML ones, like inputs or selects. Most libraries make these complex elements accessible by adding ARIA attributes with JavaScript.

However, the benefits of native HTML elements enhanced using JavaScript are totally lost if JavaScript is broken or disabled, making them inaccessible. So check for this and provide a server-rendered, no-JavaScript alternative as a safe fallback.

Check out these basic form tests to determine how an input and its companion label or legend should be written and announced by different screen readers.

Do: Make the label visible

Connecting a label and an input is important, but just as important is keeping the label visible. Clicking or tapping a visible label focuses its input partner. This is a native HTML behavior that benefits a huge number of people.

Imagine a label wanting to proudly show its association with an input:

A visible happy label proudly showing off its input partner.
A label really wants to show off its input arm candy. 💪🍬

That said, there are going to be times when a design calls for a hidden label. So, if a label must be hidden, it is crucial to do it in an accessible way. A common mistake is to use display: none or visibility: hidden to hide a label. These CSS display properties completely hide an element — not only visually but also from screen readers.

Consider using the following code to visually hide labels:

/* For non-natively-focusable elements. For natively focusable elements */
/* Use .visually-hidden:not(:focus):not(:active) */
.visually-hidden {
  border-width: 0 !important;
  clip: rect(1px, 1px, 1px, 1px) !important;
  height: 1px !important;
  overflow: hidden !important;
  padding: 0 !important;
  position: absolute !important;
  white-space: nowrap !important;
  width: 1px !important;

Kitty Giraudel explains in depth how to hide content responsibly.

What to Avoid

To preserve and maintain a healthy relationship between inputs and labels, there are some things not to do when pairing them. Let’s get into what those are and how to prevent them.

Don’t: Expect your input to be the same in every browser

There are certain types of inputs that are unsupported In some older desktop browsers. For example, an input that is type="date" isn’t supported in Internet Explorer (IE) 11, or even in Safari 141 (released September 2020). An input like this falls back to type="text". If a date input does not have a clear label, and it automatically falls back to a text input in older browsers, people may get confused.

Don’t: Substitute a label with a placeholder

Here is why a placeholder attribute on an input should not be used in place of a label:

  • Not all screen readers announce placeholders.
  • The value of a placeholder is in danger of being cut-off on smaller devices, or when a page is translated in the browser. In contrast, the text content of a label can easily wrap onto a new line.
  • Just because a developer can see the pale grey placeholder text on their large retina screen, in a well-lit room, in a distraction-free environment, doesn’t mean everyone else can. A placeholder can make even those with good vision scrunch their eyes up and eventually give up on a form.
An input on a mobile device where the placeholder text is cut off.
Make sure this is somewhere I can what? It’s hard to tell when the placeholder gets cut off like that.
An input where the translated placeholder is cut off.
Work on a multi-lingual site? A translated placeholder can get cut off even though the English translation is just fine. In this case, the translated placeholder should read “Durchsuchen Sie die Dokumentation.”
  • Once a character is entered into an input, its placeholder becomes invisible — both visually and to screen readers. If someone has to back-track to review information they’ve entered in a form, they’d have to delete what was entered just to see the placeholder again.
  • The placeholder attribute is not supported in IE 9 and below, and disappears when an input is focused in IE 11. Another thing to note: the placeholder color is unable to be customized with CSS in IE 11.

Placeholders are like the friend that shows up when everything is perfect, but disappears when you need them most. Pair up an input with a nice, high-contrast label instead. Labels are not flaky and are loyal to inputs 100% of the time.

The Nielsen Norman Group has an in-depth article that explains why placeholders in form fields are harmful.

Don’t: Substitute a label with another attribute or element

When no label is present, some screen readers will look for adjacent text and announce that instead. This is a hit-and-miss approach because it’s possible that a screen reader won’t find any text to announce.

The below code sample comes from a real website. The label has been substituted with a <span> element that is not semantically connected to the input.

  <span>Card number</span>
    <input type="text" value="" id="cardNumber" name="cardNumber" maxlength="40">

The above code should be re-written to ensure accessibility by replacing the span with a label with for="cardNumber" on it. This is by far the most simple and robust solution that benefits the most people.

While a label could be substituted with a span that has an id with a value matching the input’s aria-labelledby attribute, people won’t be able to click the span to focus the input in the same way a label allows. It is always best to harness the power of native HTML elements instead of re-inventing them. The love story between native input and label elements doesn’t need to be re-written! It’s great as-is.

Don’t: Put interactive elements inside labels

Only plain text should be included inside a label. Avoid inserting things such as headings, or interactive elements such as links. Not all screen readers will announce a label correctly if it contains something other than plain text. Also, if someone wants to focus an input by clicking its label, but that label contains a link, they may click the link by mistake.

    <!-- Don't do this -->
    <input type="checkbox" id="t-and-c" name="name" />
    <label for="t-and-c">I accept the <a href="">terms and conditions</a></label>
    <!-- Try this -->
    <input type="checkbox" id="t-and-c2" name="name" />
    <label for="t-and-c2">I accept the terms and conditions.</label>
    <span>Read <a href="">terms and conditions</a></span>

Real-life examples

I always find that real-life examples help me to properly understand something. I searched the web and found examples of labels and inputs from a popular component library and website. Below, I explain where the elements fall short and how they can be improved to ensure a better pairing.

Component library: Material

MaterialUI is a React component library based on Google’s design system. It includes a text input component with a floating label pattern that has become a popular go-to for many designers and developers:

The floating label pattern starts with the label in the placeholder position that moves the label to its proper place above the field. The idea is that this achieves a minimal design while solving the issue of placeholders disappearing when typing.

Clicking on the input feels smooth and looks great. But that’s the problem. Its qualities are mostly skin-deep.

At the time of writing this post, some issues I found with this component include:

  • There is no option to have the label outside of the input in order to offer an increased interactive area for focusing the input.
  • There is an option to add a hint like we saw earlier. Unfortunately, the hint is only associated with the input via proximity and not through a matching id and aria-describedby. This means that not all screen readers will be able to associate the helper message with the input.
  • The label is behind the input in the DOM, making the visual order is incorrect.
  • The empty input looks look like it is already filled out, at least as long as it is not active.
  • The label slides up when the input is clicked, making it unsuitable for those who prefer reduced motion.

Adam Silver also explains why float labels are problematic and gets into a detailed critique of Material’s text input design.

Website: Huffpost

The Huffpost website has articles containing a newsletter subscription form:

Huffpost newsletter signup form
This form looks quite nice but could be improved

At the time of writing this blog post, the email input that Huffpost uses could benefit from a number of improvements:

  • The lack of a label means a smaller click or tap target. Instead of a label there is an aria-label attribute on the input.
  • The font size of the placeholder and input values are a tiny 11px, which can be hard to read.
  • The entire input disappears without JavaScript, meaning people have no way to sign up to the newsletter if JavaScript is disabled or broken.

A surprising number of people struggle to enter information into poorly-constructed inputs. That list includes people with cognitive, motor and physical disabilities, autism spectrum disorders, brain injuries, and poor vision. Other people who struggle include those in a hurry, on a poor connection, on a small device, on an old device, and unfamiliar with digital forms, among many others.

Additionally, there are numerous reasons why JavaScript might break or be switched off in a browser, meaning inputs become dysfunctional or completely inaccessible. There are also people who are fully capable of viewing a web page but who may choose to use a keyboard along with a screen reader.

The message I want to get across is that happy label and input pairs are crucial. It doesn’t matter if your form is beautiful if it is unusable. I can bet that almost everyone would rather fill out an ugly but easy-to-use form rather than a pretty one that causes problems.


I want to warmly thank the following people for helping me with this post: Eric Eggert, Adam Silver, Dion Dajka, and Kitty Giraudel. Their combined accessibility knowledge is a force to be reckoned with!

  • 1 The datepicker is actually well-supported in iOS 14 and very nice. One would imagine that a macOS version has got to be on the horizon.

Source link

lcp core web vitals scoring graph

Improve Largest Contentful Paint (LCP) With A JS + CSS Trick

Ever since Google announced that Core Web Vitals would be incorporated into their ranking algorithm, developers everwhere are sweating coffee trying to find ways to improve those nutoriously difficult metrics.

I’m definitely not an exception. While working on a recent website launch, I took on the challenge of trying to get these metrics into Google’s “Good” rating. But this is a feat that’s significantly easier said than done – especially if you’re working with a CMS like WordPress, and even moreso if you’re using a page builder to build the site.

If you prefer a video walkthrough of the process, watch the video. I’ve added an additional implementation option in the video not covered in this article.

Of all of the metrics that make up Core Web Vitals, Largest Contentful Paint (LCP) was one metric that was much different to optimize for than the others. Where as the other metrics tend to be very tightly tied to general website and server performance, that wasn’t completely the case with LCP.

lcp core web vitals scoring graph

LCP is a bit different in that although it is tied to website and server performance, it’s also impacted by the design of the above the fold content. Our standard performance optimization process fell short of the mark with LCP, despite getting “Good” ratings on the remaining Core Web Vitals metrics.

To troubleshoot LCP, I looked at the reports and also analyzed the site by looking at Lighthouse reports in the browser using Chrome dev tools. What I found was that the culprit for the higher LCP value was a large hero image. Because the hero image was the largest element in the viewport, the delay in loading that hero image casued the LCP value to increase.

above the fold hero image

I tried a number of things including cropping, resizing, and compressing an image specifically just for mobile. I also tried preloading the image. Both of those strategies helped, but failed to really reduce the LCP value much.

Now with images that are below the fold, you can always rely on lazy loading those images to improve your performance. But what lazy loading means is that you’re essentially not loading something until it comes into the viewport. The problem here is that the large hero image is always going to be in the viewport, so be definition it can’t be lazy loaded, so we can’t rely on that method.

After a short recess, I had a creative out-of-the-box solution that I thought might work. We use WP Rocket as part of our performance toolkit, and there was a feature of WP Rocket that I thought I might be able to hack to manipulate the loading sequence in my favor.

WP Rocket to the Rescue – Sort Of

The trick I wanted to try out involved taking advantage of a WP Rocket feature called Delay JavaScript Execution. This feature delays the execution of JavaScript code until a user interacts with the page by scrolling, hovering, or clicking on the page.

wp rocket feature delay js execution

I wrote a single line of JavaScript code that would simply add a class to the HTML element which I could use to defer the loading of elements, like the hero image:


The next step was to remove the background from the hero, and only load it when the .js-user-action class was present on the HTML element – after the user interacts with the page.

    html.js-user-action .hero{
    	background-image: url(‘my-background-image.jpg’);

We still need to do one more thing. Since the background image won’t load until the user interacts with the page, a fallback needs to be added for the hero. In my scenario, I added a background color or gradient that matched the site’s design and color palette.

    	background: linear-gradient(140deg, #004990e6, #00499057)
above the fold image replaced with gradient

This worked exactly how I expected, and because Page Speed Insights and other performance benchmarking tools don’t register user interactions, our LCP finally crossed the threshold to green – going from 3.2s to 2.5s.

Improving the User Experience

Although this accomplishes the goal, it’s not without a cost. The background image will not load until the user interacts with the screen, so something needs to be used as a fallback until the image can be loaded. I asked a few friends to load the page on their phones and tell me if they found anything strange about the page, and none of them noticed anything “off”. What I observed is that the few friends I asked to test this all had their fingers on the screen or quickly touched the screen when the page was loading, so it happened so quickly they didn’t notice. I think most people browses the internet the same way on smartphones, so I actually don’t mind this implementation – but I can see how some might not prefer it.

Striking a Balance

Although this implementation works at accomplishing the goal of improving LCP, some might not be too happy at the idea of a “lazy loaded” hero image. I wanted to find a possible solution that could be a compromise between additional performance and more design cohesiveness.

What I did was create a mobile sized image for the hero, and applied a small guassian blur with Photoshop. The guassian blur creates more pixels that are similar to eachother, which reduces the filesize. The file can also be saved with a much lower quality level which further reduces the size. Because there are more similar or like-pixels, compression tools like Short Pixel are able to compress the image more which further reduces the filesize.

The last step was to add the blurred image to the hero as the starting image, and then “lazy-load” the full resolution image on user interaction – creating an effect of the picture coming into focus. The net result is an implementation which respects the original design more, but still lowers the LCP because the hero image is very small.

Device Targeting

One improvement to this trick that I felt was necessary, was to only implement this deferred loading on mobile devices. After all, Core Web Vitals are actually quite easy to meet on desktop computers with unthrottled, cable/dsl connections.

The problem with hacking the WP Rocket feature is that WP Rocket doesn’t distinguish between desktop and mobile, and will create the same deferred loading on both device types.

After searching online and finding some Stack Overflow JS snippets I could combine or customize, I was able to recreate the WP Rocket feature and tailor it so that it only uses this deferred loading for mobile devices:

user interaction load script screenshot

Stack Overflow Snippets
Detect Mobile Device:

This code can be reduced further if we leverage JavaScript Media Queries.

It would also be much better if we could selectively implement this type of progressively enhanced loading, based on the user’s network connection using the Network Information API. Unfortunately, at the time of writing this article, browser support for the Network Information API is poor so we would need to wait until there is more browser support behind that feature before we could consider using it.


There are other ways to improve LCP that are more conventional, and arguably more acceptable, however I like the idea of knowing there is always an ace up my sleeve that I can pull if the need arises.

Source link

r/webdev - How To Actually Get Web-Dev Clients

How To Actually Get Web-Dev Clients : webdev

For those of you in this group who want to get into freelancing, or even starting your own business in web-development, one of the most common questions I see on here is “How do I actually get clients?”

Rather than reposting the same response to everybody I see asking, I decided to just write an article about it. This is actually going to be a 2-part series, but this first one talks about how to get your first clients, and how to position yourself so that after you get a few under your belt, they keep coming.


r/webdev - How To Actually Get Web-Dev Clients

Source link

r/graphic_design - Suggestions for High Resolution Large Print?

Suggestions for High Resolution Large Print? : graphic_desig…

I recently ordered a 60″x30″ acrylic print from an online place that had good reviews, and prints in 300ppi. It is a fractal, so I wanted it printed as high resolution as possible, so you can look into the details and it would still be crisp. The company can take any size file, so I submitted a large PNG file that was 300dpi at that size.

I just received the print and I’m disappointed. See attached image for the difference between the file and the print.

I contacted the company and they said that the dots and the low resolution I’m seeing are just how the direct to print is done and looks. They suggested HD Metal printing, but I don’t know if that will be any better.

What would you suggest for having the highest resolution, large print with crisp details?

I’m interested in hearing your suggestions for format and companies. Thanks.

r/graphic_design - Suggestions for High Resolution Large Print?

Source link

Tools for Auditing CSS | CSS-Tricks

Tools for Auditing CSS | CSS-Tricks

Auditing CSS is not a common task in a developer’s everyday life, but sometimes you just have to do it. Maybe it’s part of a performance review to identify critical CSS and reduce unused selectors. Perhaps is part of effort to improve accessibility where all the colors used in the codebase evaluated for contrast. It might even be to enforce consistency!

Whatever the case and whenever that moment arrives, I usually reach for some of the tools I‘ll cover in the article. But before that, let’s see what it even means to “audit” CSS in the first place.

Auditing CSS is hard

Generally, code auditing involves analyzing code to find bugs or other irregularities, like possible performance issues. For most programming languages, the concept of auditing code is relatively straightforward: it works or it doesn’t. But CSS is a specific language where errors are mostly ignored by browsers. Then there’s the fact that you could achieve the same style in many different ways. This makes CSS a little tricky to audit, to say the least.

Finding those errors might be prevented by using an extension for your favorite code editor or setting up a linter or code checker. But that is not what I want to show here, and that is not enough. We could still use too many colors, typographic definitions, or z-indexes, all of which could lead to a messy, unmaintainable, unstable CSS codebase.

To truly audit CSS, we would need to dig deeper and find places that are not considered best practices. To find those places, we could use the following tools.

Browser DevTools

Let’s take a look at the Chrome DevTools tools for CSS auditing. I’m using Brave here, which is Chromium-based. You might also want to check out this article by Umar Hansa, who compiled a whole bunch of great DevTool features that released in 2020.

If you like inspecting CSS code manually, there is the Inspect tool. Using that, we could see the CSS code applied to a specific element. Using the “Inspect arrow” we could even see additional details about colors, fonts, size and accessibility.

Grid and Flex inspector

There’s a lot of practical details in the DevTools interface, but my favorite is the Grid and Flex inspector. To enable them, go to the Settings (a little gear icon at the top right of the DevTools), click on Experiments, then enable CSS Grid and Flexbox debugging features. Although this tool is mainly used for debugging layout issues, I sometimes use it to quickly determine if CSS Grid or Flexbox is even used on the page at all.

CSS Overview

Inspecting CSS is pretty basic, and everything needs to be done manually. Let’s look at some more advanced DevTools features.

CSS Overview is one of them. To enable CSS Overview tool, go to the Settings, click on Experiments, and enable CSS Overview option. To open the CSS Overview panel, you could use the CMD+Shift+P shortcut, type “css overview,” then select “Show CSS Overview.” This tool summarizes CSS properties like colors, fonts, contrast issues, unused declarations, and media queries. I usually use this tool to get the “feel” of how good or poor CSS code is. For example, if there are “50 shades of gray” or too many typographic definitions, that means that the style guide wasn’t respected, or one might not even exist.

Note that this tool summarizes the style applied to a specific page, not the whole file.

Coverage panel

The Coverage tool shows the amount and the percentage of code used on the page. To view it, use the CMD+Shift+P shortcut, type “coverage,” select Show Coverage, and click on the “refresh” icon.

You could filter only CSS files by typing “.css” in the URL filter input. I usually use this tool to understand the delivery technique of the site. For example, if I see that the coverage is pretty high, I could assume that the CSS file is generated for each page separately. It may not be critical data to know, but sometimes it helps to understand the caching strategy.

Rendering panel

The Rendering panel is another useful tool. To open the Rendering panel, use CMD+Shift+P again, type “rendering” this time, and choose the “Show Rendering” option. This tool has many options, but my favorite ones are:

  • Paint flashing — shows green rectangles when a repaint event happens. I use it to identify areas that take too much time for rendering.
  • Layout Shift Regions — shows blue rectangles when the layout shift occurs. To make the most of these options, I usually set the “Slow 3G” preset under the “Network” tab. I sometimes record my screen and then slow down the video to find the layout shifts.
  • Frame Rendering Stats — shows the real-time usage of GPU and frames. This tool is handy when identifying heavy animations and scrolling issues.

These tools are something that the regular audit doesn’t imply, but I find it essential to understand if the CSS code is performant and doesn’t drain a device’s energy.

Other options may be more beneficial for debugging issues, like emulation and disabling of various features, forcing the prefers-color-scheme feature or print media type, and disabling local fonts.

Performance Monitor

Another tool for auditing the performance CSS code is the Performance Monitor. To enable it, use CMD+Shift+P again, type “performance monitor,” and select the Show Performance Monitor option. I usually use this tool to see how many recalculations and layouts are triggered when interacting with the page, or when the animation occurs.

Perfomance panel

The Performance panel shows a detailed view of all browser events during page load. To enable the Performance tool, do CMD+Shift+P, type “performance,” select Show Performance, then click the “reload” icon. I usually enable the “Screenshots” and “Web Vitals” options. The most interesting metrics to me are First Paint, First Contentful Paint, Layout Shifts, and Largest Contentful Paint. There is also a pie chart showing the Painting and Rendering time.

DevTools might not be considered a classical auditing tool, but it helps us understand which CSS features are used, the efficiency of the code, and how it performs — all of which are key things to audit.

Online tools

DevTools is just one tool that is packed with a lot of features. But there are other available tools we can use to audit CSS.

Specificity Visualizer

Specificity Visualizer shows the specificity of CSS selectors in the codebase. Simply visit the site and paste in the CSS.

The main chart displays the specificity in relation to the location in the stylesheet. The other two charts show the usage of specificities. I often use this site to find “bad” selectors. For example, if I see many specificities marked as red, I could easily conclude that the code could be better. It is helpful to save the screenshots for reference as you work to improve things.

CSS Specificity Graph Generator

CSS Specificity Graph Generator is a similar tool for visualizing specificity. It shows a slightly different chart that might help you see how your CSS selectors are organized by specificity. As it says on the tool’s page, “spikes are bad, and the general trend should be towards higher specificity later in the stylesheet.” It would be interesting to discuss that further, but it’s out of scope for this article. However, Harry Roberts did write about it extensively in his article “The Specificity Graph” which is worth checking out.

CSS Stats

CSS Stats is another tool that provides analytics and visualizations for your stylesheets. In fact, Robin wrote about it a little while back and showed how he used it to audit the stylesheet at his job.

All you need to do is to enter the URL of the site and hit Enter. The information is segmented into meaningful sections, from declaration count to colors, typography, z-indexes, specificity, and more. Again, you might want to store the screenshots for later reference.

Project Wallace

Project Wallace is made by Bart Veneman, who already introduced the project here on CSS-Tricks. The power of Project Wallace is that it can compare and visualize changes based on imports. That means you could see previous states of your CSS code base and see how your code changes between states. I find this feature quite useful, especially when you want to convince someone that the code is improved. The tool is free for a single project and offers paid plans for more projects.

CLI tools

In addition to DevTools and online tools, there are command line interface (CLI) tools that can help audit CSS.


One of my favorite CLI tools is Wallace. Once installed, type wallace and then the site name. The output shows everything you need to know about the CSS code for the site. My favorite things to look at are the number of times !important is used, as well as how many IDs are in the code. Another neat piece of information is the top specificity number and how many selectors use it. These might be red flags for “bad” code.

What I like the most about this tool is that it extracts all of the CSS code from the site, not only external files, but also inline code as well. That is why the report from CSS Stats and Wallace mismatch.


The csscss CLI tool shows which rules share the same declarations. This is useful for identifying duplicated code and opportunities to reduce the amount of code that’s written. I would think twice before doing that as it might not be worthwhile, especially with today’s caching mechanisms. It is worth mentioning that csscss requires Ruby.

Other useful tools

Other CSS tools might not be used for auditing but are still useful. Let’s list those, too:

  • Color Sorter — Sort CSS colors by hue, then by saturation.
  • CSS Analyzer — Generate an analysis for a string of CSS.
  • constyble — This is a CSS complexity linter, based on CSS Analyzer.
  • Extract CSS Now — Get all the CSS from a single webpage.
  • Get CSS — Scrape all the CSS from a page.
  • uCSS — Crawl websites to identify unused CSS.


CSS is everywhere around us, and we need to consider it a first-class citizen of every project. It does not matter what other people think about your CSS, but what you think about it really does matter. If your CSS is organized and well-written, you will spend less time debugging it and more time developing new features. In an ideal world, we would educate everyone to write good CSS, but that takes time.

Let today be the day when you start caring for your CSS code.

I know that auditing CSS isn’t going to be fun for everyone. But if you run your code against any of these tools and try to improve even one part of your CSS codebase, then this post has done its job.

I am thinking about CSS code more and more lately, and I am trying to make more developers write CSS code more respectfully. I even started a new project at (yay for hyphenated domain names!) that’s dedicated to auditing CSS.

If you know of any other tools, let me know in the comments.

Source link