frontend
Technical notes on web development, DevOps, and AI integration.
104 articles
- 13:28frontend
Gradient Text Turned Into a Color Box: the Shorthand That Resets
A theme override using the background shorthand silently reset background-clip:text from the base rule, so gradient text rendered as a solid color box.
TL;DR: A CSS background shorthand silently reset background-clip:text, turning gradient text into a solid color box. Swapping to the background-image longhand fixed it, since the base rule's clipping stayed intact. Lesson: the background shorthand resets what you don't set, so per-theme visual checks are now mandatory before pushing.
#css#frontend#tailwind - 12:58frontend
The Footer Icons That Vanished When the Card Turned White
Hardcoded white GitHub and Next.js icons disappeared the moment the light-mode footer card turned solid white. The fix: var(--foreground).
TL;DR: Fixing the footer card to solid white made hardcoded white icons vanish on white. Swapping every #ffffff in Footer.tsx for var(--foreground) lets icons adapt automatically across themes. Same for the neon gradient: added a denser light-mode variant so it stays visible on white.
#css#frontend#tailwind - 12:39frontend
The Transparent Card That Vanished in Light Mode
Cards styled bg-card/20 through /90 nearly vanished in light mode because Tailwind v4's opacity modifier compiles to color-mix with a token variable.
TL;DR: Tailwind's opacity modifier compiles bg-card/50 into a color-mix() blend against the --card CSS variable, so the same class renders differently per theme. Dark mode contrast hid the issue; light mode made white blends at 20–90% opacity melt into the background. The fix: a light-mode CSS override forcing solid card colors, with shadows for depth instead of alpha.
#css#tailwind#frontend - 11:28frontend
I Replaced My Blog Carousel With a Boring List
The five latest posts were trapped in a swipe-one-by-one carousel. For navigation content, a plain vertical list is the honest pattern.
TL;DR: The author shipped a carousel for their latest blog posts, then found it tedious to use themselves. The realization: carousels suit fixed showcases like services, but blog lists are navigation, which needs everything scannable at once. They swapped it for a plain vertical list of five titles with dates, no JS or gestures.
#ux#mobile#frontend - 11:16frontend
I Rejected Carousels. Then I Built One.
Five service cards stacked on a phone became an endless scroll. A script-free carousel with CSS scroll snap turned out to be the honest middle ground.
TL;DR: The author turned five stacked mobile service cards into a pure CSS carousel using scroll snap, no JavaScript needed. Unlike typical carousels, it skips auto-rotation and shows an 80vw peek of the next card, so users know there's more. Desktop keeps the grid layout via a media query.
#css#ux#mobile - 10:49frontend
Five Cards and the Copy Problem
My portfolio had a bare list of projects. I added five capability cards: the CSS grid was solved in twenty minutes. The copy took three rewrites.
TL;DR: The CSS grid for his portfolio's service cards was the easy part, done in 20 minutes with MDN's auto-fill recipe. The hard part was the copy, which took three rewrites to compress into short, blunt descriptions that never truncate. His take: layout is a solved problem, so spend the effort on content, equal heights, and a consistent shadow.
#css#ux#frontend - 22:45frontend
I Filled the Textarea, React Never Noticed
The text visibly entered the textarea, yet React never saw a change. Why plain assignment fails on controlled components and how the native prototype setter fixes it.
TL;DR: Automating React apps like DeepSeek fails when you set textarea.value directly, because React replaces the setter on each element instance and swallows non-user input events. The fix: grab the native setter from HTMLTextAreaElement.prototype, call it with your text, then dispatch a bubbling input event. Since the icon-only send button has no label, press Enter instead.
#deepseek#react#automation - 02:49frontend
The Chat DOM Only Holds Half the Answer
Scraping an AI chat answer from the DOM gets you half of it. The full text lives behind the Copy button, plus a strict output contract.
TL;DR: Chat UIs use virtualization, so most of the AI's answer never exists in the DOM and scrolling won't load it. The fix layers a Copy-button click to read the clipboard, an accessibility tree snapshot, and innerText as fallbacks. The real win: define an output contract upfront — code block plus sentinel marker — so scraping becomes deterministic.
#automation#playwright#llm - 15:39ai
That Time a Control Flag Showed Up in the Chat Bubble
A raw CTA_FLAG: YES marker leaked into a live chat bubble. The strip regex only matched end-of-string, and the SSE stream bypassed it entirely.
TL;DR: A CTA_FLAG marker leaked into the UI because the model ignored placement instructions and SSE streaming sent chunks before the strip regex ran. The fix moved CTA data into a structured field on the knowledge source, rendered directly by the frontend. Lesson: never parse UI-critical data out of model prose; use structured fields.
#llm#streaming#sse