|||

Buttons with CSS

Going back from all-utilities to plain CSS for styling buttons has made my life easier.

Please note: I have zero interest in taking part in that dreaded love/hate Tailwind argument that cooks up every other month on social media. These are just some reflections about how I’ve been doings thing for years, and what I consider changing.

Starting with buttons

As a part of reevaluating the use of utility CSS in various use cases, the ubiquitous button component is one of the first instances where I’ve decided to go back to vanilla CSS. It has become tedious to change things, add additional variants or add template logic.

So I’ve removed those utilities from the button component’s markup:

Git diff showing how utility classes were replaced with (content-derived) semantic class name

I’ve just moved those rules in a file called button.css , as a first step by just dumping all rules into the CSS using Tailwind’s @apply . (I’m aware that using @apply is not the best or even encouraged way, but it’s a good bridge to move quickly).

I came for better maintainability, I stayed for contextual overrides

The big bonus: By writing good old CSS it becomes very simple to override a button variant based its context. This saves a lot of template logic or editor work. The cascade is, of course, as old as CSS itself, but I confess I kind of forgot about its possible usefulness.

Example: Change button appearance if used inside a container with dark background

Say this is our default styling for a primary and secondary button:

.button {
    @apply font-semibold inline-flex items-center border-2 gap-2 py-4 px-6 rounded-full leading-none no-underline select-none motion-safe:transition hover:shadow-lg active:translate-y-0.5;
}

.button--primary {
    @apply bg-primary text-white border-primary hover:shadow-primary-600/30 focus-green;
}

.button--secondary {
    @apply text-blue-950 border-cream-200 hover:bg-white/30 hover:shadow-cream-600/20;
}

This creates a secondary button with a transparent background, dark text and a subtle border. It work’s great on a light background:

Screenshot showing a button on a with dark text on transparent background

But when put on a dark background, it fails:

Screenshot showing a button on a with dark text on transparent background, but now placed on a dark blue background. The button becomes hard to read.

Now, we could create a new button variant. Then we’d write some template logic to use that new variant at the right time, such as when the button is placed inside a certain component. Or we put the burden on the editor and make them choose the correct variant in the CMS. Then they need to choose a button variant based on hierarchy and visual design. Both makes things more complicated. Let alone that we’re still talking about a secondary-level button from a UX hierarchy.

This is a perfect use case to embrace the cascade and just override the secondary button’s default styling — depending on the component it’s used within:

/* Buttons on dark background need some overrides */
[data-component="night_slide"],
[data-component="cta"] {
    .button--secondary {
        @apply bg-white border-white focus-white;
    }
}

And we’re done.

The once hard to read button now has a white background and is readable against a dark background

This seems almost too obvious and I’m really curious where this journey will take me 😊

Up next Expand Basic Markdown Formatting in Apple Notes Tailwind and Web Craftsmanship Rob articulates my feelings in this whole stupid “Tailwind vs Vanilla CSS” argument. Thanks Rob! Gatekeeping and framing in web development There’s
Latest posts Back to MyMind Sending Articles from Feedbin to Readwise Reader In Praise of Sublime App Why I Ended Up Using Todoist Yet Again Pros and Cons of Reflect Notes App A Love Letter to Sublime Internet Lazy.so is an amazing tool. Here's why I don't keep it Carl Sagan has shown the absurdity of not acting against climate change back in 1990 A success message that communicates the opposite of success Epomaker TH80 Pro Polyamor, aber mit PKM apps 🫣 Ironie, die Fabi Rommel Helft der Natur Tiny Garden Paradise Schwiegerfuchs Same Vibe Tailwind and Web Craftsmanship Buttons with CSS Expand Basic Markdown Formatting in Apple Notes Cannot Divide by Zero in Peak Picture Partial Applying a Growth Mindset (Doodle) Using the AVIF format for CSS background images Workaround for Email Validation Issue in Statamic A First Quick Look at Cosmos.so – and Why I'll Stick with MyMind Install a Starter Kit from local repo to get the latest Peak working in Statamic 4 beta Set sensible validations for Statamic image uploads Render first heading inside Statamic Page Builder as `h1` My PKM App Stack for 2023 Favorite apps in recent weeks: mymind & Craft First List Item inside CSS Multi Column Layout is offset