Adam Argyle's Avatar

Adam Argyle

@nerdy.dev.web.brid.gy

CSS DevRel @Google on Chrome, @CSSWG, co-host @CSS Podcast, co-host Bad @ CSS, host @GUI Challenges. Web design & development tips & tricks: CSS, JS, HTML, Design, & UX.

196
Followers
0
Following
279
Posts
18.07.2024
Joined
Posts Following

Latest posts by Adam Argyle @nerdy.dev.web.brid.gy

Preview
View Transitions can swoop‽ Like Zoolander who can't turn right, I thought View Transitions couldn't swoop. I had been under the impression that they couldn't curve towards the destination, and it was one of those things that you like **can't unsee**. All view transitions going in straight lines… CodePen All my prior attempts had failed, til now. ## The way of the swoop # When you give something a `view-transition-name` like: #ball1 { view-transition-name: view-transition-ball; } ` The browser creates keyframes with a predictable naming pattern: @keyframes -ua-view-transition-group-anim-view-transition-ball { … } ` If you pause a view transition, you can see the keyframes and the keyframe name applied to the pseudo elements: _Anticipating that_ naming consistency, add a comma to the `::view-transition-group()` element and include some keyframes of our own: ::view-transition-group(view-transition-ball) { animation: -ua-view-transition-group-anim-view-transition-ball 2s ease-in-out, /* 👉*/ swoop 2s ease-in-out; } ` The special sauce, the THING THAT TOOK FOREVER TO FIND, is that you can **only use individual transforms, NO`transform` shorthand**: @keyframes swoop { 50% { /* ❌ */ transform: translateY(50px); /* ✅ */ translate: 0 50px; } } ` If you try to change the transform, things fail. And if you try to add `animation-composition`, things fail harder (don't know why). BUT, using individual transforms, and just like that, you can blend a scale, translate, or whatever in combination with the browser native transition. **The trick also shows you how you can add a blur to a view transition.** CodePen "The key to the unlock was individual transforms." Below is a demo you can try that makes a simple wiggling view transition. The green ball uses custom keyframes and animation composition, and the pink ball uses view transitions. They dont perfectly match either, which is interesting (exaggerated with a scale added). There's a perspective difference at play I don't fully understand. See the Pen by Adam Argyle (@argyleink) on [CodePen. You can stop reading here if you want, but I'm about to rant about how this was lame as crap to discover. The limits # While I'm glad there's a little bit of a way for it to work, there's plenty to still want. * No access to the dynamic values that the browser calculates for view transitions * The solution is clunky and requires static `view-transition-names` (no `match-element` support), it breaks if the browsers name their keyframes something else or if I'm assigning names with JS * No support for `animation-composition: add` * No way to control the easing of the x vs the y axis separately, or separate durations I really just wanted to change the `X` easing to be `ease-out` and the `Y` easing to be `ease-in`. That would give a nice swoop. Or even add a slight delay the `X` and not the `Y`, another way to create a swoop. None of these more normal and better ergonomic ways are available. Just this narrow case with individual transforms and trying to piggy back on a browser keyframe naming convention. But hey, now we can add swoops to a native view transition and we learned a trick that can make motion blur view transitions. That's coo.
07.03.2026 05:32 👍 0 🔁 0 💬 0 📌 0
Preview
WWW Ep234 Pay No Attention To The Llm Behind The Terminal With Zach Lloyd Of Warp Ep #234 **Pay No Attention to the LLM Behind the Terminal withZach Lloyd of Warp** Robbie and I chat latest agentic workflows with the CEO of Warp, digging into our favorite features, cloud agents with Oz, some delicious smokey whiskey and some whatnot. ⤷ whiskey.fm · youtube · spotify · apple
05.03.2026 18:29 👍 0 🔁 0 💬 0 📌 0
Preview
Things Openclaw Is Making Me Hello personal software: * A Shopify store (TBA) * Beer tracker * Whiskey tracker * My own guitar songbood * My own banjo songbook * Birthday tracker
02.03.2026 03:34 👍 0 🔁 0 💬 0 📌 0
My OpenClaw Token Dashboard First off, I call my OpenClaw assistant "Punk Ass," short for "Punk Assistant." It's been great so far having a punk ass for various projects. I hadn't been using my gaming machine much; now it's a work horse. But, when you're running an AI assistant that handles Discord messages, cron jobs, and various projects; costs add up. But where exactly? I directed a simple dashboard to find out. ## How It Works # OpenClaw stores session logs as JSONL files. Each assistant response includes token counts and costs. I had a Node.js script written that extracts this data, cross-references it with Discord thread metadata embedded in each conversation, and aggregates everything by thread, day, model, and session type. The output is a single static JSON file that powers an Astro dashboard. No backend needed, just parse, deploy, and refresh when you want updated data. ## What I Track # I track a few things that help me make keep costs low: * **Cost per Discord thread** Which conversations are burning tokens? * **Daily spend trends** Are costs stable or spiking? * **Token breakdown** Input vs output vs cache hits * **Session types** Discord vs cron jobs vs direct chat ## What I Learned # The data was immediately actionable. Two threads accounted for 60% of the total spend: a Shopify web store project ($73) and the `#general` channel ($70). The store project made sense, I've been async art directing it alot. It's looking **sweet**. But `#general`? That's just a catch-all channel accumulating context from random conversations. Expensive by accident. ## The Fix # Now I know: long-running threads in Discord are context traps. Each message carries the full conversation history. The solutions: * Start fresh threads for new topics instead of continuing in the same one * Have OpenClaw delegate to sub-agents for self-contained tasks as they don't carry the parent context * Treat `#general` as a lobby, not a workspace The dashboard cost less than a dollar to make. But now, knowing where tokens go changes how I work with OpenClaw, I'll earn all that buck back quick; I can stop guessing and start optimizing.
02.03.2026 03:15 👍 0 🔁 0 💬 0 📌 0
Preview
CSS Scroll Driven Gyro Trig Experiments scroll-driven geometric orbit experiments * Triangles * Atomic * Squares * Orbits Featuring billboarding, center of mass pivoting, and CSS trig functions.



[Video] [Original post on nerdy.dev]

