Journal
Accessibility drives aesthetics by Alex Chen (on UX Collective)
This article is a couple of years old but just popped up on my radar again. UX Designer Alex Chen asserts that arguments which pit accessibility against aesthetics create a dangerous false equivalence… and I agree.
The article claims that if we are “too accessible” we will meet the needs of the minority but end up hurting those of the majority. This creates a false equivalence between having legitimate access needs and having a preference for a certain aesthetic.
Alex goes on to praise examples where accessibility is used to drive aesthetics – such as the Eames leg splint and GOV.UK’s design system – as opposed to considering the two ideals opposites or that one needs sacrificed for the other.
inline-block versus flexbox for horizontal arrangements
Something I’ve found interesting while reviewing recent code test submissions (within job applications) at work is that more developers than I’d expect still use display: inline-block when they need to lay out multiple elements horizontally such as the items in a navigation menu. It’s interesting because Flexbox – which has now been around for almost 10 years – gives you a modern, purpose-built solution to that.
Of course, there is no crime in taking the inline-block approach. It’s an option. And I did take a moment just to challenge my assumptions. But having given it a little thought, I am pretty convinced that Flexbox is the better approach and so I think their choice is worth a query.
Here’s why I think Flexbox is much better:
- Modern CSS layout is purpose-built for constructing multi-element layouts. Older methods were lacking, quirky and slightly hacky. Using (and knowing to use) purpose-built tools is generally a good thing for reliability, predictability and scalability.
- Modern CSS layout provides more control, because it’s fundamentally different. You get a parent context (the flex container or grid) that lets you style the context (with
gap, for example). We didn’t have this before. - Styling a context rather than individual items plays better with modern component-oriented organisation and ideas. It‘s good to keep components encapsulated and context-agnostic, handing off layout to separate, fit-for-purpose tools.
- Flexbox is built for responsiveness, i.e. built for the modern era.
inline-blockwas not. - the default
align-items:stretchmeans that items laid out in a row are automatically full parent-height which is often desirable for larger touch targets and achieving hover styles. inline-blockretains some of the properties ofinlinethat are undesirable for this type of use-case. Who can be bothered with whitespace in the code appearing on the screen, or having to work withvertical-alignwhen you don’t need to.
I also don’t see any reason to not use Flexbox. It’s conventional (see for example navigation menus on BBC, Tetralogical), recommended by CSS experts (Rachel Andrew, Jen Simmons etc), performant and well-supported by browsers. You are not going “fancy”, “cutting edge” or “overkill” by using Flexbox. For the “horizontal menu” use case, it’s simply a more suitable choice than the older alternatives.
Related: Chris Coyier’s article When do you use inline block is an excellent investigation into whether any necessary uses for inline-block remain. I reserve the right to change my mind on this, but aside from the “apply transform to an inline element” use case I can’t really see any that have not now been superseded.
Should I use a button or a link?
I’ve written previously about the important differences between buttons and links. While reviewing some “component refresh” design mocks at work yesterday I noticed the designs were a bit unclear in this regard so I sent the designers a little decision-tree, which I’m noting here for future reference.
It’s important both for our users and for us as practitioners to distinguish between links (the <a> element) and the <button> element. The reason I push this is because they’re fundamentally different functionally, which has important usability implications. Users expect to use mouse, keyboard, browser back-button and assistive tech differently for links than they do for <button>s. And if they can’t visually distinguish one from the other, they’ll try things they expect to work then get confused when they don’t work.
I think this is an area where design and materials can’t be considered separately and need a joined-up approach.
Here’s a flow I hope is helpful.
Ask: does it…
- take the user to another page? Then it’ll be a link – the
<a>(anchor) element. - cause something to change on the current page, or submit a form? Then it’ll be a button – i.e. the
<button>element.
If it’s a link (<a>):
- it should be underlined so people know it’s a link
- it should have a hover state, for example stay underlined but change colour
- in cases where it’s a CTA you might choose to design it to look button-like and remove some standard link affordances. Just be aware you’re only “calling” it a button. In real user-experienced terms, it’s still a link.
- it does not natively have a disabled state. We shouldn’t be disabling links.
If it’s a button (<button>):
- it should look like a button, i.e. like a pill or rectangle
- It should not look like a link – that’d confuse users into thinking it takes them to another page.
- So it shouldn’t be underlined by default or on hover. It should have some other hover state.
Testing the decision tree
Let’s take the example of a control for launching a modal dialogue.
The obvious choice is a button, because the control causes something to change on the current page. In this case it causes a dialogue to appear on the current page.
Some might argue that it could be a link. This is usually influenced by the fact that dialogues are often (perhaps inadvisably) used as a kind of “fake page”. And to get someone to a “page” we use a link, right? Advocates of the link option might also have progressive enhancement in mind. If they present a link either to a named fragment further down the page or to a separate page, that offers a resilient baseline experience regardless of whether or not JavaScript is available. The idea is that they also have JavaScript to enhance the link when the user’s environment supports it, perhaps adding role=button.
However a button is the more accessible and user-friendly approach for launching the modal.
Better accessible names | hidde.blog
Accessible names are used by assistive technologies to refer to elements on a web page. Hidde tells us how to word them so that they are more useful.
Because of how we use accessible names, we want to keep them functional and avoid naming controls after what they look like. Ideally, you do this in the imperative form, that makes it easiest to quickly grasp what a thing is going to do.
My summary of Hidde’s top tips is:
- Name after function rather than form (“Open navigation” over “Hamburger”)
- Put the most unique part first as this makes it more easy to distinguish between elements (so “Midnight Marauders - Album” rather than “Album - Midnight Marauders”)
- Be concise – keep a name to the most important 1-3 words
- No roles as part of the name (for example don’t include the word ‘button’ or
nav. The browser already handles this part so it’d be redundant and annoying) - Start names with a capital letter and don't end with a full stop, because a name is not a sentence
- Avoid ARIA if you can just use good element text content
Using the :has pseudo-class for real
By day I’m currently working on our Design System’s Table component. In order to achieve a design spec where the table has no bottom-border I needed to set:
- all cells in the final row of the
<tfoot>to have no bottom-border; but also - if there is no
<tfoot>then set all cells in the final row of the<tbody>to have no bottom-border.
Modern CSS’s support for writing selectors which traverse the DOM up, down and sideways is pretty amazing here.
I’ve gone with:
tfoot > :last-child td, tbody:not(:has(+ tfoot)) > :last-child td { border-bottom-width: 0; }
(Some BEM stuff renamed for brevity but that’s the gist of it)
In the past we’ve had to bloat the backend layer with complex and awkward logic that adds “convenience classes” like .fe-Table-bodyLastRow but as Eric Meyer has been saying :has() in particular is going to remove the need for those convenience classes.
Hat-tip to Jhey Tompkins for his excellent recent article on :has which was a great help.
How to Fix Common iOS Accessibility Issues | Deque
Although I don’t work on native apps, I’ve recently been wondering about how accessibility considerations for them compare to those for websites. So this is a timely and useful reference.
iOS provides a lot of accessibility behavior for free, so it’s a great start to making a mobile application accessible. Unfortunately, accessibility is more complicated than the iOS behavior can address, and using only default behavior can actually cause the app to have additional issues.
Tabs: truth, fiction and practical measures
My colleague Anda and I just had a good conversation about tabs, and specifically the company’s tabs component. I’ve mentioned before that our tabs are unconventional and potentially confusing, and Anda was interested to hear more.
What’s the purpose of a tabbed interface?
A tabbed interface is a space-saving tool for collapsing parallel content into panels, with one panel visible at a time but all accessible on-demand. While switching between tab panels the user is kept within the same wider context i.e. the same page, rather than being moved around.
Conventional tabbed interfaces
Here are some great examples of tabs components.
- Inclusive Components – Tabbed Interfaces
- Tabs component in GOV.UK Design System
- ARIA Tabs by Adrian Roselli
Tabs are a device intended to improve content density. They should deliver a same-page experience. Activating a tab reveals its corresponding tab panel. Ideally the approach employs progressive enhancement, starting as a basic Table of Contents. There’s quite a lot of advanced semantics, state and interactivity under the hood.
Faux tabs
But in our Design System at work, ours are currently just the “tabs” with no tab panels, and each “tab” generally points to another page rather than somewhere on the same page. In other words it’s a navigation menu made to look like a tabbed interface.
I’m not happy with this from an affordance point of view. Naming and presenting something as one thing but then having it function differently leads to usability problems and communication breakdowns. As the Inclusive Components Tabbed Interfaces page says:
making the set of links in site navigation appear like a set of tabs is deceptive: A user should expect the keyboard behaviors of a tabbed interface, as well as focus remaining on a tab in the current page. A link pointing to a different page will load that page and move focus to its document (body) element.
Confused language causes problems
One real-life problem with our tabs is that they have been engineered as if they are conventional tabs, however since the actual use case is often navigation the semantics are inappropriate.
We currently give each “tab” the ARIA tab role, defined as follows:
The ARIA
tabrole indicates an interactive element inside atablistthat, when activated, displays its associatedtabpanel.
But our tabs have no corresponding tabpanel; they don’t use JavaScript for a single-page experience balancing semantics, interactivity and state as is conventional. They’re just navigation links. And this mismatch of tabs-oriented ARIA within a non-tabs use case will do more harm than good. It’s an accessibility fail.
A stop-gap solution
If content for one or more tabpanel is provided, apply the complicated ARIA attributes for proper tabs. If not, don’t. This means we allow component consumers to either create i) a real tabbed interface, or ii) “a nav menu that looks like tabs” (but without any inappropriate ARIA attributes). I don’t agree with the latter as a design approach, but that’s a conversation for another day!
Tabs in the future
Some clever people involved with Open UI are using web components to explore how a useful tabs element could work if it were an HTML element. Check out the Tabvengers’ spicy-sections component. Again, this is based on the conventional expectation of tabs as a same-page experience for arranging content, rather than as a navigation menu. And I think it’d make sense to stay on the same path as the rest of the web.
Editable table cells
Yesterday the Design System team received a tentative enquiry regarding making table cells editable. I’m not yet sure whether or not this is a good idea – experience and spidey sense tell me it’s not – but regardless I decided to start exploring so as to base my answer on facts and avoid being overly cautious.
In my mind’s eye, there are two ways to achieve this:
- on clicking the cell, the cell content is presented in an (editable) form input; or
- apply the
contenteditableattribute
In both cases you get into slightly gnarlier territory when you start considering the need for a submit button and how to position it.
I don’t have anything further to add at the moment other than to say that if I had to spike this out, I’d probably start by following Scott O’Hara’s article Using JavaScript & contenteditable.
I’d probably also tweet Scott and ask if he can say anything more on his closing statement which was:
I have more thoughts on the accessibility of contenteditable elements, but that will also have to be a topic for another day…
Update 27-09-22: I’ve also remembered that (if I were to pursue Option 1: input within cell) Adrian Roselli has an article on Accessibly including inputs in tables.
Building the main navigation for a website (on web.dev)
learn about semantic HTML, accessibility, and how using ARIA attributes can sometimes do more harm than good.
Alongside all the sound accessibility and hiding-related advice, I also found Manuel’s approach to progressive enhancement interesting. Rather than i) include a hamburger button directly in the DOM and set its initial state to hidden; or ii) create the button element with JavaScript, he instead nests the button in a template element then clones that element with JavaScript. He later tweeted his rationale for this approach:
If JS doesn't work, the markup inside the template won't be rendered on screen and it's more convenient to prepare the markup upfront instead of using document.createElement().
The ability to prepare complex, JS-dependent component markup upfront in declarative HTML rather than recreating it in JavaScript is a compelling argument for his approach. Especially so if you don’t work in JS framework-based systems therefore your components are not written in JavaScript.
Brilliant first day at We Out Here 2022
Had such a good day yesterday @weoutherefest with Tom, Jason and Craig. In the afternoon we checked Enny, Sally Rodgers (A Man Called Adam) and Aletha. We then stopped for a short break to sample the food and drink (Char Sui Vermicelli from the NAM stall and a break from beer for a cracking coffee). Our nighttime choices were Bake, Charlie Dark, Pearson Sound and Alex Nut.
The absolute highlight was Charlie Dark in the forest. Amazing woodland setting and a killer set! Charlie has such great energy both on the decks and on the mic. He played a mix of house, techno, disco and broken biznizz – right up my street! Great mixing too (aided by his old-school lollipop headphone).
Time for Round Two!