Tagged “progressiveenhancement”
How would you build Wordle with just HTML & CSS? by Scott Jehl
Scott proposes an interview question relating to web standards and intelligent use of JavaScript.
How would you attempt to build Wordle (...or some other complex app) if you could only use HTML and CSS? Which features of that app would make more sense to build with JavaScript than with other technologies? And, can you imagine a change or addition to the HTML or CSS standard that could make any of those features more straight-forward to build?
The new HTML search element
My work colleague Ryan recently drew my attention to the new HTML search
element. This morning I read Scott O’Hara’s excellent primer. Scott worked on implementing <search>
, and his article cleared up my questions around what it is and when we can start using it.
Lean “plugin subscription form” by Chris Ferdinandi
I enjoyed this two-part tutorial from Chris arising from his critique of a subscription form plugin which includes the entire React library to achieve what could be done with a lightweight HTML and vanilla JavaScript solution. Chris advocates a progressively-enhanced approach. Instead of rendering the form with JavaScript he renders it in HTML and argues that not only is there no need for the former approach – because forms natively work without JavaScript – but also it only introduces fragility where we could provide resilience.
Let's talk about web components (by Brad Frost)
Brad breaks down the good, bad and ugly of web components but also makes a compelling argument that we should get behind this technology.
I come from the Zeldman school of web standards, am a strong proponent of progressive enhancement, care deeply about accessibility, and want to do my part to make sure that the web lives up to its ideals. And I bet you feel similar. It’s in that spirit that I want to see web components succeed. Because web components are a part of the web!
WebC
WebC, the latest addition to the Eleventy suite of technologies, is focused on making Web Components easier to use. I have to admit, it took me a while to work out the idea behind this one, but I see it now and it looks interesting.
The ARIA presentation role
I’ve never properly understood when you would need to use the ARIA presentation
role. This is perhaps in part because it is often used inappropriately, for example in situations where aria-hidden
would be more appropriate. However I think the penny has finally dropped.
Thoughts on HTML over the wire solutions
Max Böck just tweeted his excitement about htmx:
htmx (and similar "HTML over the wire" approaches) could someday replace Javascript SPAs. Cool to see a real-world case study on that, and with promising results
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!)
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.
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.
Web components as progressive enhancement, by Cloud Four
By enhancing native HTML instead of replacing it, we can provide a solid baseline experience, and add progressive enhancement as the cherry on top.
Great article by Paul Herbert of Oregon’s Cloud Four. Using a web component to enhance an existing HTML element such as <textarea>
(rather than always creating a custom element from scratch) feels very lean, resilient and maintainable.
Enhance! by Jeremy Keith—An Event Apart video (on Vimeo)
A classic talk by Jeremy Keith on progressive enhancement and the nature of the web and its technologies.
Collapsible sections, on Inclusive Components
It’s a few years old now, but this tutorial from Heydon Pickering on how to create an accessible, progressively enhanced user interface comprised of multiple collapsible and expandable sections is fantastic. It covers using the appropriate HTML elements (buttons) and ARIA attributes, how best to handle icons (minimal inline SVG), turning it into a web component and plenty more besides.
Progressively enhanced burger menu tutorial by Andy Bell
Here’s a smart and comprehensive tutorial from Andy Bell on how to create a progressively enhanced narrow-screen navigation solution using a custom element. Andy also uses Proxy
for “enabled” and “open” state management, ResizeObserver
on the custom element’s containing header
for a Container Query like solution, and puts some serious effort into accessible focus management.
Adapting Stimulus usage for better Progressive Enhancement
A while back, Jake Archibald tweeted:
Don't render buttons on the server that require JS to work.
Container Queries in Web Components | Max Böck
Max’s demo is really clever and features lots of interesting web component related techniques.
I came up with this demo of a book store. Each of the books is draggable and can be moved to one of three sections, with varying available space. Depending on where it is placed, different styles will be applied to the book.
Ruthlessly eliminating layout shift on netlify.com, by Zach Leatherman
I love hearing about clever front-end solutions which combine technologies and achieve multiple goals. In Zach’s post we hear how Netlify’s website suffered from layout shift when conditionally rendering dismissible promo banners, and how he addressed this by rethinking the problem and shifting responsibilities around the stack.
Here’s my summary of the smart ideas covered in the post:
- decide on the appropriate server-rendered content… in this case showing rather than hiding the banner, making the most common use case faster to load
- have the banner “dismiss” button’s event handling script store the banner’s
href
in the user’s localStorage as an identifier accessible on return visits - process lightweight but critical JavaScript logic early in the
<head>
… in this case a check for this banner’s identifier existing in localStorage - under certain conditions – in this case when the banner was previously seen and dismissed – set a “state” class (
banner--hide
) on the<html>
element, leading to the component being hidden seamlessly by CSS - build the banner as a web component, the first layer of which being a custom element
<announcement-banner>
and the second a JavaScript class to enhance it - delegate responsibility for presenting the banner’s “dismiss” button to the same script responsible for the component’s enhancements, meaning that a broken button won’t be presented if that script were to break.
So much to like in there!
Here are some further thoughts the article provoked.
Web components FTW
It feels like creating a component such as this one as a web component leads to a real convergence of benefits:
- tool-free, async loading of the component JS as an ES module
- fast, native element discovery (no need for a
document.querySelector
) - enforces using a nice, idiomatic class providing encapsulation and high-performing native callbacks
- resilience and progressive enhancement by putting all your JS-dependent stuff into the JS class and having that enhance your basic custom element. If that JS breaks, you still have the basic element and won’t present any broken elements.
Even better, you end up with framework-independent, standards-based component that you could share with others for reuse elsewhere, just like Zach did.
Multiple banners
I could see there being a case where there are multiple banners during the same time period. I guess in that situation the localStorage banner
value could be a stringified object rather than a simple, single-URL string.
Setting context on the root
It’s really handy to have a way to exert just-in-time control over the display of a server-rendered element in a way that avoids flashes of content… and adding a class to the <html>
element offers that. In this approach, we run the small amount of JavaScript required to test a local condition (e.g. checking for a value in localStorage) really early. That lets us process our conditional logic before the element is rendered… although this also means that it’s not yet available in the DOM for direct manipulation. But adding a class to the HTML element means that we can pre-prepare CSS to use that class as a contextual selector for hiding the element.
We’re already familiar with the technique of placing classes on the root element from libraries like modernizr and some font-loading approaches, but this article serves as a reminder that we can employ it whenever we need it.
Handling the close button
Zach’s approach to handling the banner’s dismiss button was interesting. He makes sure that it’s not shown unless the web component’s JavaScript runs successfully which is great, but rather than inject it with JavaScript he includes it in the initial HTML but hidden with CSS, and his method of hiding is opacity
.
We use opacity to toggle the close button so that it doesn’t reflow the component when it’s enabled via JavaScript.
I think what Zach’s saying is that the alternatives – inserting the button with JS, or toggling the hidden
attribute or its CSS counterpart display:none
– would affect geometry causing the browser to perform layout… whereas modifying opacity does not.
I love that level of diligence! Typically I prefer to delegate responsibility for inserting JS-dependent buttons to JavaScript because in comparison to including a button in the server-rendered HTML then hiding it, it feels more resilient and a more maintainable separation of concerns. However as always the best solution depends on the situation.
If I were going down Zach’s route I think I’d replace opacity
with visibility
since the latter hiding method removes the hidden element from the document which feels more accessible, while still avoiding triggering the reflow that display
would.
Side-thoughts
In a server-side scripted application – one using Rails or PHP, for example – you could alternatively handle persisting state with cookies rather than localStorage… allowing you to test for the presence of the cookie on the server then handle conditional rendering of the banner on the server too, rather than needing classes which trigger hiding. I can see an argument for that. Thing is though, not everyone’s working in that environment. Zach has provided a standalone solution.
References
- Zach’s Herald of the dog web component
- CSS Triggers of reflow and repaint
- Minimising layout thrashing
One web component to rule them all? (on Filament Group, Inc.)
Scott Jehl has taken a refreshingly Progressive Enhancement -centric look at Web Components.
this pattern provides a nice hook for adding progressive enhancements to already-meaningful HTML contained in these custom elements, leaving them resilient in the case of of script loading failures and allowing the page to start rendering before the JS happens to run.
Building a resilient frontend using progressive enhancement (on GOV.UK)
GOV.UK’s guidance on developing using progressive enhancement is pretty great in all departments. It begins with this solid advice:
you should start by making your page work with just HTML, before adding anything else like Cascading Style Sheets (CSS) and JavaScript. This is because HTML is the most resilient layer. If the HTML fails there’s no web page. Should the CSS or JavaScript fail, the HTML will still render correctly.
Progressively enhanced JavaScript In Real Life
Over the last couple of days I’ve witnessed a good example of progressive enhancement “In Real Life”. And I think it’s good to log and share these validations of web development best practices when they happen so that their benefits can be seen as real rather than theoretical.
Browser Support Heuristics
In web development it’s useful when we can say “if the browser supports X, then we know it also supports Y”.
Three CSS Alternatives to JavaScript Navigation (on CSS-Tricks)
In general this is a decent article on non-JavaScript-based mobile navigation options, but what I found most interesting is the idea of having a separate page for your navigation menu (at the URL /menu, for example).
Who said navigation has to be in the header of every page? If your front end is extremely lightweight or if you have a long list of menu items to display in your navigation, the most practical method might be to create a separate page to list them all.
Striking a Balance Between Native and Custom Select Elements (on CSS-Tricks)
We’re not going to try to replicate everything that the browser does by default with a native select element. We’re going to literally use a select element when any assistive tech is used. But when a mouse is being used, we’ll show the styled version and make it function as a select element.
We’ve ruined the Web. Here’s how we fix it. (This is HCD podcast)
During the COVID situation, people have an urgent need to access critical information online. But in 2020, the average webpage is rammed full of large JavaScript files, huge images etc, and as a result is slow to load. This problem is likely to be most keenly felt by those who don’t have the luxury of fast internet – potentially the same people who need access to that critical information the most.
Here’s a brilliant discussion between Gerry McGovern and Jeremy Keith on that problem, suggesting tactics to help fix things such as performance budgets, introducing tactics at the design stage to mimic slow connections and other access constraints, optimising for return visits, progressive enhancement and more.
In the same vein as Jeremy Keith’s recent blog post, Hydration, which calls out some of the performance and user experience problems associated with current Server Side Rendering approaches, I think Jake Archibald is absolutely bang on the money here.
Hydration (Adactio: Journal)
The situation we have now is the worst of both worlds: server-side rendering followed by a tsunami of hydration. It has a whiff of progressive enhancement to it (because there’s a cosmetic separation of concerns) but it has none of the user benefits.
Building an accessible show/hide disclosure component with vanilla JS (Go Make Things)
A disclosure component is the formal name for the pattern where you click a button to reveal or hide content. This includes things like a “show more/show less” interaction for some descriptive text below a YouTube video, or a hamburger menu that reveals and hides when you click it.
Progressively Enhanced JavaScript with Stimulus
I’m dipping my toes into Stimulus, the JavaScript micro-framework from Basecamp. Here are my initial thoughts.
Releasing early, releasing often… and avoiding paralysis by analysis
My name is Laurence Hughes and I’m a perfectionist. But I’m working on it.
See all tags.