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.

    iOS adaptive dashboard: size classes, readable guide & priorities

    A Health-style summary built like a UIKit screen, with widget cards that go from one column to two by swapping one data-⚓️-side value and their width multipliers.

    Full page
    <div class="stage" data-device="fill" data-orient="portrait">
      <div class="device">
        <div class="app" data-⚓️-root data-size-class="compact" data-booting>
          <!-- the whole screen as a layout guide (the device notch/home indicator anchor to it) -->
          <div class="screen-guide" data-⚓️-name="--screen" aria-hidden="true"></div>
    
          <!-- regular width only: iPadOS-style sidebar (primary column of a split view) -->
          <nav class="sidebar" aria-label="Health sections">
            <h2 class="sidebar-title">Health</h2>
            <label class="search"><svg viewBox="0 0 20 20" aria-hidden="true"><circle cx="8.5" cy="8.5" r="5.5"/><path d="m13 13 4 4"/></svg><input type="search" placeholder="Search" aria-label="Search"></label>
            <ul class="side-list">
              <li><button class="side-item is-current" data-go="top"><span class="side-icon" style="--tint: var(--pink)">♥</span>Summary</button></li>
              <li><button class="side-item" data-go="top"><span class="side-icon" style="--tint: var(--blue)">⇄</span>Sharing</button></li>
            </ul>
            <h3 class="side-heading">Health Categories</h3>
            <ul class="side-list">
              <li><button class="side-item" data-go="c1"><span class="side-icon" style="--tint: var(--red)">◎</span>Activity</button></li>
              <li><button class="side-item" data-go="c3"><span class="side-icon" style="--tint: var(--pink)">♥</span>Heart</button></li>
              <li><button class="side-item" data-go="c6"><span class="side-icon" style="--tint: var(--teal)">✺</span>Mindfulness</button></li>
              <li><button class="side-item" data-go="c5"><span class="side-icon" style="--tint: var(--orange)">➚</span>Mobility</button></li>
              <li><button class="side-item" data-go="c7"><span class="side-icon" style="--tint: var(--green)">✚</span>Nutrition</button></li>
              <li><button class="side-item" data-go="c4"><span class="side-icon" style="--tint: var(--indigo)">☾</span>Sleep</button></li>
            </ul>
          </nav>
    
          <section class="pane" data-⚓️-root data-⚓️-name="--pane" aria-label="Summary">
            <!-- safeAreaLayoutGuide: the pane minus the (real or simulated) safe-area insets -->
            <div class="safe-guide" data-⚓️-name="--safe" data-ix="safeAreaLayoutGuide" aria-hidden="true"></div>
    
            <div class="scroller">
              <div class="content" data-⚓️-root>
                <!-- layoutMarginsGuide = safe area inset by 16pt (compact) / 20pt (regular) -->
                <div class="margins-guide" data-⚓️-name="--margins" data-ix="layoutMarginsGuide">
                  <!-- readableContentGuide = margins, capped at 672pt wide and centred -->
                  <div class="readable-guide" data-⚓️-name="--readable" data-ix="readableContentGuide">
                    <header class="large-header" data-⚓️-name="--header" data-ix="header">
                      <p class="eyebrow">Thursday, 24 September</p>
                      <h1 class="large-title" data-⚓️-name="--large-title" data-ix="largeTitle">Summary</h1>
                    </header>
                  </div>
                </div>
    
                <!-- avatar: centerY to the large title, trailing to the readable guide -->
                <button class="avatar" aria-label="Profile" data-ix="avatar"
                  data-⚓️-to="--large-title" data-⚓️-align-y="center" data-⚓️-align-trailing="--readable">AA</button>
    
                <!-- Cards: each one is anchored to the previous one (a hand-built stack view).
                     JS only swaps the side (below | after) when the size class changes. -->
                <article class="card" id="c1" style="--tint: var(--red)" data-ix="activityCard" data-regular="below"
                  data-⚓️-name="--c1" data-⚓️-to="--header" data-⚓️-side="below"
                  data-⚓️-align-leading="--readable" data-⚓️-sync-width="--readable" data-⚓️-transition="glide">
                  <div class="card-body" data-⚓️-scope="all">
                    <div class="card-head" data-⚓️-name="--head">
                      <span class="card-title" data-⚓️-name="--title"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M10 2c1 3 5 5 5 10a5 5 0 0 1-10 0c0-3 2-4 2-6 2 1 2 3 2 3 1-2 1-5 1-7Z"/></svg>Activity</span>
                    </div>
                    <span class="card-meta" data-⚓️-to="--head" data-⚓️-after="--title" data-⚓️-align-trailing="--head" data-⚓️-align-y="center"><span>Today, 9:41 AM</span></span>
                    <div class="activity">
                      <svg class="rings" viewBox="0 0 100 100" data-ix="rings" aria-label="Move 84%, Exercise 80%, Stand 75%" role="img">
                        <circle class="track m" cx="50" cy="50" r="42"/><circle class="ring m" cx="50" cy="50" r="42" pathLength="100" stroke-dasharray="84 100"/>
                        <circle class="track e" cx="50" cy="50" r="30"/><circle class="ring e" cx="50" cy="50" r="30" pathLength="100" stroke-dasharray="80 100"/>
                        <circle class="track s" cx="50" cy="50" r="18"/><circle class="ring s" cx="50" cy="50" r="18" pathLength="100" stroke-dasharray="75 100"/>
                      </svg>
                      <dl class="stats">
                        <div style="--tint: var(--move)"><dt>Move</dt><dd>420<small>/500 cal</small></dd></div>
                        <div style="--tint: var(--exercise)"><dt>Exercise</dt><dd>24<small>/30 min</small></dd></div>
                        <div style="--tint: var(--stand)"><dt>Stand</dt><dd>9<small>/12 hr</small></dd></div>
                      </dl>
                    </div>
                  </div>
                  <button class="card-hit" data-⚓️-pin-all aria-label="Open Activity details"></button>
                </article>
    
                <article class="card" id="c2" style="--tint: var(--orange)" data-ix="stepsCard" data-span="half" data-regular="below"
                  data-⚓️-name="--c2" data-⚓️-to="--c1" data-⚓️-side="below"
                  data-⚓️-align-leading="--readable" data-⚓️-sync-width="--readable" data-⚓️-transition="glide">
                  <div class="card-body" data-⚓️-scope="all">
                    <div class="card-head" data-⚓️-name="--head">
                      <span class="card-title" data-⚓️-name="--title" data-ix="steps.title" data-ix-extra="compressionResistance = 750 (required-ish: never truncates first)"><svg viewBox="0 0 20 20" aria-hidden="true"><ellipse cx="7" cy="7" rx="3" ry="4.5"/><ellipse cx="13" cy="12" rx="3" ry="4.5"/></svg>Steps</span>
                    </div>
                    <span class="card-meta" data-ix="steps.time" data-ix-extra="contentHugging = 750, compressionResistance = 250 (truncates first)"
                      data-⚓️-to="--head" data-⚓️-after="--title" data-⚓️-align-trailing="--head" data-⚓️-align-y="center"><span>Today, 9:41 AM</span></span>
                    <p class="metric" data-⚓️-name="--num"><span class="num">8,432</span> <span class="unit">steps</span></p>
                    <span class="badge" data-ix="steps.trend" data-ix-priority="250" data-ix-extra="optional: removed when it can't fit (no-overflow)"
                      data-⚓️-to="--num" data-⚓️-side="after" data-⚓️-align-y="center" data-⚓️-visibility="no-overflow">▲ 12%</span>
                    <div class="bars" aria-hidden="true"><i style="--v:.42"></i><i style="--v:.66"></i><i style="--v:.5"></i><i style="--v:.9"></i><i style="--v:.72"></i><i style="--v:.38"></i><i style="--v:.8"></i></div>
                  </div>
                  <button class="card-hit" data-⚓️-pin-all aria-label="Open Steps details"></button>
                </article>
    
                <article class="card" id="c3" style="--tint: var(--pink)" data-ix="heartCard" data-span="half" data-regular="after"
                  data-⚓️-name="--c3" data-⚓️-to="--c2" data-⚓️-side="below"
                  data-⚓️-align-leading="--readable" data-⚓️-sync-width="--readable" data-⚓️-transition="glide">
                  <div class="card-body" data-⚓️-scope="all">
                    <div class="card-head" data-⚓️-name="--head">
                      <span class="card-title" data-⚓️-name="--title"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M10 17S3 12.5 3 7.5A3.5 3.5 0 0 1 10 6a3.5 3.5 0 0 1 7 1.5C17 12.5 10 17 10 17Z"/></svg>Heart Rate</span>
                    </div>
                    <span class="card-meta" data-⚓️-to="--head" data-⚓️-after="--title" data-⚓️-align-trailing="--head" data-⚓️-align-y="center"><span>9:12 AM</span></span>
                    <p class="metric" data-⚓️-name="--num"><span class="num">68</span> <span class="unit">BPM</span></p>
                    <span class="badge" data-⚓️-to="--num" data-⚓️-side="after" data-⚓️-align-y="center" data-⚓️-visibility="no-overflow">Resting 58</span>
                    <div class="ranges" aria-hidden="true"><i style="--a:.35;--b:.7"></i><i style="--a:.3;--b:.55"></i><i style="--a:.4;--b:.95"></i><i style="--a:.25;--b:.6"></i><i style="--a:.3;--b:.8"></i><i style="--a:.45;--b:.7"></i><i style="--a:.2;--b:.5"></i><i style="--a:.35;--b:.85"></i><i style="--a:.3;--b:.62"></i></div>
                  </div>
                  <button class="card-hit" data-⚓️-pin-all aria-label="Open Heart Rate details"></button>
                </article>
    
                <article class="card" id="c4" style="--tint: var(--indigo)" data-ix="sleepCard" data-span="half" data-regular="below"
                  data-⚓️-name="--c4" data-⚓️-to="--c3" data-⚓️-side="below"
                  data-⚓️-align-leading="--readable" data-⚓️-sync-width="--readable" data-⚓️-transition="glide">
                  <div class="card-body" data-⚓️-scope="all">
                    <div class="card-head" data-⚓️-name="--head">
                      <span class="card-title" data-⚓️-name="--title"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M13 3a7 7 0 1 0 4 11A6 6 0 0 1 13 3Z"/></svg>Sleep</span>
                    </div>
                    <span class="card-meta" data-⚓️-to="--head" data-⚓️-after="--title" data-⚓️-align-trailing="--head" data-⚓️-align-y="center"><span>Last night</span></span>
                    <p class="metric" data-⚓️-name="--num"><span class="num">7</span> <span class="unit">hr</span> <span class="num">21</span> <span class="unit">min</span></p>
                    <div class="stages" aria-hidden="true"><i style="--x:0;--w:.12;--y:1"></i><i style="--x:.12;--w:.2;--y:2"></i><i style="--x:.32;--w:.1;--y:3"></i><i style="--x:.42;--w:.18;--y:2"></i><i style="--x:.6;--w:.08;--y:0"></i><i style="--x:.68;--w:.14;--y:2"></i><i style="--x:.82;--w:.1;--y:3"></i><i style="--x:.92;--w:.08;--y:1"></i></div>
                  </div>
                  <button class="card-hit" data-⚓️-pin-all aria-label="Open Sleep details"></button>
                </article>
    
                <article class="card" id="c5" style="--tint: var(--orange)" data-ix="distanceCard" data-span="half" data-regular="after"
                  data-⚓️-name="--c5" data-⚓️-to="--c4" data-⚓️-side="below"
                  data-⚓️-align-leading="--readable" data-⚓️-sync-width="--readable" data-⚓️-transition="glide">
                  <div class="card-body" data-⚓️-scope="all">
                    <div class="card-head" data-⚓️-name="--head">
                      <span class="card-title" data-⚓️-name="--title" data-ix="distance.title" data-ix-extra="compressionResistance = 750"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M3 15 8 9l3 3 6-7M13 5h4v4"/></svg>Walking + Running Distance</span>
                    </div>
                    <span class="card-meta" data-ix="distance.time" data-ix-extra="contentHugging = 750, compressionResistance = 250 (truncates first)"
                      data-⚓️-to="--head" data-⚓️-after="--title" data-⚓️-align-trailing="--head" data-⚓️-align-y="center"><span>Yesterday, 11:58 PM</span></span>
                    <p class="metric" data-⚓️-name="--num"><span class="num">5.2</span> <span class="unit">km</span></p>
                    <span class="badge" data-ix="distance.trend" data-ix-priority="250" data-ix-extra="optional: removed when it can't fit (no-overflow)"
                      data-⚓️-to="--num" data-⚓️-side="after" data-⚓️-align-y="center" data-⚓️-visibility="no-overflow">▲ 8% vs avg</span>
                    <svg class="line" viewBox="0 0 140 56" preserveAspectRatio="none" aria-hidden="true"><polyline points="0,44 20,38 40,40 60,26 80,30 100,14 120,20 140,10"/></svg>
                  </div>
                  <button class="card-hit" data-⚓️-pin-all aria-label="Open Walking and Running Distance details"></button>
                </article>
    
                <article class="card" id="c6" style="--tint: var(--teal)" data-ix="mindfulCard" data-span="half" data-regular="below"
                  data-⚓️-name="--c6" data-⚓️-to="--c5" data-⚓️-side="below"
                  data-⚓️-align-leading="--readable" data-⚓️-sync-width="--readable" data-⚓️-transition="glide">
                  <div class="card-body" data-⚓️-scope="all">
                    <div class="card-head" data-⚓️-name="--head">
                      <span class="card-title" data-⚓️-name="--title"><svg viewBox="0 0 20 20" aria-hidden="true"><circle cx="10" cy="10" r="3"/><circle cx="10" cy="4.5" r="2.5"/><circle cx="10" cy="15.5" r="2.5"/><circle cx="4.5" cy="10" r="2.5"/><circle cx="15.5" cy="10" r="2.5"/></svg>Mindful Minutes</span>
                    </div>
                    <span class="card-meta" data-⚓️-to="--head" data-⚓️-after="--title" data-⚓️-align-trailing="--head" data-⚓️-align-y="center"><span>Today</span></span>
                    <p class="metric" data-⚓️-name="--num"><span class="num">15</span> <span class="unit">min</span></p>
                    <div class="dots" aria-hidden="true"><i></i><i></i><i class="off"></i><i></i><i></i><i class="off"></i><i></i></div>
                  </div>
                  <button class="card-hit" data-⚓️-pin-all aria-label="Open Mindful Minutes details"></button>
                </article>
    
                <article class="card" id="c7" style="--tint: var(--green)" data-ix="waterCard" data-span="half" data-regular="after"
                  data-⚓️-name="--c7" data-⚓️-to="--c6" data-⚓️-side="below"
                  data-⚓️-align-leading="--readable" data-⚓️-sync-width="--readable" data-⚓️-transition="glide">
                  <div class="card-body" data-⚓️-scope="all">
                    <div class="card-head" data-⚓️-name="--head">
                      <span class="card-title" data-⚓️-name="--title"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M10 2s5 6 5 10a5 5 0 0 1-10 0c0-4 5-10 5-10Z"/></svg>Water</span>
                    </div>
                    <span class="card-meta" data-⚓️-to="--head" data-⚓️-after="--title" data-⚓️-align-trailing="--head" data-⚓️-align-y="center"><span>8:30 AM</span></span>
                    <p class="metric" data-⚓️-name="--num"><span class="num">1.4</span> <span class="unit">L</span></p>
                    <span class="badge" data-⚓️-to="--num" data-⚓️-side="after" data-⚓️-align-y="center" data-⚓️-visibility="no-overflow">56% of goal</span>
                    <div class="glass" aria-hidden="true"><i style="--v:.56"></i></div>
                  </div>
                  <button class="card-hit" data-⚓️-pin-all aria-label="Open Water details"></button>
                </article>
    
                <!-- contentInset.bottom: clearance for the floating toolbar, chained below the last card -->
                <div class="bottom-inset" aria-hidden="true" data-⚓️-to="--c7" data-⚓️-side="below" data-⚓️-align-leading="--readable"></div>
              </div>
            </div>
    
            <!-- blur navigation bar: pinned to the pane's top, inline title centred on the safe area -->
            <div class="navbar" data-⚓️-pin-top data-⚓️-pin-x aria-hidden="true"></div>
            <p class="inline-title" aria-hidden="true" data-ix="inlineTitle"
              data-⚓️-to="--safe" data-⚓️-align-top data-⚓️-align-x="center">Summary</p>
    
            <!-- X-ray bands: full-height stripes stretched to the two guides living in the scroller -->
            <div class="xr-band xr-margins" aria-hidden="true" data-⚓️-stretch-x="--margins" data-⚓️-pin-y></div>
            <div class="xr-band xr-readable" aria-hidden="true" data-⚓️-stretch-x="--readable" data-⚓️-pin-y></div>
    
            <!-- floating toolbar: bottom = safeArea.bottom - 8, centerX = safeArea.centerX -->
            <div class="pill" role="toolbar" aria-label="Demo controls" data-ix="toolbar"
              data-⚓️-name="--pill" data-⚓️-to="--safe" data-⚓️-align-bottom data-⚓️-align-x="center">
              <button class="pill-btn" id="inspect" aria-pressed="false"><svg viewBox="0 0 20 20" aria-hidden="true"><rect x="3" y="3" width="14" height="14" rx="3"/><path d="M3 8h14M8 8v9"/></svg><span>Constraints</span></button>
              <button class="pill-btn" id="sizeclass" aria-label="Size class"><svg viewBox="0 0 20 20" aria-hidden="true"><rect x="2.5" y="5" width="6" height="10" rx="1.5"/><rect x="11" y="3.5" width="6.5" height="13" rx="1.5"/></svg><span>Auto</span></button>
              <button class="pill-btn" id="rotate" aria-label="Device"><svg viewBox="0 0 20 20" aria-hidden="true"><rect x="6" y="2.5" width="8" height="15" rx="2"/><path d="M2.5 9a7.5 7.5 0 0 1 3-5.5M17.5 11a7.5 7.5 0 0 1-3 5.5"/></svg><span>Fill</span></button>
              <button class="pill-btn" id="dt" aria-label="Dynamic Type size"><span class="aa">Aa</span><span class="dt-label">Default</span></button>
            </div>
          </section>
    
          <!-- simulated hardware (device-frame modes only) -->
          <div class="island" aria-hidden="true" data-⚓️-name="--island" data-⚓️-to="--screen" data-⚓️-align-top data-⚓️-align-x="center"></div>
          <span class="status-time" aria-hidden="true" data-⚓️-to="--island" data-⚓️-align-y="center" data-⚓️-align-leading="--screen">9:41</span>
          <span class="status-icons" aria-hidden="true" data-⚓️-to="--island" data-⚓️-align-y="center" data-⚓️-align-trailing="--screen"><i></i><i></i><b></b></span>
          <div class="home-indicator" aria-hidden="true" data-⚓️-to="--screen" data-⚓️-align-bottom data-⚓️-align-x="center"></div>
        </div>
      </div>
      <p class="caption" aria-live="polite"></p>
    </div>
    
    <!-- Constraints inspector: grows out of the toolbar and sits above it -->
    <div class="inspector" id="inspector" popover="manual" aria-label="Constraints"
      data-⚓️-to="--pill" data-⚓️-side="above" data-⚓️-align-x="center"
      data-⚓️-morph-from data-⚓️-transition="morph">
      <header class="inspector-head">
        <strong>Constraints</strong>
        <span class="traits"></span>
      </header>
      <ol class="ix-list"></ol>
      <p class="ix-foot">Generated from the live <code>data-⚓️-*</code> attributes. Hover or focus a row to highlight its view.</p>
    </div>
    
    <!-- Detail sheet: compact = bottom sheet, regular = centred form sheet; morphs out of the tapped card -->
    <dialog class="sheet" aria-labelledby="sheet-title" data-⚓️-to="--pane" data-⚓️-transition="morph">
      <div class="grabber" aria-hidden="true"></div>
      <header class="sheet-bar">
        <h2 id="sheet-title">Steps</h2>
        <form method="dialog"><button class="done">Done</button></form>
      </header>
      <div class="sheet-content"></div>
    </dialog>

    data-⚓️-afterdata-⚓️-align-bottomdata-⚓️-align-leadingdata-⚓️-align-topdata-⚓️-align-trailingdata-⚓️-align-xdata-⚓️-align-ydata-⚓️-morph-fromdata-⚓️-namedata-⚓️-pin-alldata-⚓️-pin-topdata-⚓️-pin-xdata-⚓️-pin-ydata-⚓️-rootdata-⚓️-scopedata-⚓️-sidedata-⚓️-stretch-xdata-⚓️-sync-widthdata-⚓️-todata-⚓️-transitiondata-⚓️-visibility

    Copied