tailwind
Technical notes on web development, DevOps, and AI integration.
38 articles
- 23:48frontend
Tests That Lock Design Intent, Not Screenshots
Design intent does not survive on documentation alone. A 129-line unit test pins the house classes, so drift breaks the build, not the quarterly audit.
TL;DR: When a fresh restyle kept slipping back to old borders and colors, thicker documentation didn’t stop the drift. So the team shipped a 129-line test that renders components to static markup and checks exact Tailwind classes. It now catches silent design changes in CI and enforces token-only styles before shipping.
#testing#vitest#tailwind - 11:38frontend
12 Commits Just to Stick a Badge on a Mascot's Chest
The technical challenge of placing an ISO badge on a mascot: positioning, border-radius, and CSS animations that don't collide.
TL;DR: Overlaying an ISO certification stamp on a mascot broke on mobile because fixed pixel sizing covered the character's face. Switching to a relative container with aspect-ratio and percentage positioning, or grouping elements in SVG, keeps the badge proportional at any size. Separate badge files per language and aria-labels keep things accessible and localized.
#css#tailwind#nextjs - 10:18frontend
A Sticker on the Wrong Wall: One Brand Mark, Two Files
A dark pill was a patch, not a fix: a brand mark needs two assets the moment a site ships a real, user-controlled dark mode.
TL;DR: A brand wordmark can't work on both themes as one asset, so two Next.js Image components share one slot, toggled with dark:hidden and dark:block—zero JavaScript. The Tailwind v4 gotcha: dark defaults to prefers-color-scheme, not a class, so the override must respect the manual toggle. Filters and single-file hacks fail; two files keep theme state in one place.
#css#tailwind#dark-mode - 10:06frontend
Ditching Manual Height Math at the Bottom of the Page
The taller brand column needed no height math and no JavaScript at all: CSS grid stretch plus one auto margin did the entire job.
TL;DR: While refactoring a site footer, the author nearly wrote JavaScript to measure column heights before realizing CSS grid's default stretch already equalized them. Pinning the company line to the bottom took only flex column plus mt-auto. The lesson: inspect defaults first, since two class names beat any runtime measuring script.
#css#flexbox#tailwind - 09:16frontend
A Font Experiment That Ended in 22 Minutes
Reverting a heading font took one line because every heading reads a single token. Taste experiments can be cheap.
TL;DR: A font experiment on this project lasted twenty-two minutes: one commit swapped the heading token to Source Serif 4, the next reverted it. Because every heading reads a single CSS variable instead of hardcoded font names, the whole trial cost one line each way. The failed taste experiment left behind cheap reversibility and an untouched, durable type scale.
#css#tailwind#accessibility - 09:13frontend
Four Commits Chasing One Vanishing Border
A card border vanished on a muted background because two grays were near-twins. Tokens, contrast, and backdrop assumptions.
TL;DR: The missing borders were never broken code; the border token was nearly identical to the muted background, so the line was invisible. The fix used Tailwind's opacity modifier for a subtle primary-colored border plus a card tint, which also satisfies WCAG 1.4.11 contrast. Per-card icons and left alignment followed; now every component gets tested on every surface.
#css#tailwind#accessibility - 07:27frontend
Three Passes, Less and Less
Three restyling commits, one direction: drop the ring, drop the icon wrapper, delete the duplicated certification strip. Negative diff.
TL;DR: After three restyling passes, the author realized less is more. Removing a decorative span wrapper around Lucide icons let them breathe with thinner strokes and larger sizes, while deleting a duplicated certification strip cut 34 lines. The takeaway: successful restyling is reduction, so run a deletion sweep and ask who would miss each decoration.
#css#tailwindcss#refactoring - 07:27frontend
The Card That Stopped Decorating Itself
Matching a card style turned out to be about deleting decoration and borrowing one shared divider class, not stacking more utilities.
TL;DR: Chasing a calmer card style, the author almost copied utility classes by hand until discovering the clean card used one shared class, reference-divider. The fix was mostly deleting borders, shadows, decorations, and an index prop, keeping only focus-visible and motion-reduce for accessibility. Lesson: prefer shared styles and divide-x/divide-y over duplicated decoration.
#css#tailwindcss#refactoring - 06:55frontend
One Card Component, Two Grids
Copying Tailwind classes from the corporate cards was not enough: the list-item identity and its keyboard handlers had to move too.
TL;DR: Copying Tailwind classes between cards failed because the divider depended on the li-in-ul structure, not styling alone. Converting the office card to a list item meant adding the button role, keyboard handlers, and proper ul wrappers. Extracting an OfficeCard component with two props made the 2+3 layout trivial, though a leftover ul rendered the list twice until deleted.
#react#tailwindcss#accessibility