Journal
Avoiding img layout shifts: aspect-ratio vs width & height attributes (on Jake Archibald's blog)
Recently I’ve noticed some developers recommending using the CSS aspect-ratio property directly on images. My understanding of aspect-ratio was that it’s not so much intended for elements like img which already have an intrinsic aspect ratio, but rather for the likes of div which do not. Furthermore, when the goal is to prevent the layout shift that can occur after an image loads we should supply our images with width and height HTML attributes rather than using CSS.
In this timely post, Jake helpfully explains how width and height attributes are used by CSS as presentation hints to automatically set an aspect-ratio that will also, in cases where the attributes were set wrongly, fall back to the image’s intrinsic aspect ratio. Therefore, concentrating on HTML alone is ideal for our content images. My previous approach seems sound but I now know a little more about why.
If I'm adding an image to an article on my blog, that's content. I want the reserved space to be the aspect ratio of the content. If I get the width and height attributes wrong, I'd rather the correct values were used from the content image. Therefore, width and height attributes feel like the best fit. This means I can just author content, I don't need to dip into inline styles.
If it's a design requirement that the layout of an image is a particular aspect ratio, enforcing that with aspect-ratio in CSS can be appropriate. For example, a hero image that must be 16 / 9 – if the image isn't quite 16 / 9 I don't want it messing up my design, I want the design to take priority. Although, if the image isn't actually that aspect ratio, it'll either end up stretched (object-fit: fill), letter-boxed (object-fit: contain), or cropped (object-fit: cover). None of which are ideal.
A local’s guide to… (on The Guardian)
For a while now I’ve been enjoying this series of bite-sized travel guides from The Guardian, which puts the spotlight on a European town or city and hands over to a switched-on local to share food, shopping, cultural and green space highlights.
Some are more suited to my tastes and budget than others, but overall they’ve been good. And not just for far-flung places – on a recent day-trip east I checked out a number of the stops on their Edinburgh guide and it gave me a great basis for further exploration.
Sites which don’t work without JavaScript enabled still benefit from progressive enhancement
At work I and our team just had an interesting realisation about a recent conversation. We had been discussing progressive enhancement for custom toggles and a colleague mentioned that the web app in question breaks at a fundamental level if the user has disabled JavaScript, displaying a message telling them to change their settings in order to continue. He used this to suggest that any efforts to provide a no-JavaScript experience would be pointless. And this fairly absolute (and on-the-surface, sensible) statement caught me off-guard and sent me and the others down a blind alley.
I remember replying “yes, but even still we should try to improve the code by introducing good practices” and that feeling a little box-ticky.
However in retrospect I realise that we had temporarily made the mistake of conflating “JavaScript enabled” with “JavaScript available” – which are separate possibilities.
When considering resilience around JavaScript, we can consider the “factors required for JavaScript to work” as layers:
- is JavaScript enabled in the user’s browser?
- is the JavaScript getting through firewalls? (it recently didn’t for one of our customers on the NHS’s network)
- has the JavaScript finished loading?
- does the user’s browser support the JavaScript features the developers have used (i.e. does the browser “cut the mustard”?)
- is the JavaScript error-free? It’s easy for some malformed JSON to creep in and break it…
And the point my colleague made relates to Layer 1 only. And that layer – JavaScript being disabled by the user – is actually the least likely explanation for a JavaScript-dependent feature not working.
So it's really important to remember that when we build things with progressive enhancement we are not just addressing Layer 1, but Layers 2—5 too (as well as other layers I’ve probably forgotten!)
Safari is getting Web Push! (on the Webventures blog)
Roderick E.J.H. Gadellaa, author of the Webventures blog writes that at their June 2022 Worldwide Developers Conference (WWDC) Apple announced that it will bring Web Push (web-based push notifications) to Safari, including iOS Safari.
MacOS is going to get it first and iOS will receive it in a later iOS 16.x update, sometime in 2023.
This could be a big deal, because…
The lack of the web being able to do push notifications on iOS is probably the biggest reason why web developers see a potential project end up being built as a native app instead of a web app
…and…
Web Push on iOS will change the “we need to build a native app” decision.
I don’t like the idea that native mobile apps are superior to mobile web experiences, nor the notion that by having a native app you can ignore your small-screen web experience. PWAs and native apps can co-exist in harmony and address different use cases. But also web APIs are becoming more powerful all the time, and this announcement by Apple provides fuel for the argument that “you might not need a native app for that!”
I’ve started reading The New Breed: How to think about robots, by Kate Darling.
How we think about browsers, on GitHub’s blog
Keith Cirkel of Github has written about how they think about browsers and it’s interesting. In summary Github achieve:
- improved performance;
- exploiting new native technologies; and
- universal user access/inclusion
…via a progressive enhancement strategy that ensures a basic experience for all but delivers an enhanced experience to most. Their tooling gets a bit deep/exotic in places but I think the basic premise is:
- decide on what our basic experience is, then use native HTML combined with a bare minimum of other stuff to help old browsers deliver that; and
- exploit new JS features in our enhanced experience (the one most people will get) to make it super lean and fast
Pretty cool.
Using accessibility literacy to counter accessibility ignorance, by Devon Persing
The idea of accessibility literacy (having the right vocabulary, knowing the trustworthy info sources etc) makes sense.
The section on Accessibility ignorance and ableism presents some home truths about organisational attitudes to accessibility that need addressed.
Accessibility ignorance actually goes beyond just a lack of accessibility literacy. Accessibility ignorance is a facet of ableism, since it causes people to make decisions that actively harm disabled people.
- Accessibility ignorance isn't usually malicious.
- It's assuming that accessibility is taken care of because your organization has an accessibility specialist on staff, or has accessibility "baked in" to a design system.
- It's providing accessibility training for only teams that build products and not people that work in support, legal, operations, leadership, or other parts of the organization.
- It's expecting accessibility work to happen without impacting schedules and roadmaps that didn't originally take accessibility work into account.
- It's assuming disabled people don't use your product.
- It's not hiring disabled people.
- It's hiring disabled people but only to do accessibility work.
- …
The article wraps up with some great advice on cultivating accessibility literacy, and the senior buy-in needed to support it.
Getting Started With CSS Cascade Layers, by Stephanie Eckles
Yesterday I read Eric Meyer discussing CSS Cascade Layers and commenting that the speed at which it had transitioned from first public working draft to shipping as a full public release in every major desktop and mobile browser had made his head spin. Amazing stuff and an indicator of the turbo-boosted pace at which modern CSS is now evolving.
It also made me want to properly read up on Cascade Layers, because I knew some of the theory but now wanted to consider using it in practice. I’m no great fan of “cascade-taming” CSS frameworks like BEM and SUIT (although I acknowledge why we have them) so I’m interested to know if Cascade Layers can replace them. Stephanie Eckles’ article is an excellent primer.
I liked the idea of a specifying a stack like this:
@layer reset, base, theme, components, utilities;
You can then write styles into any of those layers at any point in a stylesheet, safe in the knowledge that the original stack definition sets the order of priority rather than the sequence in which we wrote specific styles.
Stephanie also addresses the question of whether we should write every component as a layer, which is something I’ve been considering. She advises that you could… but it’s probably not going to achieve the scoping effect that you want.
layers are not intended to solve scoping or encapsulation of styles. For that, keep an eye on another spec also being authored by Miriam Suzanne for actual native CSS scoping.
Lastly, Stephanie tackles how ready Cascade Layers are to use right now. At the time she wrote the article – January 2022 – the feature wasn’t widely supported, so wasn’t an option. Additionally Cascade Layers can’t really be used as a progressive enhancement because its nature is so all-encompassing and because testing for feature support using @supports isn’t an option.
However like Eric Meyer mentions, a few months is a long time in CSS support! And as I write in June 2022 the browser support picture is currently looking quite healthy. However given that the first browsers to add support were only released a few months ago in February or March of this year, I think we might need to wait a bit longer – maybe til the percentage of users on non-supporting browsers is negligible – before using this on larger, higher-traffic sites.
Nothing to stop us experimenting on our smaller and intranet-based sites, though!
Refactoring a modal dialogue in 2022
My team will soon be refactoring our modal dialogue component. Ours has a few deficiencies, needs better developer experience and documentation, is not built to our Design System component standards, and could use a resilience boost from some progressive enhancement.
For a long time the best – meaning accessible, framework-agnostic, feature-packed – modal implementations were custom. Specifically:
However with recent browser advances (especially from Safari), there’s an argument that the time has now come that we no longer need custom solutions and can go native. So we might reach for the native <dialog> HTML element.
However first I think we’d need to make an informed decision regarding our satisfaction with support, based on the updated advice in Scott O’Hara’s article Having an Open Dialog.
Additionally we should definitely be keeping one eye on proposals around the exciting new togglepopup and popup attributes which promise the holy grail of entirely HTML-powered modal dialogues with no JavaScript dependency.
Does the HTML details element solve progressively-enhanced disclosures?
The HTML details element continues to gain fans and get developers’ juices flowing. Scott Jehl recently tweeted:
I love the details/summary HTML elements. So versatile. My favorite part is being able to show a collapsed state from the start without worrying about potential operability issues if JavaScript fails to run (since its behavior doesn't need it).
Scott goes on to describe how creating disclosure widgets (controls that hide and show stuff) with resilience in mind is so much more difficult when not using <details> since it can require complex progressive enhancement techniques. At the very least these involve making content available by default in case JavaScript fails, then hiding it when the disclosure widget script loads successfully, ideally without a jarring flash of content in between.
Like Scott says, the <details> element is different because you can have the content collapsed (hidden) by default without worrying about JavaScript and workarounds since the hidden content can be toggled open natively. That‘s a real superpower… and also makes you wonder: how many different places and different ways might we use this super-element?
GitHub’s use of details
Back in 2019, GitHub caused a flutter by going all-in on <details> to make various interesting UI elements interactive without JS. Muan has co-created a number of components for Github where <details> is used to, for example, open menus. They also shared notes from a talk on this subject. And Chris Coyier for one was impressed and intrigued.
Zach Leatherman’s details-utils
I’ve previously noted Zach Leatherman’s details-utils – a great example of using a web component to enhance an existing HTML element, in this case <details>. The enhancements include:
- animated open/close
- a quantum aspect ideal for responsive design – closed by default on narrow screens, open by default on wide
- and more
And Zach has already used it on the navigation menus on jamstack.org and netlify.com, amongst other use cases.
Notes of caution
- The details element and in-page search by Manuel Matuzovic
- A details element as a burger menu is not accessible on Cloud Four’s blog
- The details and summary elements, again by Scott O’Hara
- Disclosure widgets by Adrian Roselli
- Details and summary are not…
- Details content showing up in find (Ctrl+F)
Alternative approaches
Using a custom disclosure widget put together with JavaScript and ARIA is not the end of the world. In fact I recently tried my hand at a disclosure widget web component and early impressions are that the combination of fast, async ES modules plus native DOM discovery (which you get with web components) might alleviate the “flicker of content” issue I mentioned at the start.
Summing up
I’d been cautious about using details for more than cases matching its intended usage but had started thinking the time was right to take it further – possibly using Zach’s web component. However based on the findings shared in the above Notes of caution section I’ve decided to stay safe to keep the user experience predictable and accessible. The behaviour when the user does an in-page search, and the current browser inconsistencies in announcing the summary as an expand/collapse button tell me that a custom JS and ARIA disclosure widget is better for the custom UI cases.