RSSAmplifier

Blog

Lea Verou’s blog

Web standards, Software Engineering, Product, Usability, and more

lea.verou.meRSS feed ↗242 posts

Latest posts

Dark mode toggles: two states are enough

A good two-state toggle can actually express all three data model states. Until recently, if you looked at most websites with a theme toggle [1] , you’d find three options: Light , Dark , and System . Examples of tri-state dark mode toggles. In (LTR) reading direction: Tailwind, Red Hat Design System, Ant Design, Web Awesome, Excalidraw, Taiga, Astro, Hero UI. Thankfully, these days the trend has…

In defense of polyfills

If you’re a web developer, you may find the title baffling. “Polyfills need defending? Who’s against them?!” you might ask. Two weeks ago, I’d be in the same boat. Polyfills and I go way back. I dug up a JSConf EU talk of mine from 2011 on exactly this topic. Trying not to think about how young I look here 😅 One of the few opinions I have held strongly over the years is that polyfills are a net…

External import maps, today!

A few weeks ago, I posted Web dependencies are broken. Can we fix them? . Today’s post is a little less gloomy: Turns out that the major limitation that would allow centralized set-it-and-forget-it import map management can be lifted today, with excellent browser support! The core idea is that you can use DOM methods to inject an import map dynamically , by literally creating an <script…

Web dependencies are broken. Can we fix them?

No, this is not another rant about npm’s security issues. Abstraction is the cornerstone of modern software engineering. Reusing logic and building higher-level solutions from lower-level building blocks is what makes all the technological wonders around us possible. Imagine if every time anyone wrote a calculator they also had to reinvent floating-point arithmetic and string encoding! In healthy…

In the economy of user effort, be a bargain, not a scam

Alan Kay [source] One of my favorite product design principles is Alan Kay’s “Simple things should be simple, complex things should be possible” . [1] I had been saying it almost verbatim long before I encountered Kay’s quote. Kay’s maxim is deceptively simple, but its implications run deep. It isn’t just a design ideal — it’s a call to continually balance friction, scope, and tradeoffs in service…

State of HTML 2025 now open!

tl;dr : State of HTML 2025 survey is now open! Take it now Mamma mia, here we go again! About two weeks ago, I announced that I was back leading this year’s State of HTML 2025 survey, after a one year hiatus. We are grateful for all the suggestions that poured in, they were immensely helpful in shaping the survey. After two weeks of hard work from a small team spanning three continents, we are…

Influence the State of HTML 2025 Survey!

Mamma mia, here we go again! Two years ago, I was funded by Google to design the inaugural State of HTML survey . While I had led State of … surveys before (also graciously sponsored by Google), that was by far the most intense, as 0→1 projects often are. In addition to the research, content, and analysis work that goes into every State of … survey, the unique challenges it presented were a…

The Hovercar Framework for Deliberate Product Design

You may be familiar with this wonderful illustration and accompanying blog post by Henrik Kniberg about good MVPs: It’s a very visual way to illustrate the age-old concept that that a good MVP is not the one developed in isolation over months or years, grounded on assumptions about user needs and goals, but one that delivers value to users as early as possible , so that future iterations can take…

Bluesky Likes Web Components

Just want the components? Here you go: Demo Repo NPM A love letter to the Bluesky API I’m old enough to remember the golden Web 2.0 era, when many of today’s big social media platforms grew up. A simpler time, when the Web was much more extroverted. It was common for websites to embed data from others (the peak of mashups ), and prominently feature widgets from various platforms to showcase a…

Construction Lines

I recently stumbled across The Oatmeal’s series on Creativity . While all of it is spot on, the part on erasers hit especially hard. “There is a lot of shame associated with backpedaling; things like quitting your job, getting a divorce, or simply starting over are considered shameful . But forward isn’t always progress. And backward isn’t always regress. Sometimes going down the wrong path isn’t…

Style-observer: JS to observe CSS property changes, for reals

