Skip to content

Instantly share code, notes, and snippets.

View robdodson's full-sized avatar
Working from home

Rob Dodson robdodson

Working from home
View GitHub Profile
module.exports = function (config) {
config.addPlugin(EleventyServerlessBundlerPlugin, {
name: 'possum', // The serverless function name from your permalink object
functionsDir: './functions/',
return {
dir: {
input: 'src/site/content/', // we use a string path with the forward slash since windows doesn't like the paths generated from path.join
output: 'dist',
robdodson /
Last active July 29, 2021 03:40
:focus-visible tabindex

One of the intentions of :focus-visible is to not match if someone mouse-clicks on a div (or other generic element) with a tabindex. The reason is because developers often build custom controls using generic elements and when they unexpectedly show a focus ring on mouse click these same developer reach for :focus { outline: none; } which we really want to discourage.

The spec attempts to explain that :focus-visible should not match when you mouse click an element with a tabindex, but does so in a way that maybe isn't explicit enough. Quoting from the spec:

If the element which supports keyboard input (such as an input element, or any other element that would triggers a virtual keyboard to be shown on focus if a physical keyboard were not present), indicate focus.

This attempts to highlight the concept of "supporting keyboard input". Noteably a div with a tabindex would not meet this criteria.

If the user interacts with the page via

robdodson /
Last active May 5, 2021 20:04
:focus-visible meta keys


This is discussed in this issue but it looks like we updated the polyfill and forgot to update the spec :(

How we arrived at this decision

Slack asked if we should only match :focus-visible on tab / shift-tab (or in cases where the element should always receive it, like an input). Twitter chimed in with a +1. They both said essentially that when folks hit keyboard shortcuts that move focus, it's confusing to see the ring show up.

Alice pointed out that it's just as likely for a keyboard user to use those same shortcuts and it might be confusing for them to not see the ring.

We try to follow the methodology. The CSS for all component-like-things lives in the blocks directory. Blocks could either be BEM CSS components or web components. Here's a web component:

You can see how it's used here:

We use an Eleventy transform to feed the HTML for every page to PurgeCSS. Our PurgeCSS config looks at the raw html, and also our JS files, to figure out which classes to include in the page.

module.exports = function(eleventyConfig) {
eleventyConfig.addFilter('debug', function(...args) {
module.exports = (collection) => {
return collection
.slice(0, 3);
This file has been truncated, but you can view the full file.
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="">
<subtitle>Let&#39;s build the future of the web.</subtitle>
<link href="" rel="self"/>
<link href=""/>
<name>Google Developers</name>
robdodson / .eleventy.js
Last active November 8, 2021 11:54
Memoize an eleventy collection.
const {memoize} = require('find-by-slug');
// Turn collection.all into a lookup table so we can use findBySlug
// to quickly find collection items without looping.
config.addCollection('memoized', function(collection) {
return memoize(collection.getAll());
Skimmed this thread, so perhaps much of this was mentioned in some form or another before.
I would say testing against screen reader output is subject to all of the same issues that interactive ui testing suffers from.
It doesn't mean we shouldn't do it, but I have not seen it ever work in at least four instances I've seen it tried previously. The tests were always flakey, suffered from constant need for re-baselining, and generally were a net negative.
AOM is still under active development, so seems, at least for now, a poor target.
Chrome does indeed have an accessibility tree. We don't make it especially easy to introspect this tree. The easiest way currently is by using the chrome.automation extension api (which is only available on dev channel). It does have eventing and is what ChromeVox is based on.
Testing against this tree and making strong assertions against it for your given page makes the most sense to me.
el.accessibleNode.describedBy =
new AccessibleNodeList([accessibleNode1, accessibleNode2]);
el.accessibleNode.activeDescendant = accessibleNode3;