RSSAmplifier

Blog

A Beautiful Site

A boutique web development studio. Est. 2007

abeautifulsite.netRSS feed ↗190 posts

Latest posts

Contextual Styling With CSS Nesting

I've been hooked on CSS nesting for awhile. Like Sass, I've always written it with the & selector at the front, like this. .button { background: slategrey; &:hover { background: darkslategrey; } } Turns out, the & doesn't have to come first. Put it after another selector and the relationship flips. Instead of styling what's inside the element, you're styling the element based on what surrounds it.…

I'm pulling ColorCopy from the macOS App Store

I launched ColorCopy on May 18. It was my second macOS app, but the first one I launched on the Mac App Store . Today, I decided to pull it. The app isn't a new idea, but it bakes four color tools into a single menu bar app: an eyedropper, a color picker, a palette manager, and a contrast checker, each one a hotkey away. I made it available for free, with a one-time in-app purchase to unlock…

Software Has Changed

A tweet from Jamon Holmgren inspired some thoughts about how software has changed, from a developer's perspective. He says: I've been spending a lot of time talking to experienced software engineers lately and when you get in a 1:1 candid conversation, everyone is rather shell-shocked by how quickly and drastically things have changed. It's true. We're building faster, but not necessarily better.…

I Mostly Stopped Typing

I built the dictation app I wanted. It's called TongueType , and my daughter did the voice over for the video. (Family business.) It hasn't gotten much traction yet, and I think I know why. Dictation was bad for so long that most people stopped paying attention. I don't blame them. I wrote it off myself for years. Alas, that reputation is out of date. The thing that was flaky and frustrating five…

Introducing ColorCopy

My second macOS app, ColorCopy , was approved by the Mac App Store today! It started as a menu bar color picker. Press a key, click any pixel on your screen, and the color lands on your clipboard in whatever format you need. Then I kept finding more things I wanted to put into it. Update (August 2026): ColorCopy is no longer on the Mac App Store. It's now self-distributed and available at…

Introducing TongueType

I just launched my first macOS app, TongueType . It's voice dictation that runs entirely on your Mac. Hold a key, speak, release, and your words appear wherever your cursor happens to be. Why I made it I type fast, but I often think faster than I type. When an idea is fully formed in my head, the bottleneck is my fingers. macOS has had built-in dictation forever, but I never liked relying on it.…

My Stance on AI in Software Development

I believe artificial intelligence is a powerful and valuable tool that can significantly improve how we create, solve problems, and bring ideas to life. I didn't always feel this way. . But these days, I use AI regularly in my work and I expect that to continue. We may not have chosen this reality, but it's the reality we're in. The tools and their benefits — costs be damned — can no longer be…

How I Use GitHub Issues

I like using GitHub issues for actionable things such as bugs and backlog items I've committed to doing. Non-maintainers are encouraged to open issues only for bugs , whereas everything else is a discussion. Bug Report 👉 Issue Help/support 👉 Discussion Ask a question 👉 Discussion Ideas/suggestions 👉 Discussion Waxing Philosophical 👉 Discussion Alas, no matter how clear you make your templates…

Revisiting FOUCE

It's been awhile since I wrote about FOUCE and I've since come up with an improved solution that I think is worth a post. This approach is similar to hiding the page content and then fading it in, but I've noticed it's far less distracting without the fade. It also adds a two second timeout to prevent network issues or latency from rendering an "empty" page. First, we'll add a class called…

Web Components Are Not the Future — They’re the Present

It’s disappointing that some of the most outspoken individuals against Web Components are framework maintainers. These individuals are, after all, in some of the best positions to provide valuable feedback. They have a lot of great ideas! Alas, there’s little incentive for them because standards evolve independently and don’t necessarily align with framework opinions. How could they? Opinions are…

Component Machines

Components are like little machines. You build them once. Use them whenever you need them. Every now and then you open them up to oil them or replace a part, then you send them back to work. And work, they do. Little component machines just chugging along so you never have to write them from scratch ever again. Adapted from this tweet .

Styling Custom Elements Without Reflecting Attributes

I've been struggling with the idea of reflecting attributes in custom elements and when it's appropriate . I think I've identified a gap in the platform, but I'm not sure exactly how we should fill it. I'll explain with an example. Let's say I want to make a simple badge component with primary, secondary, and tertiary variants. <my-badge variant="primary">foo</my-badge> <my-badge…

