A score of 100 in Lighthouse or 0 errors in axe doesn’t mean that you’re done, it means that you’re ready to start manual testing and testing with real users, if possible.
Thursday, June 25th, 2020
Monday, June 22nd, 2020
But if I were going to bet on a web technology, it’s HTML. Always bet on HTML.
Saturday, June 13th, 2020
I think this a solution worthy of Solomon. In this case, the Gordian knot is the
select element and its inevitable recreation in order to style it.
What if we instead deliver a native select by default and replace it with a more aesthetically pleasing one if possible? That’s where the “hybrid” select idea comes into action. It’s “hybrid” because it consists of two selects, showing the appropriate one at the right moment:
- A native select, visible and accessible by default
- A custom select, hidden until it’s safe to be interacted with a mouse
The implementation uses a genius combination of a
hover media query and an adjacent sibling selector in CSS. It has been tested on a number of device/platform/browser combinations but more tests are welcome!
What I love about this solution is that it satisfies the stakeholders insisting on a custom component but doesn’t abandon all the built-in accessibility that you get from native form controls.
Friday, June 12th, 2020
A really great one-page guide to HTML from Bruce. I like his performance-focused intro:
If your site is based on good HTML, it will load fast. Browsers incrementally render HTML—that is, they will display a partially downloaded web page to the user while the browser awaits the remaining files from the server.
Wednesday, June 10th, 2020
Smart thinking from Sara to improve usability for keyboard users by using
aria-hidden="true" tabindex="-1" to skip duplicate links:
A good rule of thumb for similar cases is that if you have multiple consecutive links to the same page, there is probably a chance to improve keyboard navigation by skipping some of those links to reduce the number of tab stops to one. The less tab stops, the better, as long as it does not worsen or compromise on other aspects of usability.
I’ve cautiously implemented this pattern now over on The Session where snippets of comments had both a title link and a “more” link going to the same destination.
Friday, May 29th, 2020
Chris has put together one of his indispensable deep dives, this time into responsive images. I can see myself referring back to this when I need to be reminded of the syntax of
Sunday, May 10th, 2020
Here’s a short clear introduction to DOM scripting.
Monday, May 4th, 2020
A decade apart
I’m so proud of that book, and so honoured that I was the first author published by the web’s finest purveyors of brief books. I mean, just look at the calibre of their output since my stumbling start!
They started something magnificent. Ten years on, with Katel at the helm, it’s going from strength to strength.
Friday, May 1st, 2020
Some great practical examples of progressive enhancement on one website:
- using grid layout in CSS,
- using the
pictureelement to provide
webpimages in HTML.
All of those enhancements work great in modern browsers, but the underlying functionality is still available to a browser like Opera Mini on a feature phone.
A collection of articles and talks about HTML, CSS, and JS, grouped by elements, attributes, properties, selectors, methods, and expressions.
Thursday, April 30th, 2020
Here, Brian proposes a kind of minimum viable web component that handles logic like keyboard control and accessibility, but leaves the styling practically untouched. Check out his panel-set demo of a tabbed interface.
I really, really like the way that it wraps existing content. If the web component fails for any reason, the content is still available. So the web component is a progressive enhancement:
An experimental custom element that wraps plain-old HTML (view the source) and decorates function, keyboard handling, accessibility information.
Tuesday, April 28th, 2020
Great typography on the web should be designed in layers. The web is an imperfect medium, consumed by countless different devices over untold numbers of network connections—each with their own capabilities, limitations, and peculiarities. To think that you can create one solution that will look and work the same everywhere is a fantasy. To make this more than just one nice book website, the whole project and process needs to embrace this reality.
Thursday, April 23rd, 2020
I never thought of combining the
datalist element with
input type="color"—it’s pretty cool that it just works!
Monday, April 20th, 2020
Here’s one simple, practical way to make apps perform better on mobile devices: always configure HTML input fields with the correct
autocompleteattributes. While these three attributes are often discussed in isolation, they make the most sense in the context of mobile user experience when you think of them as a team.
This is an excellent deep dive with great advice:
You may think that you are familiar with the basic
autocompleteoptions, such as those that help the user fill in credit card numbers or address form fields, but I’d urge you to review them to make sure that you are aware of all of the options. The spec lists over 50 values!
I love how Remy explains front-end development to his kids:
The bones are the HTML. Each bone has a name, we call them tags (or elements).
…the skin and the paint on the skin, this is CSS.
Friday, April 17th, 2020
This is a terrific explanation of the concept of accessible names in HTML, written with verve and style!
Contrary to what you may think, naming an element involves neither a birth certificate nor the HTML
nameattribute is never directly exposed to the user, and is used only when submitting forms. Birth certificates have thus far been ignored by spec authors as a potential method for naming controls, but perhaps when web UI becomes sentient and self-propagating, we’ll need to revisit that.
Wednesday, April 8th, 2020
Consider what React and other SPA frameworks are good for: stateful, extensible component-driven applications. Now consider what a résumé’s goals are.
Monday, April 6th, 2020
Chromium browsers—Chrome, Edge, et al.—are getting a much-needed update to some interface elements like the
progess element, the
meter element, and the
color input types.
Friday, April 3rd, 2020
A nice succint explanation of using the
sizes attributes on the
img element—remember, you probably don’t need
source elements if your use case is swapping out different sized versions of the same image.
One caveat thought: you do need to know the dimensions of the images. If you’re dealing with unknown or user-generated photos, that can be an issue.
Tuesday, March 24th, 2020
I wrote yesterday about how messing about on your own website can be a welcome distraction. I did some tinkering with adactio.com on the weekend that you might be interested in.
Let me set the scene…
I’ve started recording and publishing a tune a day. I grab my mandolin, open up Quicktime and make a movie of me playing a jig, a reel, or some other type of Irish tune. I include a link to that tune on The Session and a screenshot of the sheet music for anyone who wants to play along. And I embed the short movie clip that I’ve uploaded to YouTube.
iframe has been delivered for nothing.
Meanwhile over on The Session, I’ve got a strategy for embedding YouTube videos that’s better for performance. Whenever somebody posts a link to a video on YouTube, the thumbnail of the video is embedded. Only when you click the thumbnail does that image get swapped out for the
iframe with the video.
That’s what I needed to do here on adactio.com.
That code checks to see if the URL is from a service that provides an oEmbed endpoint. A what-Embed? oEmbed!
In this case
http://example.com/oembed is the endpoint and
url is the value of a URL from that provider. Here’s a real life example from YouTube:
https://www.youtube.com/oembed is the endpoint and
url is the address of any video on YouTube.
You get back some JSON with a pre-defined list of values like
html payload is the markup for your embed code.
By default, YouTube sends back markup like this:
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
But now I want to use an
img instead of an
iframe. One of the other values returned is
thumbnail_url. That’s the URL of a thumbnail image that looks something like this:
In fact, once you know the ID of a YouTube video (the
?v= bit in a YouTube URL), you can figure out the path to multiple images of different sizes:
- 120 × 90:
- 320 × 180:
- 480 × 360:
- 1280 × 720:
(Although that last one—
maxresdefault.jpg—might not work for older videos.)
Okay, so I need to extract the ID from the YouTube URL. Here’s the PHP I use to do that:
parse_str(parse_url($url, PHP_URL_QUERY), $arguments);
$id = $arguments['v'];
Then I can put together some HTML like this:
<a class="videoimglink" href="'.$url.'">
<img width="100%" loading="lazy"
Over on The Session, I’m using
addEventListener but here on adactio.com I’m going to be dirty and listen for the event directly in the markup using the
When the link is clicked, I nuke the link and the image using
innerHTML. This injects an iframe where the link used to be (by updating the
innerHTML value of the link’s
But notice that I’m not using the default YouTube URL for the iframe. That would be:
Instead I’m swapping out the domain
I can’t remember where I first came across this undocumented parallel version of YouTube that has, yes, you guessed it, no cookies. It turns out that, not only is the default YouTube embed code bad for performance, it is—unsurprisingly—bad for privacy too. So the
youtube-nocookie.com domain can protect your site’s visitors from intrusive tracking. Pass it on.
Anyway, I’ve got the markup I want now:
<a class="videoimglink" href="https://www.youtube.com/watch?v=-eiqhVmSPcs"
<img width="100%" loading="lazy"
alt="The Banks Of Lough Gowna (jig) on mandolin"
The functionality is all there. But I want to style the embedded images to look more like playable videos. Time to break out some CSS (this is why I added the
videoimglink class to the YouTube link).
I’m going to use generated content to create a play button icon. Because I can’t use generated content on an
img element, I’m applying these styles to the containing
I was going to make an SVG but then I realised I could just be lazy and use the unicode character instead.
Right. Time to draw the rest of the fucking owl:
top: calc(50% - 5vmax);
left: calc(50% - 5vmax);
That’s a bunch of instructions for sizing and positioning. I’d explain it, but that would require me to understand it and frankly, I’m not entirely sure I do. But it works. I think.
With a translucent play icon positioned over the thumbnail, all that’s left is to add a
:hover style to adjust the opacity:
Wheresoever thou useth
:hover, thou shalt also useth
Okay. It’s good enough. Ship it!
If you embed YouTube videos on your site, and you’d like to make them more performant, check out this custom element that Paul made: Lite YouTube Embed. And here’s a clever technique that uses the
srcdoc attribute to get a similar result (but don’t forget to use the