Read a position

Where a box sits in a row, in pixels from the row’s start.

In CSS, a box stretched from its parent’s left edge to an anchor’s left edge with right: anchor(--target left) is as wide as the gap, and a query container inside it reads the gap as a number. It followed the anchor in the same frame while an animated sibling moved it (Chrome 155, WebKit 26.4 and Firefox 158: 8 of 8 frames); CSS Anchor Positioning 1 lets an anchor moved by a transform lag a few frames.

Example

Result
Markup
<div class="read-a-position">
  <i style="--value: 60"></i>
  <i style="--value: 140"></i>
  <i class="target"></i>
  <b>
    <span><output></output></span>
  </b>
</div>
CSS
@property --result { syntax: '<integer>'; inherits: true; initial-value: 0; }
.read-a-position output::after { counter-reset: result var(--result); content: counter(result); }
.read-a-position { position: relative; display: flex; }
.read-a-position > i { flex: none; width: calc(var(--value) * 1px); }
.read-a-position > .target { anchor-name: --target; }
.read-a-position > b { position: absolute; left: 0; right: anchor(--target left); }
.read-a-position > b > span { display: block; container-type: inline-size; }
.read-a-position > b > span > output { --result: round(100cqw / 1px); }
/* only makes room for the answer */
.read-a-position { min-height: 1lh; }

Limits

  • the box absolutely positioned in the row, and the row positioned (position: relative); the anchor an item of the row: an anchor that is itself absolutely positioned has to come before the box, and Firefox 158 doesn’t follow one that moves
  • the anchor at or after the row’s start: a box can’t be narrower than 0, so a position before the row reads 0
  • no gap between the items: a gap adds to the position read
  • the items packed at the row’s start, with no padding there: the box starts at the row’s padding edge (left: 0), so padding or justify-content adds its offset to the read
  • the query container inside the anchored box, not the box itself: WebKit 26.4 reads 0 when a lone anchored box is the container (measured)
  • a whole-number answer: the read rounds to 1px
  • each answer under 1,000,000: from a million up, Chrome passes --result on as 1e+06, which counter-reset rejects, so the counter prints 0
  • no margins, padding or borders on the items or the query containers: they add to the widths read, and 100cqw reads the content box
  • no example nested inside another’s row: an anchor name is the whole document’s, so the outer box takes the inner example’s anchor (400 for 200)
  • no other registration of --result on the page: a later @property --result that doesn’t inherit leaves the read right and the counter at 0

Browser support

ChromeSafariFirefox
Example14026158

Each row gives the first versions that support every feature its example uses, by MDN’s browser-compat-data. The Example was run in Chrome 155, Safari’s WebKit 26.4 and Firefox 158.