I cannot count the number of times in my career I wished I could run JS in response to CSS property changes, regardless of what triggered them: media queries, user actions, or even other JS. Use cases abound. Here are some of mine: Implement higher level custom properties in components, where one custom property changes multiple others in nontrivial ways (e.g. a --variant: danger that sets 10…

Context Chips in Survey Design: “Okay, but how does it _feel_?”

One would think that we’ve more or less figured survey UI out by now. Multiple choice questions, checkbox questions, matrix questions, dropdown questions, freeform textfields, numerical scales, what more could one possibly need ?! And yet, every time Google sponsored me to lead one of the State Of … surveys , and especially the inaugural State of HTML 2023 Survey , I kept hitting the same wall; I…

Web Components are not Framework Components — and That’s Okay

Disclaimer: This post expresses my opinions, which do not necessarily reflect consensus by the whole Web Components community. A blog post by Ryan Carniato titled “Web Components Are Not the Future” has recently stirred a lot of controversy. A few other JS framework authors pitched in, expressing frustration and disillusionment around Web Components. Some Web Components folks wrote rebuttals ,…

Making the Web more Awesome — for everyone

Folks, I have some exciting news to share. 🤩 Today I start a new chapter in my career. After a decade at MIT , teaching and doing research at the intersection of usability and programming language design, I wrapped up my PhD two weeks ago (yes, I’m a Dr now ! And damn right I will — once it actually sinks in) and today I start my new role as Product Lead at Font Awesome . I will be evaluating…

Forget “show, don’t tell”. Engage, don’t show!

A few days ago, I gave a very well received talk about API design at dotJS titled “API Design is UI Design” [1] . One of the points I made was that good UIs (and thus, good APIs) have a smooth UI complexity to Use case complexity curve. This means that incremental user effort results in incremental value ; at no point going just a little bit further requires a disproportionately big chunk of…

Inline conditionals in CSS, now?

The CSS WG resolved to add if() to CSS, but that won’t be in browsers for a while. What are our options in the meantime? A couple days ago, I posted about the recent CSS WG resolution to add an if() function to CSS . Great as it may be, this is still a long way off, two years if everything goes super smoothly, more if not. So what can you do when you need conditionals right now ? You may be…

Inline conditionals in CSS?

Last week, the CSS WG resolved to add an inline if() to CSS. But what does that mean, and why is it exciting? Last week, we had a CSS WG face-to-face meeting in A Coruña, Spain. There is one resolution from that meeting that I’m particularly excited about: the consensus to add an inline if() to CSS . While I was not the first to propose an inline conditional syntax, I did try and scope down the…

On compliance vs readability: Generating text colors with CSS

Can we emulate the upcoming CSS contrast-color() function via CSS features that have already widely shipped? And if so, what are the tradeoffs involved and how to best balance them? Relative Colors Out of all the CSS features I have designed , Relative Colors aka Relative Color Syntax (RCS) is definitely among the ones I’m most proud of. In a nutshell, they allow CSS authors to derive a new color…

Eigensolutions: composability as the antidote to overfit

tl;dr: Overfitting happens when solutions don’t generalize sufficiently and is a hallmark of poor design. Eigensolutions are the opposite: solutions that generalize so much they expose links between seemingly unrelated use cases. Designing eigensolutions takes a mindset shift from linear design to composability . Creator tools are not Uber or Facebook In product literature, the design process…

Minimalist Affordances: Making the right tradeoffs

Usability and aesthetics usually go hand in hand. In fact, there is even what we call the “Aesthetic Usability Effect” : users perceive beautiful interfaces as easier to use and cut them more slack when it comes to minor usability issues. Unfortunately, sometimes usability and aesthetics can be at odds, also known as “form over function”. Simplicity, and knowing when to stop A common incarnation…

State of HTML 2023 now open!

tl;dr the brand new State of HTML survey is finally open! Take State of HTML 2023 Survey Benefits to you: Survey results are used by browsers to prioritize roadmaps — the reason Google is funding this. Time spent thoughtfully filling them out is an investment that can come back to you tenfold in the form of seeing features you care about implemented, browser incompatibilities being prioritized,…

Numbers or Brackets for numeric questions?

As you may know, this summer I am leading the design of the inaugural State of HTML survey. Naturally, I am also exploring ways to improve both survey UX, as well as all questions. Shaine Madala , a data scientist working on the survey design team proposed using numerical inputs instead of brackets for the income question. While I was initially against it , I decided to explore this a bit further,…

Help Design the Inaugural State of HTML Survey!

You have likely participated in several Devographics surveys before, such as State of CSS , or State of JS . These surveys have become the primary source of unbiased data for the practices of front-end developers today (there is also the Web Almanac research, but because this studies what is actually used on the web, it takes a lot longer for changes in developer practices to propagate). You may…

Going Lean

WordPress has been with me since my very first post in 2009 . There is a lot to love about it: It’s open source, it has a thriving ecosystem, a beautiful default theme, and a revolutionary block editor that makes my inner UX geek giddy. Plus, WP made building a website and publishing content accessible to everyone. No wonder it’s the most popular CMS in the world , by a huge margin. However, for…

Rethinking Categorization

This is the third spinoff post in the migration saga of this blog from WordPress to 11ty . Migrating was a good opportunity to rethink the information architecture of my site , especially around categorization. Categories vs Tags Just like most WP users, I was using both categories and tags, simply because they came for free. However the difference between them was a bit fuzzy, as evidenced by how…

11ty: Index ALL the things!

This is a second spinoff post in the migration saga of this blog from WordPress to 11ty . On good URLs It was important to me to have good, RESTful, usable, hackable URLs. While a lot of that is easy and comes for free, following this principle with Eleventy proved quite hard: URLs that are “hackable” to allow users to move to higher levels of the information architecture by hacking off the end of…

Migrating Disqus from WP to 11ty

So I recently ported my 14 year old blog from WordPress to Eleventy . I had been using Disqus for comments for years, so I didn’t want to lose them, even if I ended up using a different solution for the future (or no comments at all). Looking around for an existing solution did not yield many results. There’s Zach’s eleventy-import-disqus but it’s aimed at importing Disqus comments as static…

JS private class fields considered harmful

Today I mourn. What am I mourning? Encapsulation. At least in my projects. As a library author, I’ve decided to avoid private class fields from now on and gradually refactor them out of my existing libraries . Why did I make such a drastic decision? It all started a few days ago, when I was building a Vue 3 app that used Color.js Color objects. For context, Vue 3 uses proxies to implement its…

Contrast Ratio has a new home — and this is great news!

It has been over a decade when I launched contrast-ratio.com , an app to calculate the WCAG 2.1 contrast ratio between any two CSS colors. At the time, all similar tools suffered from several flaws when being used for CSS editing: No support for semi-transparent colors (Since WCAG included no guidance for alpha transparency — I had to do original research to calculate the contrast ratio range for…

Position Statement for the 2022 W3C TAG Election

Update: I got re-elected !! Thank you for trusting me once more with this huge responsibility towards the Open Web. I will continue to do my best to justify the confidence the W3C membership has placed in me. 🥹 Context: In 2020 , I ran for the TAG election for the first time and had the great honor of being elected by the W3C membership. This year, I’m running for re-election. The W3C Technical…

State of CSS 2022 now open!

Take State of CSS 2022 survey A while ago I posted a call for feedback to inform the design of the State of CSS 2022 survey . The response has been overwhelming and it was glorious. We got quite a lot of proposals , feedback , votes . But that also meant we had to make some tough decisions about what gets in the survey and what doesn’t, otherwise we’d end up with a survey so long nobody would want…

On ratings and meters

I always thought that the semantically appropriate way to represent a rating (e.g. a star rating) is a <meter> element. They essentially convey the same type of information, the star rating is just a different presentation. An example of a star rating widget, from Amazon However, trying to style a <meter> element to look like a star rating is …tricky at best . Not to mention that this approach…

Help design the State of CSS Survey 2022!

Since 2019, the annual State of CSS survey has collected feedback from web developers from across the world to try and take the pulse of the CSS ecosystem, and it’s become a valuable resource not only for CSS developers, but also for browser vendors. This summer, one of my side projects is helping out with survey design and outreach for the State of CSS survey , thanks to a generous Google UI fund…

What is the best way to mark up an exclusive button group?

A few days ago I asked Twitter a seemingly simple question (I meant aria-pressed , not aria-selected but Twitter doesn’t allow edits…) : https://twitter.com/LeaVerou/status/1545712667515654144 For background, I was implementing a web component for an app I’m working on at work and I was getting into some pretty weird rabbit holes with my approach of generating radios and labels. Unsurprisingly,…

Introducing Rety: live coding, without the stress

I recently spoke at CSS Day in Amsterdam. It was only my second f2f talk after the pandemic. It went down really well, both in person, and recently that the video was released: https://www.youtube.com/watch?v=ZuZizqDF4q8 Here is a sample of tweets about it that made me particularly warm and fuzzy inside: https://twitter.com/CSSDayConf/status/1542778793219301376…

Releasing Color.js: A library that takes color seriously

Related: Chris’ blog post for the release of Color.js This post has been long overdue: Chris and I started working on Color.js in 2020, over 2 years ago! It was shortly after I had finished the Color lecture for the class I was teaching at MIT and I was appalled by the lack of color libraries that did the things I needed for the demos in my slides. I asked Chris, “Hey, what if we make a Color…

On Yak Shaving and `<md-block>`, a new HTML element for Markdown

This week has been Yak Shaving Galore. It went a bit like this: I’ve been working on a web component that I need for the project I’m working on. More on that later, but let’s call it <x-foo> for now. Of course that needs to be developed as a separate reusable library and released as a separate open source project. No, this is not the titular component, this was only level 1 of my multi-level yak…

Custom properties with defaults: 3+1 strategies

When developing customizable components, one often wants to expose various parameters of the styling as custom properties, and form a sort of CSS API . This is still underutlized, but there are libraries, e.g. Shoelace , that already list custom properties alongside other parts of each component’s API (even CSS parts !). Note: I’m using “component” here broadly, as any reusable chunk of…

Inherit ancestor font-size, for fun and profit

If you’ve been writing CSS for any length of time, you’re probably familiar with the em unit, and possibly the other type-relative units . We are going to refer to em for the rest of this post, but anything described works for all type-relative units. As you well know, em resolves to the current font size on all properties except font-size , where it resolves to the parent font size. It can be…

Is the current tab active?

Today I ran into an interesting problem. Interesting because it’s one of those very straightforward, deceptively simple questions, that after a fair amount of digging, does not appear to have a definite answer (though I would love to be wrong!). The problem was to determine if the current tab is active . Yes, as simple as that. Why? (i.e. my use case) I was working on my slide deck framework,…

82% of developers get this 3 line CSS quiz wrong

( I always wanted to do a clickbait title like this and when this chance came along I could not pass it up. 😅 Sorry! ) While putting my ideas into slides for my Dynamic CSS workshop for next week, I was working on a slide explaining how the CSS wide keywords work with custom properties. inherit , initial , unset I had used numerous times and knew well. But what about revert ? How did that work? I…

Dark mode in 5 minutes, with inverted lightness variables

By now, you probably know that you can use custom properties for individual color components, to avoid repeating the same color coordinates multiple times throughout your theme. You may even know that you can use the same variable for multiple components, e.g. HSL hue and lightness: :root { --primary-hs: 250 30%; } h1 { color: hsl(var(--primary-hs) 30%); } article { background:…

Mass function overloading: why and how?

One of the things I’ve been doing for the past few months (on and off—more off than on TBH) is rewriting Bliss to use ESM 1 . Since Bliss v1 was not using a modular architecture at all, this introduced some interesting challenges. Bliss is essentially a collection of helper functions. Most of these functions have a number of different signatures , to allow for more compact, readable code. The…

Writable getters

Setters removing themselves are reminiscent of Ouroboros , the serpent eating its own tail, an ancient symbol. Media credit A pattern that has come up a few times in my code is the following: an object has a property which defaults to an expression based on its other properties unless it’s explicitly set, in which case it functions like a normal property. Essentially, the expression functions as a…

Position Statement for the 2020 W3C TAG Election

Update: I got elected!! Thank you so much to every W3C member organization who voted for me. 🙏🏼 Now on to making the Web better, alongside fellow TAG members! Context: I’m running for one of the four open seats in this year’s W3C TAG election . The W3C Technical Architecture Group (TAG) is the Working Group that ensures that Web Platform technologies are usable and follow consistent design…

The case for Weak Dependencies in JS

Earlier today, I was briefly entertaining the idea of writing a library to wrap and enhance querySelectorAll in certain ways. I thought I’d rather not introduce a Parsel dependency out of the box, but only use it to parse selectors properly when it’s available, and use more crude regex when it’s not (which would cover most use cases for what I wanted to do). In the olden days, where every library…

Simple pie charts with fallback, today

Five years ago, I had written this extensive Smashing Magazine article detailing multiple different methods for creating simple pie charts, either with clever use of transforms and pseudo-elements, or with SVG stroke-dasharray . In the end, I mentioned creating pie charts with conic gradients, as a future technique. It was actually a writeup of my “The Missing Slice” talk , and an excerpt of my…

The -​-var: ; hack to toggle multiple values with one custom property

What if I told you you could use a single property value to turn multiple different values on and off across multiple different properties and even across multiple CSS rules? What if I told you you could turn this flat button into a glossy skeuomorphic button by just tweaking one custom property --is-raised , and that would set its border, background image, box and text shadows in one fell swoop?…

The failed promise of Web Components

Web Components had so much potential to empower HTML to do more, and make web development more accessible to non-programmers and easier for programmers. Remember how exciting it was every time we got new shiny HTML elements that actually do stuff ? Remember how exciting it was to be able to do sliders, color pickers, dialogs, disclosure widgets straight in the HTML, without having to include any…

Developer priorities throughout their career

I made this chart in the amazing Excalidraw about two weeks ago: It only took me 10 minutes! Shortly after, my laptop broke down into repeated kernel panics, and it spent about 10 days in service (I was in a remote place when it broke, so it took some time to get it to service). Yesterday, I was finally reunited with it, turned it on, launched Chrome, and saw it again. It gave me a smile, and I…