Anchored Auto Layout
npm

Hover or focus a box to measure it. Click its tag, or press ] and [, to pin one. Esc unpins.

    Legend
    • Anchor: a box with data-⚓️-name
    • Placed by anchors: out of flow
    • Gap from the anchor's edge, in px
    • Edges of the box you're inspecting

    Every tag, line and number here is itself placed by data-⚓️-* attributes. JS only measures.

    Filter, sort & drag grid that glides

    Filter chips hide cells, sort buttons and drag/Alt+arrow reorder only change CSS order; every swatch is anchored to its grid cell with data-⚓️-fill + data-⚓️-transition="glide" + data-⚓️-scope-name, so it glides to it…

    Full page
    <header class="intro">
      <h1>Filter, sort &amp; drag grid</h1>
      <p>
        A plain CSS grid of invisible cells reflows instantly; every swatch is anchored to its cell with
        <code>data-⚓️-fill</code> and glides after it (<code>data-⚓️-transition="glide"</code>,
        <code>data-⚓️-scope-name</code> so all cells share one anchor name). Filters toggle <code>hidden</code>,
        sorting and dragging only change each cell's CSS <code>order</code>. Drag a swatch (grip on touch) or
        focus one and press <kbd>Alt</kbd>+<kbd>←</kbd>/<kbd>→</kbd>.
      </p>
    </header>
    
    <div class="toolbar">
      <fieldset class="chips" aria-label="Filter">
        <label><input type="radio" name="filter" value="all" checked><span>All <i>24</i></span></label>
        <label><input type="radio" name="filter" value="warm"><span>Warm <i>8</i></span></label>
        <label><input type="radio" name="filter" value="cool"><span>Cool <i>8</i></span></label>
        <label><input type="radio" name="filter" value="neutral"><span>Neutral <i>8</i></span></label>
      </fieldset>
      <fieldset class="chips" aria-label="Sort">
        <label><input type="radio" name="sort" value="hue"><span>Hue</span></label>
        <label><input type="radio" name="sort" value="light"><span>Lightness</span></label>
        <label><input type="radio" name="sort" value="name"><span>A–Z</span></label>
        <button id="shuffle" type="button">Shuffle</button>
      </fieldset>
      <label class="xray-toggle"><input type="checkbox" id="xray"> X-ray</label>
    </div>
    
    <div class="grid" id="grid" data-⚓️-root>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="warm" data-l="58" data-c="0.13" data-h="45">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(58% .13 45)" aria-label="Terracotta">
          <span class="face"><b>Terracotta</b><small>58% .13 45</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="neutral" data-l="80" data-c="0.01" data-h="250">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(80% .01 250)" aria-label="Fog">
          <span class="face"><b>Fog</b><small>80% .01 250</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="neutral" data-l="96" data-c="0.01" data-h="80">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(96% .01 80)" aria-label="Linen">
          <span class="face"><b>Linen</b><small>96% .01 80</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="cool" data-l="40" data-c="0.1" data-h="290">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(40% .1 290)" aria-label="Dusk">
          <span class="face"><b>Dusk</b><small>40% .1 290</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="warm" data-l="86" data-c="0.06" data-h="10">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(86% .06 10)" aria-label="Blush">
          <span class="face"><b>Blush</b><small>86% .06 10</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="cool" data-l="86" data-c="0.09" data-h="165">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(86% .09 165)" aria-label="Mint">
          <span class="face"><b>Mint</b><small>86% .09 165</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="neutral" data-l="70" data-c="0.015" data-h="70">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(70% .015 70)" aria-label="Stone">
          <span class="face"><b>Stone</b><small>70% .015 70</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="neutral" data-l="22" data-c="0.015" data-h="270">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(22% .015 270)" aria-label="Ink">
          <span class="face"><b>Ink</b><small>22% .015 270</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="warm" data-l="75" data-c="0.14" data-h="75">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(75% .14 75)" aria-label="Honey">
          <span class="face"><b>Honey</b><small>75% .14 75</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="neutral" data-l="65" data-c="0.025" data-h="50">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(65% .025 50)" aria-label="Clay">
          <span class="face"><b>Clay</b><small>65% .025 50</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="cool" data-l="50" data-c="0.18" data-h="260">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(50% .18 260)" aria-label="Cobalt">
          <span class="face"><b>Cobalt</b><small>50% .18 260</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="neutral" data-l="93" data-c="0.015" data-h="85">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(93% .015 85)" aria-label="Bone">
          <span class="face"><b>Bone</b><small>93% .015 85</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="cool" data-l="65" data-c="0.12" data-h="200">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(65% .12 200)" aria-label="Lagoon">
          <span class="face"><b>Lagoon</b><small>65% .12 200</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="warm" data-l="62" data-c="0.2" data-h="35">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(62% .2 35)" aria-label="Ember">
          <span class="face"><b>Ember</b><small>62% .2 35</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="cool" data-l="72" data-c="0.07" data-h="150">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(72% .07 150)" aria-label="Sage">
          <span class="face"><b>Sage</b><small>72% .07 150</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="cool" data-l="88" data-c="0.05" data-h="220">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(88% .05 220)" aria-label="Glacier">
          <span class="face"><b>Glacier</b><small>88% .05 220</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="warm" data-l="70" data-c="0.16" data-h="25">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(70% .16 25)" aria-label="Coral">
          <span class="face"><b>Coral</b><small>70% .16 25</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="neutral" data-l="35" data-c="0.01" data-h="260">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(35% .01 260)" aria-label="Graphite">
          <span class="face"><b>Graphite</b><small>35% .01 260</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="warm" data-l="82" data-c="0.16" data-h="85">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(82% .16 85)" aria-label="Saffron">
          <span class="face"><b>Saffron</b><small>82% .16 85</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="warm" data-l="80" data-c="0.12" data-h="65">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(80% .12 65)" aria-label="Apricot">
          <span class="face"><b>Apricot</b><small>80% .12 65</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="neutral" data-l="55" data-c="0.02" data-h="250">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(55% .02 250)" aria-label="Slate">
          <span class="face"><b>Slate</b><small>55% .02 250</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="cool" data-l="45" data-c="0.09" data-h="160">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(45% .09 160)" aria-label="Pine">
          <span class="face"><b>Pine</b><small>45% .09 160</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="warm" data-l="48" data-c="0.13" data-h="15">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(48% .13 15)" aria-label="Rosewood">
          <span class="face"><b>Rosewood</b><small>48% .13 15</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
      <div class="cell" data-⚓️-name="--cell" data-⚓️-scope-name="--cell" data-family="cool" data-l="58" data-c="0.17" data-h="285">
        <button class="tile" data-⚓️-to="--cell" data-⚓️-fill data-⚓️-transition="glide" style="--c: oklch(58% .17 285)" aria-label="Iris">
          <span class="face"><b>Iris</b><small>58% .17 285</small><span class="grip" aria-hidden="true">⠿</span></span>
        </button>
      </div>
    </div>

    data-⚓️-filldata-⚓️-namedata-⚓️-rootdata-⚓️-scope-namedata-⚓️-todata-⚓️-transition

    Copied