Reflection and Custom States in Web Components

In the Web Component world, attribute reflection is commonly used to style custom elements both internally and as public APIs for consumers. If you're not familiar, attribute reflection occurs when an attribute in the DOM is updated due to changes in a corresponding property. A lot of folks conflate attributes and properties, so here's an example. <!-- This is the open attribute --> <details open>…

Anchoring Software to Major Versions

In a SemVer world, major releases are those which contain incompatible API changes. We often see software projects anchor themselves to major versions for long periods of time, usually with the promise of stability. We all know how frustrating it is to upgrade a package and run into tons of breaking changes. Many of us have kept outdated software in production for longer than we should just…

Building Custom Elements With a Library

I often get asked why I use Lit to build web components. Hands down, it's become my preference after years of working with various libraries and tools. Here's why I use it. Libraries offer a better DX This seems like a selfish answer for a developer to lean on, but there are advantages to end users as well. A better developer experience (DX) means I can write components and fix bugs faster. In my…

Design Systems Are An Investment

It's hard to put a value on a design system. It's a lot easier to add up the costs of said design system, especially in terms of salaries and development time. It's even easier to target a design system as the thing that's holding up a product from getting delivered. The truth is, design systems aren't made to slow you down or piss you off, they're made to make you more productive. What a lot of…

How to File a Bug Report

They say there's no such thing as bug-free code. When problems arise, creating a minimal reproduction will give you the best chance of a speedy resolution. When a potential bug is discovered, many developers' first reaction is to file an issue. That's great, but please exercise due diligence before posting! Have you reviewed the docs to confirm the behavior in question? Are you able to reproduce…

Thoughts on Framework Churn

I often worry about framework churn. A lot. But using a framework isn't a bad thing. After all, they save time. They help you build things faster. Yes, there are costs associated with frameworks later on , especially as new versions come out and your app instantly feels like legacy software. It can be exhausting trying to keep up, especially when your work schedule doesn't account for that type of…

Better Buttons with color-mix() and Custom Properties

Let's build a button that accepts one color and calculates its hover and focus states automatically. For this experiment, we'll use CSS Custom Properties , color-mix() , and OKLCH to ensure that tints and shades are perceptually uniform. To keep things simple, we'll follow today's flat design trend and use a single color for the background. We'll store that color in a custom property so we can…

Dynamic Slots

Web Component authors already know how powerful slots are, but what if you could do even more with them? Here's an interesting technique to use (or abuse) slots in your custom elements. I've been calling the pattern dynamic slots . Before we dive in, let's take a quick look at how slots actually work. Here's a custom button with a label and an image. <my-button> Click me <img slot="icon" src="..."…

My Commitment to Accessibility

I recognize the need for all users, regardless of ability or device, to have undeterred access to the websites and applications that are created with my software. This is an important goal of my projects. Oftentimes, people will ask "is it accessible?" I'm reluctant to answer because accessibility isn't binary — there's no simple "yes" or "no" response to provide. What seems accessible to a…

Converting a URL Object to a Plain Object in JavaScript

I needed to convert a URL object to a plain object yesterday. You might have used it before. It's pretty handy for working with URLs! const url = new URL('https://example.com/'); console.log(url); // URL {origin: 'https://example.com', protocol: 'https:', username: '', password: '', host: 'example.com', …} Alas, you can't provide a URL object as data to Handlebars for security reasons .…

The Term "Headless Component" is a Misnomer

You've likely heard the term "headless component" tossed around. The idea is you get solid, accessible components without any styles. A clean slate to style from scratch! But the structure (bones) and logic (head) are there. You're mostly adding styles. They should be called "skinless components." And the thing about headless components is that, in my experience, people actually don't want to…

Shoelace 2.0

It's been three years since I broke ground on Shoelace 2.0 . Between then and now, the project has amassed over 300 million monthly hits on jsDelivr and, as of today, it is jsDelivr's 73rd most popular project . And that was just the beta version. Today, I'm happy to announce that the first stable release of Shoelace is finally available! First and foremost, I'd like to say thank you to all my…

Installing Shoelace in a React App

Although Shoelace is a web component library, it ships React wrappers that lets you use the library idiomatically in React. This video shows you how to install Shoelace in a brand new Create React App . If you found this video helpful, please subscribe to my channel on YouTube and follow me on Twitter for more helpful Shoelace tips!

