<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
  <title>WebCraft</title>
  <link>https://web-craft.net/</link>
  <atom:link href="https://web-craft.net/feed.xml" rel="self" type="application/rss+xml"/>
  <description>One interface element at a time, with the caveat that breaks it.</description>
  <language>en</language>
  <lastBuildDate>Tue, 18 Aug 2026 00:00:00 +0000</lastBuildDate>
  <item>
    <title>animation-delay: -43200s — An analog clock wound by one line of JavaScript</title>
    <link>https://web-craft.net/elements/analog-clock-wound-by-one-line-of-javascript/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/analog-clock-wound-by-one-line-of-javascript/</guid>
    <category>motion</category>
    <pubDate>Tue, 18 Aug 2026 00:00:00 +0000</pubDate>
    <description>CSS cannot ask what time it is. The clock is three infinite rotations, and a negative animation-delay winds it: minus four hours starts an animation four hours in, instantly. The only JavaScript writes seconds-since-midnight into a custom property — and that is the whole script. The dial itself is laid out by cos() and sin(), not twelve hand-tuned offsets.</description>
  </item>
  <item>
    <title>animation + cqw — The logo that never hits the corner</title>
    <link>https://web-craft.net/elements/logo-that-never-hits-the-corner/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/logo-that-never-hits-the-corner/</guid>
    <category>motion</category>
    <pubDate>Tue, 18 Aug 2026 00:00:00 +0000</pubDate>
    <description>Two animations cannot share a property. Put the horizontal and the vertical drift on one element and the second translate wins outright instead of the two combining — which is why this needs one element per axis. And 100% in a translate is the element’s own size, so the travel is 100cqw - 100%: the box, less the logo.</description>
  </item>
  <item>
    <title>resize + max-width — resize keeps writing after max-width stops it</title>
    <link>https://web-craft.net/elements/resize-keeps-writing-after-max-width-stops-it/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/resize-keeps-writing-after-max-width-stops-it/</guid>
    <category>layout</category>
    <pubDate>Mon, 17 Aug 2026 00:00:00 +0000</pubDate>
    <description>Dragging writes an inline width and does not stop at max-width. The box paints clamped, but a fit-content parent measures the stored value instead, so anything centred in that parent drifts off the box it belongs to.</description>
  </item>
  <item>
    <title>background + padding — A gradient border that keeps its corners</title>
    <link>https://web-craft.net/elements/gradient-border-that-keeps-its-corners/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/gradient-border-that-keeps-its-corners/</guid>
    <category>surface</category>
    <pubDate>Mon, 17 Aug 2026 00:00:00 +0000</pubDate>
    <description>border-image ignores border-radius outright — square corners, every time, and no amount of radius fixes it. So the border is not a border here: it is padding over a gradient background.</description>
  </item>
  <item>
    <title>radial-gradient at var() — A spotlight that follows the cursor</title>
    <link>https://web-craft.net/elements/spotlight-that-follows-the-cursor/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/spotlight-that-follows-the-cursor/</guid>
    <category>hover</category>
    <pubDate>Mon, 17 Aug 2026 00:00:00 +0000</pubDate>
    <description>Gate it behind @media (hover: hover) and (pointer: fine). On a touchscreen :hover latches after a tap, so the light switches on and stays on with nothing hovering it.</description>
  </item>
  <item>
    <title>animation-timeline: scroll() — A progress bar tied to scroll, with no JavaScript</title>
    <link>https://web-craft.net/elements/progress-bar-tied-to-scroll-with-no-javascript/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/progress-bar-tied-to-scroll-with-no-javascript/</guid>
    <category>motion</category>
    <pubDate>Sun, 16 Aug 2026 00:00:00 +0000</pubDate>
    <description>An animation whose timeline is unsupported does not simply switch off — it still applies its fill state. Ship this unguarded and browsers without scroll timelines show a permanently full progress bar.</description>
  </item>
  <item>
    <title>position: sticky — A table header that stays put</title>
    <link>https://web-craft.net/elements/table-header-that-stays-put/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/table-header-that-stays-put/</guid>
    <category>table</category>
    <pubDate>Sun, 16 Aug 2026 00:00:00 +0000</pubDate>
    <description>Any ancestor carrying overflow: hidden switches sticky off silently — no warning, no error, the header just scrolls away. That ancestor is usually a card wrapper somebody added months later.</description>
  </item>
  <item>
    <title>-webkit-line-clamp — Cut a paragraph to three lines</title>
    <link>https://web-craft.net/elements/cut-a-paragraph-to-three-lines/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/cut-a-paragraph-to-three-lines/</guid>
    <category>text</category>
    <pubDate>Sat, 15 Aug 2026 00:00:00 +0000</pubDate>
    <description>All four declarations are load-bearing. Bottom padding is the trap: the clipped line stays visible inside the padding box, so pad the parent, never the clamped element.</description>
  </item>
  <item>
    <title>field-sizing: content — A textarea that grows as you type</title>
    <link>https://web-craft.net/elements/textarea-that-grows-as-you-type/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/textarea-that-grows-as-you-type/</guid>
    <category>form</category>
    <pubDate>Sat, 15 Aug 2026 00:00:00 +0000</pubDate>
    <description>Give it a max-height, or a pasted wall of text pushes the submit button off screen — worse than the scrollbar you were removing. lh units keep the bounds in lines, not guessed pixels.</description>
  </item>
  <item>
    <title>&lt;details name&gt; — An accordion with no JavaScript</title>
    <link>https://web-craft.net/elements/accordion-with-no-javascript/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/accordion-with-no-javascript/</guid>
    <category>disclosure</category>
    <pubDate>Fri, 14 Aug 2026 00:00:00 +0000</pubDate>
    <description>Hiding the marker takes two declarations, not one. Miss either and one browser keeps a triangle you never designed for.</description>
  </item>
  <item>
    <title>:focus-visible — A focus ring for keyboards only</title>
    <link>https://web-craft.net/elements/focus-ring-for-keyboards-only/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/focus-ring-for-keyboards-only/</guid>
    <category>a11y</category>
    <pubDate>Fri, 14 Aug 2026 00:00:00 +0000</pubDate>
    <description>:focus { outline: none } is the most common accessibility bug on the web, and it looks like a tidy-up. It takes the ring from keyboard users, the only people who needed it.</description>
  </item>
  <item>
    <title>position: sticky (inline) — A wide table that keeps its first column</title>
    <link>https://web-craft.net/elements/wide-table-that-keeps-its-first-column/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/wide-table-that-keeps-its-first-column/</guid>
    <category>table</category>
    <pubDate>Thu, 13 Aug 2026 00:00:00 +0000</pubDate>
    <description>The corner cell is sticky in two directions at once, so it has to outrank both the header row and the pinned column. Give it the highest z-index of the three or the scrolling cells paint straight over it.</description>
  </item>
  <item>
    <title>background-attachment: local — Shadows that show there is more to scroll</title>
    <link>https://web-craft.net/elements/shadows-that-show-there-is-more-to-scroll/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/shadows-that-show-there-is-more-to-scroll/</guid>
    <category>scroll</category>
    <pubDate>Thu, 13 Aug 2026 00:00:00 +0000</pubDate>
    <description>The two cover gradients have to match the container background exactly. Put this on a transparent or patterned surface and the covers read as grey smears sitting on top of your design.</description>
  </item>
  <item>
    <title>:has() + translate — A segmented control with a sliding indicator</title>
    <link>https://web-craft.net/elements/segmented-control-with-a-sliding-indicator/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/segmented-control-with-a-sliding-indicator/</guid>
    <category>control</category>
    <pubDate>Wed, 12 Aug 2026 00:00:00 +0000</pubDate>
    <description>Never size the indicator in pixels. Hardcode a width and a shift and the pill lines up until someone renames an option — then it sits half over the next label, with no error to tell you. Equal columns and a shift of 100% of itself need no measuring.</description>
  </item>
  <item>
    <title>@keyframes + gradient — A skeleton that does not lie about the layout</title>
    <link>https://web-craft.net/elements/skeleton-that-does-not-lie-about-the-layout/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/skeleton-that-does-not-lie-about-the-layout/</guid>
    <category>loading</category>
    <pubDate>Wed, 12 Aug 2026 00:00:00 +0000</pubDate>
    <description>A skeleton whose blocks are not the size of the real content is worse than a spinner: the page visibly rearranges the moment data lands. Match the line heights and widths you will actually render.</description>
  </item>
  <item>
    <title>aria-expanded — A menu button that turns into a close button</title>
    <link>https://web-craft.net/elements/menu-button-that-turns-into-a-close-button/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/menu-button-that-turns-into-a-close-button/</guid>
    <category>menu</category>
    <pubDate>Tue, 11 Aug 2026 00:00:00 +0000</pubDate>
    <description>It is a button with aria-expanded, not a checkbox. A checkbox announces itself as a checkbox, and a menu toggle that reads as "checkbox, not checked" is worse than no label at all.</description>
  </item>
  <item>
    <title>appearance: none — A switch that is still a checkbox</title>
    <link>https://web-craft.net/elements/switch-that-is-still-a-checkbox/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/switch-that-is-still-a-checkbox/</guid>
    <category>form</category>
    <pubDate>Tue, 11 Aug 2026 00:00:00 +0000</pubDate>
    <description>Style the input itself rather than hiding it behind a div. appearance: none strips the paint and keeps everything else — focus, the space key, the label association, the announced role.</description>
  </item>
  <item>
    <title>translateX(-50%) — A marquee that never jumps</title>
    <link>https://web-craft.net/elements/marquee-that-never-jumps/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/marquee-that-never-jumps/</guid>
    <category>motion</category>
    <pubDate>Mon, 10 Aug 2026 00:00:00 +0000</pubDate>
    <description>The track holds the list twice and travels exactly -50%. Any other distance, or a single copy, and the loop visibly snaps back at the seam.</description>
  </item>
  <item>
    <title>backdrop-filter — Frosted glass over anything</title>
    <link>https://web-craft.net/elements/frosted-glass-over-anything/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/frosted-glass-over-anything/</guid>
    <category>surface</category>
    <pubDate>Mon, 10 Aug 2026 00:00:00 +0000</pubDate>
    <description>The element needs its own translucent background. Fully opaque and there is nothing to see through; fully transparent and most engines skip the filter entirely. Somewhere near 40% is where it reads as glass.</description>
  </item>
  <item>
    <title>background-clip: text — Type painted with a gradient</title>
    <link>https://web-craft.net/elements/type-painted-with-a-gradient/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/type-painted-with-a-gradient/</guid>
    <category>type</category>
    <pubDate>Sun, 09 Aug 2026 00:00:00 +0000</pubDate>
    <description>color: transparent is doing the work, so if the background fails to paint for any reason the text is invisible rather than merely unstyled. Never put a whole paragraph in it, only display type you can afford to lose.</description>
  </item>
  <item>
    <title>::-webkit-slider-thumb — A range slider you can actually style</title>
    <link>https://web-craft.net/elements/range-slider-you-can-actually-style/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/range-slider-you-can-actually-style/</guid>
    <category>form</category>
    <pubDate>Sun, 09 Aug 2026 00:00:00 +0000</pubDate>
    <description>The WebKit and Gecko thumb selectors cannot share a rule. One unknown pseudo-element invalidates the entire selector list, so a combined rule silently styles nothing anywhere. Write them out separately, every time.</description>
  </item>
  <item>
    <title>perspective + rotate — A card that tips towards the cursor</title>
    <link>https://web-craft.net/elements/card-that-tips-towards-the-cursor/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/card-that-tips-towards-the-cursor/</guid>
    <category>hover</category>
    <pubDate>Sat, 08 Aug 2026 00:00:00 +0000</pubDate>
    <description>The perspective belongs on the parent, not on the card. Put it on the transformed element and every card gets its own vanishing point, so a row of them tilts in visibly different directions.</description>
  </item>
  <item>
    <title>@property — A gradient angle that actually animates</title>
    <link>https://web-craft.net/elements/gradient-angle-that-actually-animates/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/gradient-angle-that-actually-animates/</guid>
    <category>motion</category>
    <pubDate>Sat, 08 Aug 2026 00:00:00 +0000</pubDate>
    <description>Custom properties are strings until you register them. Animate an unregistered --angle and it jumps from start to end with nothing in between — no error, no warning, just a hard cut at 50%.</description>
  </item>
  <item>
    <title>@container — A card that reads its own container, not the window</title>
    <link>https://web-craft.net/elements/card-that-reads-its-own-container-not-the-window/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/card-that-reads-its-own-container-not-the-window/</guid>
    <category>layout</category>
    <pubDate>Fri, 07 Aug 2026 00:00:00 +0000</pubDate>
    <description>An element cannot query itself. The container-type goes on a wrapper and the query targets its children, so every queried component needs one box more than you expected.</description>
  </item>
  <item>
    <title>cqi — Type that scales with its container</title>
    <link>https://web-craft.net/elements/type-that-scales-with-its-container/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/type-that-scales-with-its-container/</guid>
    <category>layout</category>
    <pubDate>Fri, 07 Aug 2026 00:00:00 +0000</pubDate>
    <description>A cqi unit resolves against the nearest ancestor that declared a container, not the nearest ancestor you had in mind. Nest two containers and the inner one silently wins.</description>
  </item>
  <item>
    <title>aspect-ratio — Boxes that keep their proportions</title>
    <link>https://web-craft.net/elements/boxes-that-keep-their-proportions/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/boxes-that-keep-their-proportions/</guid>
    <category>layout</category>
    <pubDate>Fri, 07 Aug 2026 00:00:00 +0000</pubDate>
    <description>An explicit height beats aspect-ratio every time. The one that catches people is implicit: a flex or grid parent stretches its children by default, and that stretch is a height.</description>
  </item>
  <item>
    <title>text-wrap: balance — A heading that breaks where a typesetter would</title>
    <link>https://web-craft.net/elements/heading-that-breaks-where-a-typesetter-would/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/heading-that-breaks-where-a-typesetter-would/</guid>
    <category>type</category>
    <pubDate>Thu, 06 Aug 2026 00:00:00 +0000</pubDate>
    <description>Browsers stop balancing past roughly six lines and quietly do nothing beyond that. It is a headline tool: put it on body copy and you pay for the layout pass and get no result.</description>
  </item>
  <item>
    <title>text-wrap: pretty — Paragraphs with no orphan last line</title>
    <link>https://web-craft.net/elements/paragraphs-with-no-orphan-last-line/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/paragraphs-with-no-orphan-last-line/</guid>
    <category>type</category>
    <pubDate>Thu, 06 Aug 2026 00:00:00 +0000</pubDate>
    <description>This is the one for body copy, and balance is not. Swapping them is the common mistake: pretty only fixes the last lines, balance evens out every line but gives up on long text.</description>
  </item>
  <item>
    <title>hyphens: auto — Hyphenation in a narrow column</title>
    <link>https://web-craft.net/elements/hyphenation-in-a-narrow-column/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/hyphenation-in-a-narrow-column/</guid>
    <category>type</category>
    <pubDate>Thu, 06 Aug 2026 00:00:00 +0000</pubDate>
    <description>It does nothing without a lang attribute on the element or an ancestor. The browser needs to know which dictionary to hyphenate with, and silently declines rather than guessing.</description>
  </item>
  <item>
    <title>:user-invalid — An error state that waits its turn</title>
    <link>https://web-craft.net/elements/error-state-that-waits-its-turn/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/error-state-that-waits-its-turn/</guid>
    <category>form</category>
    <pubDate>Wed, 05 Aug 2026 00:00:00 +0000</pubDate>
    <description>:invalid matches from the moment the page loads, so an empty required field is red before anyone has typed a character. :user-invalid waits until the field has been interacted with.</description>
  </item>
  <item>
    <title>accent-color — Native controls in your palette</title>
    <link>https://web-craft.net/elements/native-controls-in-your-palette/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/native-controls-in-your-palette/</guid>
    <category>form</category>
    <pubDate>Wed, 05 Aug 2026 00:00:00 +0000</pubDate>
    <description>One property, one colour, no second opinion — the tick, the thumb and the fill are all derived from it. Need the check mark a different colour from the box and you are back to rebuilding the control.</description>
  </item>
  <item>
    <title>:placeholder-shown — A label that floats out of the way</title>
    <link>https://web-craft.net/elements/label-that-floats-out-of-the-way/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/label-that-floats-out-of-the-way/</guid>
    <category>form</category>
    <pubDate>Wed, 05 Aug 2026 00:00:00 +0000</pubDate>
    <description>The trick needs a real placeholder attribute — even a single space — because the selector matches the placeholder being shown, not the value being empty. Drop the attribute and the label never moves.</description>
  </item>
  <item>
    <title>scroll-snap-type — A carousel the browser drives</title>
    <link>https://web-craft.net/elements/carousel-the-browser-drives/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/carousel-the-browser-drives/</guid>
    <category>scroll</category>
    <pubDate>Tue, 04 Aug 2026 00:00:00 +0000</pubDate>
    <description>scroll-snap-type goes on the scroller and scroll-snap-align on every child. Set only the first and nothing snaps, with no indication that half the recipe is missing.</description>
  </item>
  <item>
    <title>overscroll-behavior — Scrolling that stops at the edge</title>
    <link>https://web-craft.net/elements/scrolling-that-stops-at-the-edge/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/scrolling-that-stops-at-the-edge/</guid>
    <category>scroll</category>
    <pubDate>Tue, 04 Aug 2026 00:00:00 +0000</pubDate>
    <description>This is the real fix for the page scrolling behind an open modal. Locking body with overflow: hidden throws away the reading position and jumps the layout by the scrollbar width.</description>
  </item>
  <item>
    <title>scroll-padding-top — Anchor links that clear a sticky header</title>
    <link>https://web-craft.net/elements/anchor-links-that-clear-a-sticky-header/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/anchor-links-that-clear-a-sticky-header/</guid>
    <category>scroll</category>
    <pubDate>Tue, 04 Aug 2026 00:00:00 +0000</pubDate>
    <description>Jump to an anchor under a sticky header and the heading lands behind it. The offset belongs to the scroll container as scroll-padding-top, or to the target as scroll-margin-top, never to both.</description>
  </item>
  <item>
    <title>:has() — A wrapper that knows its input is wrong</title>
    <link>https://web-craft.net/elements/wrapper-that-knows-its-input-is-wrong/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/wrapper-that-knows-its-input-is-wrong/</guid>
    <category>state</category>
    <pubDate>Mon, 03 Aug 2026 00:00:00 +0000</pubDate>
    <description>Specificity is taken from the heaviest selector inside the brackets, not from :has() itself. Put an id in there and the whole rule inherits an id-level weight you did not intend to spend.</description>
  </item>
  <item>
    <title>:has() + :not() — Hovering one row quiets the others</title>
    <link>https://web-craft.net/elements/hovering-one-row-quiets-the-others/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/hovering-one-row-quiets-the-others/</guid>
    <category>hover</category>
    <pubDate>Mon, 03 Aug 2026 00:00:00 +0000</pubDate>
    <description>This re-evaluates on every pointer move across the list. On a few dozen rows it is free; on a table of several hundred it is a visible frame cost, and the fix is to move the rule to the row rather than the list.</description>
  </item>
  <item>
    <title>:has(:nth-child()) — A layout that changes when the list gets long</title>
    <link>https://web-craft.net/elements/layout-that-changes-when-the-list-gets-long/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/layout-that-changes-when-the-list-gets-long/</guid>
    <category>layout</category>
    <pubDate>Mon, 03 Aug 2026 00:00:00 +0000</pubDate>
    <description>A quantity query counts children, so it re-runs whenever the list changes. Keep the threshold to one breakpoint: chaining several counts makes the layout jump twice while items are still loading in.</description>
  </item>
  <item>
    <title>showModal() — A modal that traps focus for you</title>
    <link>https://web-craft.net/elements/modal-that-traps-focus-for-you/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/modal-that-traps-focus-for-you/</guid>
    <category>dialog</category>
    <pubDate>Sun, 02 Aug 2026 00:00:00 +0000</pubDate>
    <description>show() and showModal() are different elements in practice. Only the modal one gets ::backdrop, makes the rest of the page inert, traps focus and closes on Escape. Call the wrong one and you have a floating box with none of it.</description>
  </item>
  <item>
    <title>popovertarget — A popover with no JavaScript at all</title>
    <link>https://web-craft.net/elements/popover-with-no-javascript-at-all/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/popover-with-no-javascript-at-all/</guid>
    <category>dialog</category>
    <pubDate>Sun, 02 Aug 2026 00:00:00 +0000</pubDate>
    <description>It lives in the top layer, so z-index on it or on anything around it is meaningless. Stacking is decided by the order things were promoted, and that trips up anyone debugging it the usual way.</description>
  </item>
  <item>
    <title>inert — A section the page cannot reach</title>
    <link>https://web-craft.net/elements/section-the-page-cannot-reach/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/section-the-page-cannot-reach/</guid>
    <category>a11y</category>
    <pubDate>Sun, 02 Aug 2026 00:00:00 +0000</pubDate>
    <description>inert removes the subtree from focus order and from the accessibility tree, which pointer-events: none and disabled do not. Do not add it around an open modal: showModal() already inerts the rest of the page, and doing both can strand focus.</description>
  </item>
  <item>
    <title>@starting-style — Animating something in from display: none</title>
    <link>https://web-craft.net/elements/animating-something-in-from-display-none/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/animating-something-in-from-display-none/</guid>
    <category>motion</category>
    <pubDate>Sat, 01 Aug 2026 00:00:00 +0000</pubDate>
    <description>There is nothing to transition from when an element appears: it had no previous style. @starting-style supplies that first frame. Without it the element simply snaps into place and the transition never runs.</description>
  </item>
  <item>
    <title>allow-discrete — The exit animation, which is the hard half</title>
    <link>https://web-craft.net/elements/exit-animation-which-is-the-hard-half/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/exit-animation-which-is-the-hard-half/</guid>
    <category>motion</category>
    <pubDate>Sat, 01 Aug 2026 00:00:00 +0000</pubDate>
    <description>display is a discrete property: it flips at the halfway point, so the element vanishes mid-fade. allow-discrete makes the browser hold display: none back until the rest of the transition has finished.</description>
  </item>
  <item>
    <title>startViewTransition() — Reordering a list without it jumping</title>
    <link>https://web-craft.net/elements/reordering-a-list-without-it-jumping/</link>
    <guid isPermaLink="true">https://web-craft.net/elements/reordering-a-list-without-it-jumping/</guid>
    <category>motion</category>
    <pubDate>Sat, 01 Aug 2026 00:00:00 +0000</pubDate>
    <description>Every element you want animated needs a view-transition-name, and each one has to be unique at the moment of the transition. Two matching names and the transition is skipped outright, with an error only in the console.</description>
  </item>
</channel>
</rss>
