Resources
Resource | Type / Description |
---|---|
up your a11y | Guide |
MagentaA11y | Accessibility Acceptance Criteria Checklists |
HTMLHell | "A collection of bad practices in HTML, copied from real websites." |
Using Emoji
I love the use of Emoji as a design shortcut, especially for personal projects. Lightweight vector icon that is baked into the system and matches the user's OS styles? Yes please! However, there are some important a11y concerns.
General rule of thumb:
- Wrap with
<span></span>
- Modify span, if...
- Purely decorative (isn't part of the content)
- Add
aria-hidden="true"
to span - Omit label & role
- Add
- Part of content / conveys meaning
- Add
role="img"
- Add
aria-label="{emojiShortName}"
- Do not use aria-hidden
- Add
- Purely decorative (isn't part of the content)
Example:
My face when my code worked: <span role="img" aria-label="face with tears of joy">😂</span>
💡 Tip: If you are using a lot of emojis in your project, you might want to extract this pattern into a component, or use a pre-built component (such as
a11y-react-emoji
for React).
âš Note: Emoji can have multiple text strings associated with their Unicode entry; the official title (English only, permanent), alias, and - most commonly used for
aria-label
and display - the CLDR short name.
Forms
Label Grouping and Associations
Every form input (aka form control) should generally have a label, which describes its purpose. There are a few ways to associate a label with a control element, which is outlined in detail here (and here), but I'll summarize below:
- Explicit Linking
- Option: Use
<label for="{idOfInput}">{descriptiveText}</label>
- It is OK to hide this element for those that can visually infer purpose without it. But you might be better off with below approach in that case.
- Option: Use
<input aria-label="{descriptiveText}" />
- Good for if you don't want a visual label
- Option: Use
<input aria-labelledby="{idOfElement}" />
- The element you reference by ID should contain th descriptive text itself
- Good for when you have an existing (non-label) element you want to reuse the text from, as both a visual element and assistive text
- Not recommended:
<input title="{descriptiveText}" />
- Option: Use
- Implicit Association
- Option: Use
<label>
as container for input & text<label> Favorite food: <input type="text" /> </label>
- (For buttons only): Enclose text in button element:
<button>{descriptiveText}</button>
- Option: Use
🤔 What about placeholder values?
- Although they can be combined with
label
features, in general you are better off just using labels- Even for sighted users, the
placeholder
attribute is usually not great to use from a UX perspective, since it doesn't play nice with translations and disappears as soon as the user types
Buttons vs Links
📄 Great resource: Adrian Roselli - "Links, Buttons, Submits, and Divs, Oh Hell"
When you want an action performed on an element click, a <button>
is almost always preferred. And if you want to navigate a user to a different page, a link is preferred (<a>
).
In general, if it acts like a duck, it needs to look (semantically, not necessarily visually) like a duck. That is to say, if clicking on an element takes you somewhere it should be a link, but if it performs an action without navigating, it should be a button.
However, what about the rare cases when these collide; when you have links that you want to look like buttons. What is the most accessible way to implement these?
Let's start off by saying what you should almost never do:
<!-- Please... no, just no. Use an `<a>` instead. -->
<button role="link">Click here to login</button>
OK, so we should stick with <a>
if we are navigating somewhere. But what if we really want it to look like a button? Is this OK?
<a href="/login" class="my-button">Click here to login</a>
<style>
.my-button {
/* A bunch of styling that makes .my-button look like a button */
}
</style>
This is better than using button
with role
, but you are not in the clear just yet. In styling links, ideally you still need to adhere to the rule that the way your components look should communicate their function. So styling a link like a button, to the extent that a user might confuse the two, is generally a no-no, even if you use an actual link element.
That being said... this is still done all the time. In fact, MDN has a tutorial on "styling links as button".
Going back to "if it acts like a link, it needs to be a link...", to take things a step further, what about when the behavior is indeterminate? E.g., when clicking a certain element could either perform an action or redirect the user, based on some condition that cannot be known until the click happens (e.g., expired login cookies)?
This is kind of a contentious question within the community; just look at the replies to this tweet and the follow-up post.