Why You Should Prefix Custom Events

Similar to how every custom element must contain a dash, I like to pretend that every custom event must also contain a dash. This removes all ambiguity between native events and custom events. Therefore, I prefix all custom events in Shoelace with sl- . It may seem contradictory that I've chosen to follow the platform's convention for emitting events but not for naming them. There's a good reason,…

Custom Event Names and the Bubbling Problem

The topic of custom element event names comes up every now and then, especially from Shoelace users who get confused when events of the same name are emitted from different components. Take <sl-details> , <sl-dialog> , and <sl-dropdown> , for example. They all emit sl-show and sl-hide events, allowing you to hook into their lifecycle as they open and close. Occasionally, someone will nest a…

The Future of Shoelace

It's been more than two years since the beta release of Shoelace 2.0 , which was the first version of the project to ship Web Components. What started off as a fun side project has quickly grown to become one of the most recognized Web Component libraries in the world. As of today, Shoelace receives more than 100 million monthly CDN hits on jsDelivr , and that number continues to grow. Thank you…

A Web Component Story

Gather 'round, it's story time. A number of years ago, I was hired by a company to rebuild a component library for their design system. The one they were replacing was built with AngularJS, but AngularJS was old and rickety and nobody wanted to use it anymore. Plus, many teams had moved on to other frameworks and one team even preferred doing everything with vanilla JS. But the company couldn't…

Not Everything Can Be Feature Detected

In the early days of Web browsers, it was extremely common to see user agent checks in JavaScript. Sometimes, you'd write the same code in two or three different ways to support various browsers. Code such as that shown below allowed webpages to work in browsers like Netscape Navigator and Internet Explorer, who didn't always agree on how features should be implemented. if…

Buttons and Cursors

There's a post from 2016 entitled Buttons shouldn't have a hand cursor that's been making its way around social media this week. While the author is correct in his statement that operating system buttons don't have hand cursors, the pattern has become ubiquitous and somewhat expected on the Web. Some of his points include: When a button has the hand cursor, it subtly suggests that the user is…

My Stance on AI-generated Code

2026-04-20 - Times change, and so do feelings. Please see this post for my latest thoughts on the matter. I recently added this to Shoelace's contribution guidelines , which sums up my position on AI-generated code. As an open source maintainer, I respectfully ask that you refrain from using AI-generated code when contributing to this project. This includes code generated by tools such as GitHub…

Design Systems Aren&#39;t Cheap

Buttons are one of my favorite components. On the surface they seem simple, but in practice, they tend to be much more involved. In a post by Nathan Curtis entitled And you thought buttons were easy? , he demonstrates how costs can quickly skyrocket to $1,000,000 when one arm of the organization isn't aware of what the other is doing. This is easy to brush off as an extreme example that only…

CSS Parts Inspired by BEM

In a previous post, I explored valid names for CSS parts and discovered that there are very few restrictions in what you can call them. The purpose of that deep dive was to help identify a pattern for naming parts that lets me expose states and subparts , or parts exported as a result of composition. Using inspiration from BEM , I've settled on a familiar and intuitive pattern that I'd like to…

When To Create CSS Parts

I was recently asked a really good question on Twitter: when shouldn't an element be a CSS Part? I've spent a lot of time building web components, most of which are intended for design systems, and my answer is pretty straight-forward. Every part you expose is an API that you're committing to supporting, so it should be very intentional. Consider a component that uses a complex structure that you…

Valid Names for CSS Parts

CSS Shadow Parts , colloquially known as CSS Parts , are used to expose elements inside a web component's shadow root so they can be styled by consumers with CSS. But what are we allowed to call these parts? What characters comprise a valid CSS part name? To find out, I had to dive into the spec ! The part attribute is parsed as a space-separated list of tokens representing the part names of this…

Complacency on the Front End

We live in a world where front end developers are fatigued from the framework wars. Most have settled into a niche — especially the React crowd — and they’re happy to not have to think outside that box. They are, by far, the hardest crowd to sell web components to. I'm not knocking them. They went through hell trying to keep up with things and ended up finding something that made sense and worked…

A Web Components Primer