27.02.2026 16:13 👍 0 🔁 0 💬 0 📌 0
Preview
WWW Ep233 Humans Are Now Legacy Dependencies Ep #233 **Humans Are Now Legacy Dependencies** Robbie and I chat agentic workflows, OpenClaw, Pi, malleable software, some whiskey and some whatnot. ⤷ whiskey.fm · youtube · spotify · apple
27.02.2026 03:57 👍 0 🔁 0 💬 0 📌 0
Preview
WWW Ep232 No Ralph Wiggum No Training Wheels Just Agents Ep #232 **No Ralph Wiggum. No Training Wheels. Just Agents.** * do Ralph Wiggum loops automatically produce better results? * is context pollution killing productivity? * the rise and fall of MCP servers and skills * why vanilla Claude might be the only tool you actually need * CSS anchor positioning failures * Stranger Things hot takes * why small distilleries are just like indie startups ⤷ whiskey.fm · youtube · spotify · apple
19.02.2026 19:16 👍 0 🔁 0 💬 0 📌 0
Preview
WWW 231 We Stopped Coding By Hand Ep #231 **We stopped coding by hand because agentic AI is too good** Robbie and Chuck dig into agentic AI loops, the rise of prompt-driven development, whether coding by hand is officially dead, and what happens when tools like OpenCode and Claude become the new normal. ⤷ whiskey.fm · youtube · spotify · apple
13.02.2026 05:09 👍 0 🔁 0 💬 0 📌 0
Preview
Site Updates Feb 2026 **Site Updates** * New persona filtering on desktop * Deno KV social data caching * new Codepen 2.0 editor support * UI fixes * Notebook update (added Color Picker) * Server analytics added to Notebook * Server page views and active users integrated into UI
08.02.2026 06:36 👍 0 🔁 1 💬 0 📌 0
Preview
Scaley Mask Image Hover img:hover { scale: 1.2; clip-path: inset(10% round 20px); } ` nice, n' simple (codepen)



[Video] [Original post on nerdy.dev]

08.02.2026 04:08 👍 0 🔁 0 💬 0 📌 0
Preview
WWW Ep230 We Accidentally Deleted Programming <img alt="Whiskey web and whatnot episode 230" height="600" src="https://nerdy.dev/media/www-ep230.jpg" style="display: none;" width="600" /> <p><span class="Tag">Ep #230</span><br /> <strong>We accidentally deleted programming</strong></p> <p><a href="https://robbiethewagner.dev">Robbie</a> and I dig into the shift from code-first to spec-first development, whether TypeScript still matters in an AI-driven world, the rise of agency over specialization, and why the future might belong to prompt-driven tinkerers instead of traditional developers.</p> <p>⤷ <a href="https://whiskey.fm/we-accidentally-deleted-programming-presented-by-coderabbit">whiskey.fm</a> · <a href="https://www.youtube.com/watch?v=9w_5Pstg1zk">youtube</a> · <a href="https://open.spotify.com/episode/26nuPJwftZKwMzi00p95sz">spotify</a> · <a href="https://podcasts.apple.com/us/podcast/we-accidentally-deleted-programming-presented-by-coderabbit/id1552776603?i=1000748337252">apple</a></p>
06.02.2026 00:39 👍 0 🔁 0 💬 0 📌 0
Preview
Nice Select <img alt="Text emphasized alt text example" height="980" src="https://nerdy.dev/media/nice-selects.jpg" style="display: none;" width="2030" /> <p>This post pushes <a href="https://developer.chrome.com/blog/a-customizable-select">customizable <code>&lt;select&gt;</code></a> to an extreme. I think it turned out nice.</p> <p>It's mostly CSS! A li'l JS sprinkle just to position the <code>::picker()</code> and the selected option together; the JS is nice to have, <strong>CSS does the real work</strong>.</p> <p><video alt="" controls="controls" height="1080" loop="loop" poster="/media/nice-select.avif" preload="none" src="/media/nice-select.mp4" width="1440"></p> <p><span class="Tag">superellipse</span> <span class="Tag">forced colors</span> <span class="Tag">light/dark theme</span> <span class="Tag">slick scrollbar</span> <span class="Tag">scroll driven animations</span> <span class="Tag">scroll-state stuck query</span> <span class="Tag">scroll-state scrollable query</span> <span class="Tag">overscroll behavior</span> <span class="Tag">smooth scroll</span> <span class="Tag">RTL support</span> <span class="Tag">text-box trim</span> <span class="Tag">spring easing</span> <span class="Tag">anchor &amp; anchor fallbacks</span> <span class="Tag">color-mix()</span></p> <p><small>Chrome only atm, and I keep mobile with the native select. <b>Still cool!</b></small></p> <p><a href="https://codepen.io/editor/argyleink/pen/019c1f28-bbc2-7bac-ad4a-a7e41d3730f1">Try it</a></p> <h2> Core Architecture <a href="#core-architecture" name="core-architecture">#</a> </h2> <p>This component builds on the new <code>appearance: base-select</code> foundation, combining native accessibility with sweet visual control. Progressive enhancement ensures the custom experience only loads on capable devices. </p> <q class="info"> The examples in this post just look like regular select elements in Firefox and Safari. Firefox is <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1944403">working on it though!</a> </q> <ul> <li><strong><a href="https://developer.mozilla.org/docs/Web/CSS/appearance#base-select"><code>appearance: base-select</code></a></strong><br /> unlocks <a href="https://developer.chrome.com/blog/a-customizable-select">full customization</a> of native <code>&lt;select&gt;</code> elements while retaining browser controlled accessibility and keyboard navigation</li> <li><strong>Conditional enhancement</strong><br /> Only enables custom styling for devices with hover and fine pointer (<a href="https://developer.mozilla.org/docs/Web/CSS/@media/hover">@media (hover)</a> and <a href="https://developer.mozilla.org/docs/Web/CSS/@media/pointer">(pointer: fine)</a>)</li> <li><strong>JavaScript + CSS hybrid</strong><br /> JS calculates an anchor offset for alignment while CSS handles all visual presentation and animation</li> </ul> <h2> Alignment &amp; Positioning <a href="#alignment-&amp;-positioning" name="alignment-&amp;-positioning">#</a> </h2> <p>Anchor positioning plus some special JS sauce to write an inline CSS variable unlocks the picker to position near the selected option (obviously this can't work at the viewport edges). This creates a pleasant morphing effect that feels connected. </p> <q class="info"> <p>Maybe I should have used <a href="/anchor-interpolated-morphing">AIM</a>?</p> </q> <ul> <li><a href="https://developer.mozilla.org/docs/Web/CSS/CSS_anchor_positioning">CSS Anchor Positioning</a><br /> Picker uses <a href="https://developer.mozilla.org/docs/Web/CSS/Reference/Values/anchor"><code>anchor(start)</code></a> to position relative to the trigger button </li> <li><strong>Selected option alignment</strong><br /> When dropdown opens, the currently selected option aligns vertically with the button text via <code>--_select-anchor-offset</code> <a href="https://developer.mozilla.org/docs/Web/CSS/--*">custom property</a> </li> <li><strong>Syncs</strong> <code>transform-origin</code><br /> With <code>50% var(--_select-anchor-offset)</code> ensures scale animations line up better with the selected option's position </li> <li><strong>Anchor fallbacks with</strong> <a href="https://developer.mozilla.org/docs/Web/CSS/position-try-fallbacks"><code>position-try</code></a><br /> <code>flip-block, flip-inline</code> automatically repositions the anchor position if the picker would overflow the viewport</li> </ul> <p></p> <h2> Animation &amp; Transitions <a href="#animation-&amp;-transitions" name="animation-&amp;-transitions">#</a> </h2> <p>Scale effects with spring physics to scroll-driven option reveals, every interaction respects user motion preferences while providing rich feedback.</p> <ul> <li><a href="https://developer.mozilla.org/docs/Web/CSS/Reference/At-rules/@starting-style"><code>@starting-style</code></a><br /> Defines entry animation initial state for the popover </li> <li><strong>Spring easing</strong><br /> Uses <a href="https://open-props.style/#easing">Open Props</a> <code>--ease-spring-3</code> for playful, physics-based motion on scale and rotation</li> <li><strong>Discrete property transitions</strong><br /> <a href="https://developer.mozilla.org/docs/Web/CSS/display">display</a> and <a href="https://developer.mozilla.org/docs/Web/CSS/overlay">overlay</a> use <a href="https://developer.mozilla.org/docs/Web/CSS/transition-behavior"><code>allow-discrete</code></a> for proper <code>::picker()</code> popover animation support</li> <li><strong>Chevron rotation</strong><br /> <a href="https://developer.mozilla.org/docs/Web/CSS/::picker-icon"><code>::picker-icon</code></a> rotates 180° on open with spring easing</li> <li><strong>Scroll-driven option fade-in</strong><br /> Options animate in from the bottom using <a href="https://developer.mozilla.org/docs/Web/CSS/animation-timeline"><code>animation-timeline: view()</code></a></li> <li><strong>Respects reduced motion</strong><br /> Animations and transitions wrapped in <a href="https://developer.mozilla.org/docs/Web/CSS/@media/prefers-reduced-motion"><code>@media (prefers-reduced-motion: no-preference)</code></a></li> <li><strong>Button press feedback</strong><br /> <a href="https://developer.mozilla.org/docs/Web/CSS/:active">Active state</a> <a href="https://developer.mozilla.org/docs/Web/CSS/scale">scales</a> down to <code>0.98</code> for tactile feedback</li> <li><strong>Open state button feedback</strong><br /> Select scales up to <code>1.04</code> when <a href="https://developer.mozilla.org/docs/Web/CSS/:open"><code>:open</code></a>, scaling back down on close with a soft bounce</li> </ul> <p> </p> <h2> Theming &amp; Color Handling <a href="#theming-&amp;-color-handling" name="theming-&amp;-color-handling">#</a> </h2> <p>Automatic light/dark adaptation leverages system colors and modern color functions for seamless theme switching. Definitely check the support for light/dark forced colors too, a really great way to debug spacing and skeletal aspects of the UI.</p> <ul> <li><a href="https://developer.mozilla.org/docs/Web/CSS/color-scheme"><code>color-scheme: light dark</code></a><br /> Enables automatic system color adaptation </li> <li><a href="https://developer.mozilla.org/docs/Web/CSS/color_value/light-dark"><code>light-dark()</code> function</a><br /> Used for backgrounds that need different light/dark values</li> <li><a href="https://developer.mozilla.org/docs/Web/CSS/system-color">System colors</a><br /> <code>Canvas</code>, <code>CanvasText</code>, <code>Highlight</code>, <code>HighlightText</code> for semantic, colors</li> <li><a href="https://developer.mozilla.org/docs/Web/CSS/color_value/color-mix"><code>color-mix()</code></a><br /> Creates semi-transparent overlays and borders</li> <li><strong>Data URI icons</strong><br /> Chevron and checkmark icons embedded as SVG <a href="https://developer.mozilla.org/docs/Web/URI/Schemes/data">data URIs</a> with variants for each color scheme</li> <li><strong>Forced colors support</strong><br /> <a href="https://developer.mozilla.org/docs/Web/CSS/@media/forced-colors"><code>@media (forced-colors: active)</code></a> provides high-contrast mode adaptations (even the sticky scroll state respects this!)</li> </ul> <p> </p> <h2> Layout &amp; Spacing <a href="#layout-&amp;-spacing" name="layout-&amp;-spacing">#</a> </h2> <p>Logical properties enable true internationalization with automatic RTL support, while text-box trim delivers pixel-perfect vertical alignment. Custom properties create a flexible design token system.</p> <ul> <li><a href="https://developer.mozilla.org/docs/Web/CSS/--*">CSS Custom Properties</a> <strong>design tokens</strong><br /> All spacing, sizes, and timing values defined as <code>--_select-*</code> variables</li> <li><a href="https://developer.mozilla.org/docs/Web/CSS/CSS_logical_properties_and_values">Logical properties</a> <strong>throughout</strong><br /> <a href="https://developer.mozilla.org/docs/Web/CSS/inline-size"><code>inline-size</code></a>, <a href="https://developer.mozilla.org/docs/Web/CSS/block-size"><code>block-size</code></a>, <a href="https://developer.mozilla.org/docs/Web/CSS/inset-block-start"><code>inset-block-start</code></a>, <a href="https://developer.mozilla.org/docs/Web/CSS/margin-inline"><code>margin-inline</code></a>, <a href="https://developer.mozilla.org/docs/Web/CSS/padding-block"><code>padding-block</code></a> for full RTL support</li> <li><a href="https://developer.mozilla.org/docs/Web/CSS/text-box"><code>text-box: trim-both cap alphabetic</code></a><br /> Precise vertical text alignment in legends</li> <li><strong>Flexible option content</strong><br /> Options use <a href="https://developer.mozilla.org/docs/Web/CSS/CSS_flexible_box_layout">flexbox</a> with <a href="https://developer.mozilla.org/docs/Web/CSS/gap">gap</a> for icon + text layout</li> <li><strong>Checkmark auto-positioned</strong><br /> <a href="https://developer.mozilla.org/docs/Web/CSS/order"><code>order: 2</code></a> and <a href="https://developer.mozilla.org/docs/Web/CSS/margin-inline-start"><code>margin-inline-start: auto</code></a> pushes checkmark to end of option</li> </ul> <p> </p> <h2> Scrolling &amp; Overflow <a href="#scrolling-&amp;-overflow" name="scrolling-&amp;-overflow">#</a> </h2> <p><a href="https://developer.chrome.com/blog/css-scroll-state-queries">Scroll-state queries</a> dynamically detect when content is scrollable and when sticky headers become stuck. Custom scrollbar styling and smooth scrolling enhance the browsing experience within long option lists.</p> <ul> <li><a href="https://developer.mozilla.org/docs/Web/CSS/Guides/Conditional_rules/Container_scroll-state_queries">Container scroll-state queries</a><br /> <a href="https://developer.mozilla.org/docs/Web/CSS/container-type"><code>container-type: scroll-state</code></a> enables <a href="https://developer.mozilla.org/docs/Web/CSS/Guides/Conditional_rules/Container_scroll-state_queries#using_stuck_queries"><code>@container scroll-state(stuck)</code></a> detection</li> <li><strong>Sticky legends</strong><br /> Group headers <a href="https://developer.mozilla.org/docs/Web/CSS/position#sticky">stick to top</a> when scrolling, with color change when stuck</li> <li><strong>Custom scrollbar styling</strong><br /> <a href="https://developer.mozilla.org/docs/Web/CSS/scrollbar-width"><code>scrollbar-width: thin</code></a> and <a href="https://developer.mozilla.org/docs/Web/CSS/scrollbar-color"><code>scrollbar-color</code></a> with fade on hover-out</li> <li><strong>Scroll containment</strong><br /> <a href="https://developer.mozilla.org/docs/Web/CSS/overscroll-behavior-block"><code>overscroll-behavior-block: contain</code></a> prevents scroll chaining</li> <li><strong>Smooth scroll</strong><br /> <a href="https://developer.mozilla.org/docs/Web/CSS/scroll-behavior"><code>scroll-behavior: smooth</code></a> for programmatic scrolling (motion-safe)</li> <li><strong>Dynamic scrollable detection</strong><br /> JS adds <code>.scrollable</code> class when content exceeds max height, CSS adjusts padding accordingly</li> </ul> <p> </p> <h2> Customizable Select Features <a href="#customizable-select-features" name="customizable-select-features">#</a> </h2> <p>New pseudo-elements provide surgical styling control over picker components, while superellipse corners deliver the modern aesthetic popularized by iOS. State selectors enable precise targeting of open and selected states.</p> <ul> <li><a href="https://developer.mozilla.org/docs/Web/CSS/::picker"><code>::picker(select)</code></a><br /> Pseudo-element for styling the dropdown picker container</li> <li><a href="https://developer.mozilla.org/docs/Web/CSS/::picker-icon"><code>::picker-icon</code></a><br /> Pseudo-element for the dropdown chevron indicator</li> <li><a href="https://developer.mozilla.org/docs/Web/CSS/::checkmark"><code>::checkmark</code></a><br /> Pseudo-element for the selected option indicator</li> <li><a href="https://developer.chrome.com/blog/customize-select#selectedcontent"><code>&lt;selectedcontent&gt;</code></a><br /> Native element that mirrors selected option content in the button</li> <li><strong>Squircle corners</strong><br /> <a href="https://developer.mozilla.org/docs/Web/CSS/corner-shape"><code>corner-shape: superellipse(1.25)</code></a> for modern rounded rectangles (with fallback)</li> <li><a href="https://developer.mozilla.org/docs/Web/CSS/:open"><code>:open</code> pseudo-class</a><br /> State selector for when picker is visible</li> <li><a href="https://developer.mozilla.org/docs/Web/CSS/:checked"><code>:checked</code></a> on options<br /> State selector for selected option</li> </ul> <p></p> <h2> Accessibility &amp; UX <a href="#accessibility-&amp;-ux" name="accessibility-&amp;-ux">#</a> </h2> <p>Accessibility is built-in with proper focus indicators, keyboard navigation, and semantic markup thanks to the web platform. Touch-friendly targets and overflow handling ensure the component works elegantly across all input methods.</p> <ul> <li><strong>Focus ring styling</strong><br /> Distinct <a href="https://developer.mozilla.org/docs/Web/CSS/:focus"><code>:focus</code></a> (subtle) and <a href="https://developer.mozilla.org/docs/Web/CSS/:focus-visible"><code>:focus-visible</code></a> (prominent)</li> <li><strong>Disabled option support</strong><br /> <a href="https://developer.mozilla.org/docs/Web/HTML/Element/option#disabled"><code>option[disabled]</code></a> styling and hover prevention</li> <li><strong>Text overflow handling</strong><br /> <a href="https://developer.mozilla.org/docs/Web/CSS/text-overflow"><code>text-overflow: ellipsis</code></a> in button display</li> <li><strong>Minimum touch target</strong><br /> <code>36px</code> item height matches mobile guidelines</li> <li><strong>Hidden option support</strong><br /> JS skips <a href="https://developer.mozilla.org/docs/Web/HTML/Global_attributes/hidden"><code>[hidden]</code></a> options in offset calculations</li> <li><strong>RTL example included</strong><br /> Arabic language demo validates <a href="https://developer.mozilla.org/docs/Web/CSS/CSS_writing_modes">bidirectional layout</a></li> </ul> <h2> Performance Optimizations <a href="#performance-optimizations" name="performance-optimizations">#</a> </h2> <p>Careful optimization strategies keep animations smooth while minimizing layout thrash. Smart caching and compositor hints ensure the component performs well even on lower-end devices.</p> <ul> <li><a href="https://developer.mozilla.org/docs/Web/CSS/will-change"><code>will-change: scale</code></a><br /> Hints to browser for compositor optimization (also fixes text shift bug)</li> <li><a href="https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WeakMap">WeakMap</a> <strong>offset cache</strong><br /> Avoids expensive DOM measurements on every interaction;<br />auto-garbage-collected</li> <li><strong>Hardcoded layout constants</strong><br /> Avoids <a href="https://developer.mozilla.org/docs/Web/API/Window/getComputedStyle"><code>getComputedStyle</code></a> forced reflows during initialization. Tried dynamically computing these in a hidden instance, but couldn't get it as close as just &quot;hardcoding / speficying them ahead of time&quot; in a config</li> <li><strong>Background clip</strong><br /> <a href="https://developer.mozilla.org/docs/Web/CSS/background-clip"><code>background-clip: padding-box</code></a> prevents background bleeding under border</li> <li><strong>Parallel icon variants</strong><br /> Pre-defined black/white SVGs avoid runtime color manipulation</li> </ul> <h2> Example Variations <a href="#example-variations" name="example-variations">#</a> </h2> <p>The component architecture supports diverse use cases, from simple toggles to rich content pickers. Each variation demonstrates how the base patterns adapt to different content and interaction models.</p> <ul> <li><strong>Toggle with status indicators</strong><br /> Colored dots (green/red/gray) for on/off/disabled states</li> <li><strong>Avatar select</strong><br /> Circular images with person names</li> <li><strong>Multi-line options</strong><br /> Title + description layout for status picker</li> <li><strong>Grouped options</strong><br /> Fieldsets with sticky legend headers</li> <li><strong>Label above value</strong><br /> Color space picker with small label text above the selected value</li> <li><strong>Flag emoji select</strong><br /> Country picker organized by region</li> </ul> <h2> Try It <a href="#try-it" name="try-it">#</a> </h2> <p>Experience the component in action on CodePen:</p> <p> See the Pen <a href="https://codepen.io/argyleink/embed/preview/019c1f28-bbc2-7bac-ad4a-a7e41d3730f1"> by Adam Argyle (<a href="https://codepen.io/argyleink">@argyleink</a>) on <a href="https://codepen.io">CodePen</a>. </p> <h2> Wrapping Up <a href="#wrapping-up" name="wrapping-up">#</a> </h2> <p>There's room for improvement, please fork and offer feedback!</p> <p>I tried many variants of animation, trying to reduce some of the shift of the positioning, but never found something that worked across all the variants. Help me?! 🙏</p> <p>This select component intends to showcase what's possible when we combine modern CSS features with thoughtful progressive enhancement. The <code>appearance: base-select</code> property provides the foundation, while anchor positioning, scroll-state queries, and entrance animations create a polished, accessible experience.</p> <p>The real power lies in how these features compose together—each enhancement builds on platform primitives rather than fighting against them. The result is a component that's maintainable, accessible, and ready for the next generation of web interfaces.</p> <p>Most importantly, this approach lets us create custom experiences without sacrificing the keyboard navigation, focus management, and screen reader support that come free with native elements.</p> <p>For more, checkout <a href="/nice-details">nice details</a>!</p>
03.02.2026 17:17 👍 0 🔁 0 💬 0 📌 0
Preview
March Mad CSS Md <img alt="some title" height="496" src="https://nerdy.dev/media/march-madcss.jpg" style="display: none;" width="1400" /> <p>This week I compete in <a href="https://syntax.fm/">Syntax</a>'s <a href="https://www.madcss.com/">March madCSS</a>; me against <strong>16 other badass devs</strong> in CSS &amp; UI challenges 😅</p> <p>Wish me luck 🤞</p>
02.02.2026 04:02 👍 0 🔁 0 💬 0 📌 0
Preview
WWW Ep229 Is Ai Just Stealing With Extra Steps <img alt="some title" height="600" src="https://nerdy.dev/media/www-ep229.jpg" style="display: none;" width="600" /> <p><span class="Tag">Ep #229</span><br /> <strong>Is AI just stealing with extra steps?</strong></p> <p><a href="https://robbiethewagner.dev">Robbie</a> and I talk about the ethics and economics of AI, and why “stealing with extra steps” feels like the right metaphor for where things are headed. </p> <p>We also dig into open source burnout, whether AI replaces developers or just reshapes the job, and some whatnot over whiskey.</p> <p>⤷ <a href="https://whiskey.fm/is-ai-just-stealing-with-extra-steps-presented-by-coderabbit">whiskey.fm</a> · <a href="https://www.youtube.com/watch?v=i9Ra1J3NbYo">youtube</a> · <a href="https://open.spotify.com/episode/0K0bTlTs690yMo6JFZJbJp">spotify</a> · <a href="https://podcasts.apple.com/us/podcast/is-ai-just-stealing-with-extra-steps-presented-by/id1552776603?i=1000747148623">apple</a></p>
30.01.2026 01:11 👍 0 🔁 0 💬 0 📌 0
Preview
Whiskeyfm Collections <img alt="some title" height="772" src="https://nerdy.dev/media/www-collections.jpg" style="display: none;" width="1200" /> <p>Need to catch up on a tech topic? Try one of the 🆕 <a href="https://whiskey.fm/collections">WhiskeyFM Collections</a>!</p>
29.01.2026 05:58 👍 0 🔁 0 💬 0 📌 0
Preview
Prompt In Logical Properties <p>I prompt LLMs with logical properties.</p>
27.01.2026 22:37 👍 0 🔁 0 💬 0 📌 0
Preview
Anchor Interpolated Morph (AIM) It's more natural when animations start near the trigger point, this CSS technique makes it easy. AIM animates from any element, and to any element. Thanks to `anchor()`, `anchor-size()`, `@starting-style`, and `interpolate-size`. All together they can create an anchor interpolated morph: an **interruptible** contextual transition from where a user invoked it. That's a `popover=hint` + `interestfor`, no JS CSS transition. Try it This is a **very powerful** and capable feature combination. Similar results are visually possible with child elements using their parent as the anchor, but: 1. What if they're not ancestors? 2. What if one is in the `:top-layer`? 3. What if you want semantic HTML and a healthy accessibility OM? AIM is the remedy. ## FLIP # This technique is inspired by Paul Lewis's coined animation technique called FLIP (First, Last, Invert, Play). The gist of FLIP is to **use JS** to **calculate** the difference in positions/size/whatever of an element, **before and after** some DOM change. ## AIM # The gist of AIM is to **use CSS** to **access properties** from where another element is (first), to where natural render is (last), and let `transition` handle invert and play. **First:** `anchor()`, `anchor-size()` & `@starting-style` **Last:** `interpolate-size: allow-keywords` & `auto` The roles where JS was accessing properties, measuring natural sizes, and calculating the differences… are now handled by CSS. Definitely not 100% like FLIP 😅 but hopefully you see the connection. Here's a less designed example (so there's less CSS to sift through) that's a `<dialog>` element: Try it. You can uncomment a top-left position example too! ### How it works # **1:** The `anchor-name` property is used to identify the element that the element is morphing from. button { anchor-name: --⚓︎-morph; } ` Can you believe this one line of CSS enables **any other element to observe the height, width, and position of this element** 🤯 "Want more about that emoji naming convention?" **2:** Link up the dialog with that anchor. dialog { position-anchor: --⚓︎-morph; /* adjust position as desired */ left: anchor(left); top: anchor(top); } ` **3:** Enable transitioning to `auto` width/height. dialog { interpolate-size: allow-keywords; } ` **4:** Enable transitions for all properties you want in the morph. dialog { @media (prefers-reduced-motion: no-preference) { transition: display var(--_speed) allow-discrete, overlay var(--_speed) allow-discrete, height var(--_speed) var(--ease-3), width var(--_speed) var(--ease-3), left var(--_speed) var(--ease-3), top var(--_speed) var(--ease-3); } } ` **5:** Now we can use `@starting-style` to apply the styles from the anchor to the dialog before it opens. I call this "enter stage from" styles, and you can apply as many of the anchor values as you want. I specify all corners here and setup a mask system to allow the dialog to transition to fit it's content, from the anchor size, without distorting the dialog contents. dialog { @starting-style { &[open] { left: anchor(left); top: anchor(top); right: anchor(right); bottom: anchor(bottom); width: anchor-size(width); height: anchor-size(height); } } } ` Notice `anchor-size()` for height and width, this combined with height and width `auto` and `interpolate-size: allow-keywords` will allow the dialog to transition to its natural size from the anchor with a nice reveal. And for exit out on the `dialog`, it's similar as enter stage in my example but you could easily transition a different way or to a different element. dialog { &:not([open]) { left: anchor(left); top: anchor(top); right: anchor(right); bottom: anchor(bottom); width: anchor-size(width); height: anchor-size(height); } } ` **That's it for a dialog!** See the Pen by Adam Argyle (@argyleink) on [CodePen. AIM can be used for: * Dialogs * Popovers * Tooltips * Page preview * Fullscreen takeover (go big!) * Quick actions * Disclosures * Submenus * Hovercards * Particles? add some CSS `random()` * Other overlay components? Here's the popover from the video at the beginning. It's using all the above techniques, plus some extras, precise timings, easings and intentionality. See the Pen by Adam Argyle (@argyleink) on CodePen. View Transitions # What about view transitions and morphing, don't they do that too? Yep! They do, and can do some neat morphing tricks. Here's a view transitions demo I called "anything to anything". See the Pen by Adam Argyle (@argyleink) on CodePen. But… that requires JS, is always a straight line and is not elegantly interruptible. ""always straight lines"… once you notice it you can't unsee it. View transitions can't curve or swing to a new destination." Here's some slides I made using the [Astro Morphull repo I made that use no JS view transitions so content morphs: [https://cascadiajs-2025.netlify.app. Spatial Continuity # Traditional transitions often appear out of thin air or fade in from a generic center point. By leveraging `anchor()` and `@starting-style`, we can let CSS tell a story about where an element came from. > We're telling a story about where an element came from and why it’s there. Go forth and make more natural transitions that feel spatially contextual. Stop letting your elements "teleport" into view, start letting them grow, stretch, and evolve directly from the components that triggered them. Your users (and their muscle memory) will thank you. Speaking of, don't forget to gate the motion behind a `prefers-reduced-motion` media query (test the dialog and popovers). "Hot tip: You could easily morph to a different element than the invoking element, `anchor()` doesnt care." **Summary checklist for AIM:** 1. **Set the Anchor:** `anchor-name` on the invoking element to create a spatial reference. 2. **Set "Enter From" and "Exit To" styles with `anchor()`:** Use `@starting-style` to declare the entry and exit properties relative to the anchor. 3. **Transition:** Orchestrate `transition` properties to allow the browser to interpolate the path, shapes and colors between the anchor point and the final layout. *[anchor interpolated morph]: AIM *[AIM]: anchor interpolated morph
23.01.2026 17:04 👍 0 🔁 0 💬 0 📌 0
Preview
Custom Media `@custom-media` working behind a flag in Firefox Nightly! @custom-media --motionOK (prefers-reduced-motion: no-preference); @media (--motionOK) { transition: transform .3s ease; } ` **Lovely syntax.** Open Props has ~45 ready to go, peep the spec, or visit MDN for more info.
23.01.2026 04:46 👍 0 🔁 0 💬 0 📌 0
Preview
WWW Ep228 Santa Exe <img alt="some title" height="1280" src="https://nerdy.dev/media/www-228.jpg" style="display: none;" width="1280" /> <p><span class="Tag">Ep #228</span><br /> <strong>Santa.exe 🎄💻🥃</strong></p> <p><a href="https://robbiethewagner.dev">Robbie</a>, Chuck and I bring you the holiday edition of <a href="https://whiskey.fm/">Whiskey Web and Whatnot</a>: random whiskeys, Christmas hot takes, and dev debates.</p> <p>⤷ <a href="https://whiskey.fm/santaexe-presented-by-coderabbit">whiskey.fm</a> · <a href="https://youtu.be/uv-SC4gJCY8?si=gY8EX3cEwLhpCDfz">youtube</a> · <a href="https://open.spotify.com/episode/0qttXIrlVBJ2dq73dcY4xF?si=EFp3b8LmQRWa8uLOAgRHdA">spotify</a> · <a href="https://podcasts.apple.com/us/podcast/santa-exe-presented-by-coderabbit/id1552776603?i=1000746179395">apple</a></p>
22.01.2026 05:48 👍 0 🔁 0 💬 0 📌 0
Preview
Overscroll Effects On Nested Scrollers In All Browsers Finally… Chrome 145 joins WebKit and Firefox in supporting **overscroll effects** on nested scrollers. No more bonk UX, get the same soft edge bounce as the main page has always had! ❤️ Ty Robert!
21.01.2026 04:20 👍 0 🔁 0 💬 0 📌 0
Preview
WWW Ep227 Ai And Oath With Will Johnson Ep #227 **AI and Oath with Will Johnson** Robbie and I talk with Will Johnson, senior developer advocate at Auth0, about web dev, parenting, and internet culture. ⤷ whiskey.fm · youtube · spotify · apple
15.01.2026 00:00 👍 0 🔁 0 💬 0 📌 0
Preview
WWW Ep226 A Very Merry Descent Into Holiday Madness Ep #226 **A very merry descent into holiday madness** Robbie and I talk about holiday travel chaos, parenting stress, and health scares before diving into AI-assisted coding, Linux quirks, IDE trends, burnout in open source, and more. ⤷ whiskey.fm · youtube · spotify · apple
08.01.2026 00:00 👍 0 🔁 0 💬 0 📌 0
Preview
4 CSS Features Every Front-End Developer Should Know In 2026 2026; I think every front-end developer should know how to query scroll states, trim typographic whitespace, stagger with sibling-index(), and use type safe `attr()`. **This is only some of the CSS that shipped in 2025 you need to know.** " This post is a themed post! Check out 2023, 2024 and 2025. " ## sibling-index() and sibling-count() # Earlier this year these were just experiments, now they're available in stable Chrome and Safari! They let you use an element's position relative to its siblings as values in calculations. For example, you can stagger elements with a transition delay based on their `sibling-index()`. A nice trick is to subtract 1 so the **first element starts immediately** : li { transition: opacity .3s ease; transition-delay: calc((sibling-index() - 1) * 100ms); } ` Stagger enter stage animations easily by combining with `@starting-style`! li { transition: opacity .3s ease; transition-delay: calc((sibling-index() - 1) * 100ms); @starting-style { opacity: 0; } } ` See the Pen by Adam Argyle (@argyleink) on [CodePen. You can rotate hues in oklch, automatically number elements, and all sorts of fun things. Resources * Earlier post I wrote * sibling-index() * sibling-count() * Brecht * CSS Tricks @container scroll-state() # These features fit nicely into progressive enhancement, similar to scroll driven animations, as they're enhancements rather than requirements. IMO at least. Three states of a scroller are now queryable: stuck, snapped, scrollable and scrolled. To start, you need the element that's stuck, snapped, or scrollable to have `container-type: scroll-state`. Then, a child can query it with `@container scroll-state()`. " An element cannot query itself, but its pseudo elements can! " stuck # Perfectly know when `position: sticky` elements are stuck. /* when .outer-navbar is stuck */ @container scroll-state(stuck) { .inner-navbar { box-shadow: var(--shadow-3); } } ` Use this to help users understand an element will now be overlaying their scroll content. snapped # Perfectly know when scroll-snap alignment is active. /* when <li> parent is snapped */ @container scroll-state(snapped) { .box { scale: 1.1; } } /* or not snapped! */ @container not scroll-state(snapped) { .box figcaption { translate: 0 100%; } } ` Great for highlighting the item, or demoting every other item. scrollable # Perfectly know when content overflows its container, and in which direction(s). @container scroll-state(scrollable) { .scroll-hint { opacity: 1; } } ` Use this to toggle hints, scroll indicators, or adjust padding to signal more content. scrolled # Perfectly know when content is scrolled in a direction. @container scroll-state(scrolled: bottom) { translate: 0 -100%; } ` Use this for sticky headers or navbars that showy hidey based on scroll direction. Resources * Chrome blog * MDN * Una on scrolled * Bramus on scrolled * Me on remaking the Switch Homescreen * The CSS Podcast text-box # `text-box` lets you slice half-leading right off a text box! Web font rendering includes whitespace above and below glyphs for "safe spacing", but sometimes you want pixel-perfect alignment to baselines or x-heights. Achieve the above image with: h1 { text-box: trim-both cap alphabetic; } ` That one-liner trims spacing above cap height and below alphabetic baselines. Learn more in my interactive notebook Perfect for type and grid alignment nerds. I think it'll become the default. Resources * Chrome blog article * Interactive notebook * Codepen collection * Una and I on Syntax typed attr() # There's an advanced version of `attr()`; type-safe and more powerful. It allows **using HTML attributes directly in CSS** with type checking and fallbacks. **Pass colors:** <div data-bg="white" data-fg="deeppink"></div> ` .theme { background: attr(data-bg color, black); color: attr(data-fg color, white); } ` **Pass numbers:** <div class="grid" data-columns="3">…</div> ` .grid { --_columns: attr(data-columns number, 3); display: grid; grid-template-columns: repeat(var(--_columns), 1fr); } ` This creates a powerful bridge between HTML and CSS. Here's a scroll snap example where CSS basically controls the enums and HTML must pass valid values to get the desired snap results: <li scroll-snap="start"></li> <li scroll-snap="center"></li> <li scroll-snap="end"></li> <li scroll-snap="nothing"></li> ` [scroll-snap] { scroll-snap-align: attr(scroll-snap type(start | center | end)); } ` The `type()` function validates attribute values against allowed keywords. Invalid values fall back gracefully. Try it on Codepen Resources * My post in 2025 about it * Try it on CodePen * Chrome Developers article * Temani Afif's post * Temani slider tooltips **CSS rules.** Now let's laugh at this hilarious obvious AI generated nano banana image I made about us having our cake and eating it too. Still can't do hands lol
07.01.2026 07:01 👍 0 🔁 0 💬 0 📌 0
Preview
Ios Vs Android In 2025 iOS vs Android in 2025: * iOS apps get more TLC (might not matter over time) * iOS scrolling is better (Android needs to fix this)
27.12.2025 06:01 👍 0 🔁 0 💬 0 📌 0
Preview
Bring The Color Bring the color in at gradient.style
16.12.2025 07:05 👍 0 🔁 0 💬 0 📌 0
Preview
5 WebGL Tools of 2025 I don't have enough time to play with all these amazing webGL tools right now! Maybe you do‽ This post is a quick round up of webGL tools that I've come across this year. Maybe you'll **have fun** in one. ## Hydra # I'm already a sucker for Strudel, but Hydra is a sick way to take the code and drive a visual. https://hydra.ojack.xyz ## Efecto # The rad Pablo Stanley has a wake of great tools behind them, and Efecto is no exception. https://efecto.app ## Shaders # I recently got early access to this one, was on a waiting list for so long I forgot I registered. But, worth the wait, was able to make some rad stuff in a short amount of time. https://shaders.com ## Paper # A Figma-like design tool but built for the web, with the web, rendering to DOM so WYSIWYG 100%. Mega bonus, it's got sweet drop in webGL effects. Putting an animated webGL effects behind a beautiful artboard is so sick; **the canvas feels alive and exciting**. https://paper.design ## Unicorn Studio # This one had me hooked for a bit too, I think it's the one I have the most projects in. Intuitive UI, great presets, and LOTS of ways to add interactivity. https://www.unicorn.studio Did I miss one?
09.12.2025 05:33 👍 0 🔁 0 💬 0 📌 0
Preview
Custom Media Feature Flags A fun use case for `@custom-media` queries is to toggle styles based on a feature flag. Imagine an edge worker that toggles `true` or `false` in a CSS file, and the rest of your styles can tap in and adapt. * A/B testing * Unique user features * Reveal Debug elements * v2 layouts you name it. ## Syntax # Define an **enabled** feature like: @custom-media --feature-flag true; ` Or a **disabled** feature like: @custom-media --debug-flag false; ` Use them like: @media (--feature-flag) { body { … } } .component { @media (--debug-flag) { … } } ` Use nesting, query from JavaScript, or both. ## More custom media # The spec, a CSS Tricks article, post by Stefan Judis, a polyfill, a premade set in Open Props (anticipating the feature), and there's been good browser implementation activity recently in Firefox (marked FIXED!) and Chrome, not webkit as much. I'm excited, it's a great feature.
06.12.2025 04:32 👍 0 🔁 0 💬 0 📌 0
Preview
CSS Text Grow Fit width text in 1 line of CSS: h1 { text-grow: per-line scale; } ` Prototype available in Canary 145+ Codepen · CSSWG · Explainer · Prior Art
05.12.2025 06:34 👍 0 🔁 0 💬 0 📌 0
Preview
On The Ux Show Was on The UX Show with Yash Raj and Victor Sanchez 🤓 Watch it on YouTube
02.12.2025 00:29 👍 1 🔁 0 💬 0 📌 0
Preview
Using CSS to fix the irradiation illusion Ever noticed how white text on a black background **looks thicker** than black text on a white background, even though the weights are the same? This post teaches you how to account for this and adjust perceived font weight for dark mode **without layout shift** , with variable fonts and the `GRAD` axis. "g…RAD! 👈😎👈" ## Feel out the problem space # Test your eyes and feel the problem space with the following demo (def open it up larger): See the Pen by Adam Argyle (@argyleink) on [CodePen. **To test:** Flip between light and dark. Look closely at font weights in the "un-adjusted" and "adjusted" example content. **The goal:** The visual weight to not perceptively change when switching between light and dark. This means, when in dark mode, using a negative value for `GRAD` to reduce the perceived thickness. **Some play:** In dark mode, use the slider to adjust the `GRAD` axis to see how it changes the perceived weight of the font in the adjusted example. Feel free to fine tune the slider to find the perfect balance for your eyes, flipping back and forth, adjust the slider until you see no weight change when flipping themes. I think it's easier to notice the difference in the paragraph text than the heading text, but you find which is easier to notice for yourself. **It's subtle:** Don't expect this to jump out at you, but **you'll struggle to unsee once you see**. Irradiation illusion # Humans perceive white on black vs black on white differently. We learned it from the world, the way shadows and light have given us biases and expectations. Our squishy human eye has been through some things you know? Read more about irradiation illusion. This impacts typography in dark mode, as the perceived weight of a font changes in dark mode, without intention from the CSS authors. The light text appears thicker than the dark text counterpart, even though the font weight is the same. **CSS can account for this illusion** 🤓 GRAD in variable fonts to the rescue # Before variable fonts, font weight was the only way to adjust the perceived weight of a font, but this changes the glyph size. This can cause accidental layout shift, aka a janky experience. `GRAD` stands for "grade", and it's a variable font axis that allows us to adjust the perceived weight of a font without changing the glyph size. Fixing bold link hovers # Here, you'll recognize this classic issue. Hover the links in the below demo to see a small preview of the type of layout shift that can occur. See the Pen by Adam Argyle (@argyleink) on CodePen. **With variable fonts, we can use the`GRAD` axis to adjust the perceived weight of a font without changing the glyph size.** This allows us to adjust the perceived weight of a font without causing layout shift. That's what the "fixed" example is using. One step further # So far we've only adjusted the perceived weight of a font in dark mode with a negative value for `GRAD`, and for links being hovered that use a positive value for `GRAD`, but we can go even further: See the Pen by Adam Argyle (@argyleink) on [CodePen. This allows us to adjust the perceived weight of a font based on the [users contrast preferences. If the user prefers more contrast, without layout shift, we can use a positive value for `GRAD` to increase the perceived thickness. In dark mode, we can use a negative value for `GRAD` to reduce the perceived thickness while still maintaining their preference. body { --GRAD: 0; font-variation-settings: "GRAD" var(--GRAD); } @media (prefers-contrast: more) { body { --GRAD: 700 } } @media (prefers-contrast: less) { body { --GRAD: -50 } } @media (prefers-color-scheme: dark) { body { --GRAD: -50 } } @media (prefers-color-scheme: dark) and (prefers-contrast: more) { body { --GRAD: 150 } } @media (prefers-color-scheme: dark) and (prefers-contrast: less) { body { --GRAD: -150 } } ` Users will never ask for something like this. They'll just be able to easily read the content in your design in a way that feels natural. Time to check if your favorite font has a `GRAD` axis.
29.11.2025 21:47 👍 2 🔁 0 💬 0 📌 0