Accessibility
Memory Bank: Labels In HTML
Explains how to properly label HTML elements for accessibility. It covers methods like using the <label>
element, aria-labelledby
, and aria-label
, recommending visible labels whenever possible. The title
attribute is discouraged for essential info due to poor accessibility.
How to Audit Web Accessibility with WAVE Extension
Auditing with WAVE gives you immediate, visual insights into your site’s accessibility. While it won’t replace thorough manual testing or user feedback, it’s a powerful tool for catching common problems, learning best practices, and making accessibility part of your development culture.
Tables: Beyond Rows and Columns
This article explains the best way to use semantic table markup to present web content in accessible rows and columns.
A Quick Primer on Accessible Pagination
Pagination is a common feature across many websites, from news archives and product listings to blogs and search results. Despite its simplicity on the surface, pagination is one of those UI patterns that can be surprisingly nuanced when it comes to accessibility. Most developers implement it using visual styling alone, assuming it “just works.” Unfortunately, that’s rarely the case for users relying on screen readers or keyboard navigation. In this primer, we’ll look at what it means to build pagination that is truly accessible and demonstrate how to do so with clean, semantic HTML and just enough CSS to make it practical.
Common misconceptions about screen readers
Screen readers are familiar to many in digital, but how they work in practice can be less clear. In this post, we shed some light on the topic.
Screen Reader HTML Support – Lookup
Documents how different HTML elements are supported across screen readers, browsers, and operating systems.
Accessible form validation with examples and code
The article explains how to create accessible form validation by using custom error messages, summaries at the top of the form, and clear inline feedback. It emphasizes disabling default browser validation, supporting screen readers, and guiding users with clear focus and messaging.
Make Navigation Accessible with aria-current
Learn when 'you are here' needs aria-current
. Simple examples for navigation, breadcrumbs, and multi-step processes. Give screen readers navigation context.
CSS
A tiny bit-o-CSS for Stable Scrollbar Gutters
To show scrollbars only when they’re needed (while keeping space for the scrollbar if it’s added later) use the scrollbar-gutter
CSS property. scrollbar-gutter
is Baseline 2024 Newly Available, so make sure you enhance it with a @supports
guard.
Conditional Border Radius with Modern CSS
A simple trick to control the border-radius
based on the screen/container size.
Dynamic Tooltip Position with Anchor Positioning (Part 2)
In the previous post, we created a tooltip that flips between two positions to remain visible. It's either on the top or the bottom. We can adjust the code to do the same with four positions (top, bottom, left, and right). And whatever the position of the tooltip, the tail will always point to the anchor.
Fluid Headings
There’s no shortage of posts that explain how to perform responsive typography.
However, in those articles no one really mentions what qualities you are meant to look out for when figuring out the values. I’ll admit the closest article to this is the first article which explains that if you use only viewport units for a font-size
that it’ll break the zoom expectations in the browser, which will cause a WCAG 1.4.4 failure. The recommendation there is to always include a non-viewport unit in the calculation with your viewport unit.
Well, I’m about to turn that on its head.
What I set out to do is to have a rule that helps explain what the transition should be for heading font sizes between large and small screen sizes. In other words, what the middle value of a CSS clamp()
function is expected to be.
Tailwind CSS in React and Next.js: A Complete Setup Guide
This comprehensive guide walks you through setting up Tailwind CSS versions 3 and 4 in both React and Next.js projects, covering installation steps, configuration, component patterns, dark mode implementation, best practices, and common troubleshooting scenarios.
The new progress() function in CSS
Imagine a responsive hero image that becomes more transparent as the viewport gets narrower, helping text readability on small screens or a card that scales up slightly as the viewport grows, adding a subtle polish.
Until now, achieving these effects required complex calc()
expressions or JavaScript, often leading to brittle solutions. But with the new CSS progress()
function, you can express these relationships cleanly and intuitively.
HalfStyle - Style Half of a Character by CSS
HalfStyle is a set of advanced CSS rules that allow styling each half or third of a character, vertically or horizontally, independently and individually.
Works on any dynamic text, or a single character, and is all automated. All you need to do is add a class on the target text and the rest is taken care of.
It also preserves the original text's accessibility for screen readers for the blind or visually impaired.
CSS Grid: A helpful mental model and the power of grid lines
What’s the right mental model for thinking about Grid? What do all the new terms mean? What’s with that “/” anyway? If you have these questions and struggle to wrap your head around Grid, you’re not alone. There’s a lot of stuff to learn. Let’s see if we can unpack and explore it together, and make grid a little more comfortable to use.
Dynamic Styling with calc() in TailwindCSS
Use calc()
in TailwindCSS for responsive, dynamic styling. Explore practical examples for layouts, custom designs with its utility-first approach.
A Complete Guide to CSS Logical Properties, with Cheat Sheet
CSS logical properties offer a new way of declaring properties, such as width, height, padding, margin, and border, based on the direction of text instead of the physical dimensions of a computer screen.
Logical properties are adaptable to changes in text direction, making them especially useful for websites with multiple language versions. They also offer advantages for monolingual websites, such as adaptability to changes in text direction due to media or container queries.
Modern CSS Round-Out Tabs
Explains how to create modern, rounded tab designs in CSS using the shape()
function and clip-path
. This technique allows for smooth, connected tab shapes without extra HTML, making the code cleaner and more flexible.
Alignment in Anchor Positioning using position-area
An interactive demo to understand how to control the alignment using the position-area
property.
Making Context-Aware Components: How CSS inherit() Could Simplify Design Systems
Make your components context-aware with CSS inherit()
: learn how the new inherit()
function lets components derive spacing, colour and motion from their container, reduce token bloat, and implement robust fallbacks for browsers that don’t yet support the feature. Practical card examples included.
HTML
HTML—the Most Difficult Programming Language in the World
If HTML is a programming language, yet virtually no one writes error-free HTML code, there can be only one conclusion:
HTML is the most difficult programming language in the world.
When to Use Modal vs Dialog Components
Confused about modal vs dialog components? Discover implementation patterns, accessibility guidelines, and best practices for creating user-friendly interfaces.
JavaScript
The killer feature of Web Components
One unsung feature in the web components space that I don’t think gets enough attention is the Custom Elements Manifest initiative. I think it’s the killer feature of web components.
How to group arrays in JavaScript without reduce()
Ditch the reduce()
boilerplate. Learn how to use Object.groupBy()
and Map.groupBy()
in JavaScript to group data with cleaner, more expressive code.
Vue Basics: State Management in Vue
Learn how to scale Vue state management with ref/reactive, props/emits, provide/inject and Pinia as your app grows.
How to Animate WebGL Shaders with GSAP: Ripples, Reveals, and Dynamic Blur Effects
A hands-on guide to animating WebGL shaders with GSAP, exploring how to control shader uniforms and sync JavaScript timelines.
Alpine AJAX
A set of AlpineJS directives that enable forms and links to make asynchronous HTTP requests and render the response to the page.
Miscellaneous
How modern browsers work
This article dives into how modern browsers work - focusing on Chromium's architecture and internals, while noting where other engines differ. We'll explore everything from the networking stack and parsing pipeline to the rendering process via Blink, JavaScript engine via V8, module loading, multi-process architecture, security sandboxing, and developer tooling. The goal is a developer-friendly explanation that demystifies what happens behind the scenes.
Most Job Seekers Skip Negotiation — and Pay a High Price
Job candidates who negotiate their compensation prior to hiring usually walk away with noticeably higher salaries, better benefits or both, according to a long-established consensus of research. Yet well over half of job seekers still just accept the initial offer.
10 things I have learned doing design systems
Every design system starts with enthusiasm — and almost always with an underestimation of what lies ahead. Over the years, I’ve seen systems appear, grow, and disappear. Some collapsed under their own weight, others stayed alive and helped teams work better.
With time, I realized: a design system is not a tool, but a process — one that goes far beyond components and color sets.
Here are ten things I’ve learned from building them again and again.