On the eve of February, I was inspired to tweet about web components . What started as a simple thought quickly turned into a series of tweets that folks seem to find useful. I've adapted the thread and I'm posting it here for prosperity. Overview Shadow DOM? Light DOM? Slots? If you've heard of these but aren't sure what they are, maybe this will clear things up! Custom elements are a feature…

Success Requires Luck

I've concluded that successful "makers" have one thing in common: luck. It's not that strategy and vision don't play a role in success, but nobody — literally nobody — can guarantee that a product or service will be successful. Think about some of the major corporations that launched new products, throwing tens of millions of dollars into research, development, and marketing, only to see their…

Flash of Undefined Custom Elements (FOUCE)

Update (December 23, 2024): Check out my latest post on this topic: Revisiting FOUCE Web components are defined and registered with JavaScript. Depending on how and when you load the scripts that perform registration, you may see a brief flash of unstyled HTML where your custom elements should be when the page loads. This is not dissimilar to FOUC , which occurs when HTML is displayed before the…

Bulletproof Components

Somewhere buried in my dusty basement lives a signed copy of Dan Cederholm's classic book Bulletproof Web Design . I purchased it during my first trip to An Event Apart in 2007. This book meant a lot to me back then, and almost 15 years later, many of its concepts still hold true. The premise of the book is that designs should be "bulletproof" to accommodate the many ways they can be used. I'm…

Empowering Design System Users

The question of whether or not component APIs should be locked down at the code level comes up quite a bit. For example, if a button spec only calls for primary, secondary, and tertiary variants, should we still expose parts and custom properties so users can make further customization as needed? In my experience, the answer is "yes." The arguments for locking things down seem to stem from…

Exploring the EyeDropper API

The EyeDropper API has landed in Chrome and Edge 95 ! This is a simple promise-based API that lets you select a color from anywhere on the screen. Let's dive in and see how it works. To start, we'll add a button that activates the eye dropper. <button type="button">Select a color</button> When the button is clicked, we'll launch the eye dropper. As soon as the user selects a color, we'll update…

The Future of Frameworks

Love them or hate them, web components ("custom elements") are making a huge dent in the world of front-end development. As of today, close to 18% of page views in Chrome are registering web components. That's an insane amount of usage! The benefits of a framework-agnostic component model are becoming obvious to web developers, particularly those who have built the same components over and over…

Superpowers

I stumbled upon a short post that intrigued me. In it, the author claims that the cure for boredom is superpowers. Not superpowers in the Superman sense, but ones that we can teach ourselves. Learn Photoshop, and you’ll have a superpower. You’ll be able to see what your bedroom would look like with blue walls, improve the lighting in your craigslist posting, make custom christmas cards, do your…

Know When To Draw The Line

One-off variations aren't uncommon, but they don't belong in your design system. You're design system isn't solving for every possible use case — it's encouraging visual consistency and efficient development. Use custom styles for one-offs. This came up recently on my team. We have a button component that supports prefix icons. By default, the icon color matches the text. In one design, the same…

Don&#39;t Do Magic

We recently had a design for an "alert" component with an actions slot. In the spec, only secondary buttons were allowed in it. Dev: "Design only wants secondary buttons in the actions slot, so I'm forcing it." The developer was listening for the slotchange event and applying the secondary variant to all buttons in the slot automatically. The idea was to prevent consumers from using the wrong…

On Buttons and Links

I posted a tweet yesterday that was met with some controversy, so I thought it would be a good idea to unravel it. Unpopular opinion: in a design system, a "link" and a "button" should be one component. &mdash; Cory LaViska (@claviska) October 5, 2021 At face value, I understand why people are upset with this. It's hard to provide context in 280 characters, though, so I made it a thread . That was…

On Using Web Component Libraries

We tend to think of components as things that belong to a framework. After all, React has components, Vue has components, Angular has components…it's just how we've always used them. Because of that, people tend to refer to Lit and FAST Element as frameworks, but they’re not. They’re libraries , and that’s an important distinction. If you want a React component to work, you have to use it with…

Finding the Closest Element Through Shadow Roots

A great trick to find the closest element in the DOM that matches an arbitrary selector is Element.closest() . // Starts at el and walks the DOM until it finds a parent element // that matches the selector. In this case, it will return the // <body> element. el.closest('body'); But what happens if you do this from inside a custom element's shadow root ? someElementInShadowRoot.closest('body'); By…