惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
News and Events Feed by Topic
GbyAI
GbyAI
博客园 - Franky
宝玉的分享
宝玉的分享
Blog — PlanetScale
Blog — PlanetScale
Google DeepMind News
Google DeepMind News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
人人都是产品经理
人人都是产品经理
Microsoft Azure Blog
Microsoft Azure Blog
The Register - Security
The Register - Security
腾讯CDC
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
I
InfoQ
The Cloudflare Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
有赞技术团队
有赞技术团队
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
F
Full Disclosure
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Vercel News
Vercel News
博客园 - 【当耐特】
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
S
Schneier on Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Project Zero
Project Zero
量子位
M
MIT News - Artificial intelligence
Stack Overflow Blog
Stack Overflow Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
美团技术团队
Attack and Defense Labs
Attack and Defense Labs
C
Cybersecurity and Infrastructure Security Agency CISA
T
The Blog of Author Tim Ferriss
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Troy Hunt's Blog
Google Online Security Blog
Google Online Security Blog
罗磊的独立博客
P
Proofpoint News Feed
Schneier on Security
Schneier on Security
Spread Privacy
Spread Privacy
S
SegmentFault 最新的问题
L
LINUX DO - 最新话题
Simon Willison's Weblog
Simon Willison's Weblog
爱范儿
爱范儿
博客园 - 聂微东
A
About on SuperTechFans
PCI Perspectives
PCI Perspectives
D
Docker

1A23 Blog

Rotated Background Patterns in CSS with SVG Shift-JIS / UTF-8 文字化け解読:実はもうちょっと読めるかも DAM Karaoke in Round1 Tukwila from the View of a Vocaloid Enjoyer ひとりのボカロファンから見る Round1 Tukwila の DAM カラオケ Reverse engineering an IL2CPP NSO binary: Case study of Mojipittan Encore Use WebVTT without actually using WebVTT: Another way to monitor playback progress of HTML Media Elements Flexible and dynamic flow control of Azure DevOps YAML Pipelines using variables Content-aware Infinite Scroll Loop using JavaScript 『初音ミクの消失合作』セリフ文字起こし
Progress Bar Labels with CSS Anchor Positioning
Eana Hufwe · 2025-11-29 · via 1A23 Blog

Here’s a small but fun use case for CSS Anchor Positioning, using it to keep multiple labels around a progress bar readable, without touching JavaScript.

The goal is simple: we have a horizontal progress bar with three labels: one on the left, one on the right, and one that should follow the progress “tip”. We want that center label to sit as close as possible to the current progress, but never overlap with either side label.

To make things easier, we’ll assume:

  • Only the center label needs to move dynamically, the side labels stay at their ends.
  • The progress bar is wide enough to fit all three labels with some spacing.

Describing the layout as rules

Instead of hard-coding coordinates, it helps to think in terms of a small set of layout rules the browser can try in order.

For the center label, the logic can be written as:

  1. Try placing the center label to the left of the progress tip, with a margin.
  2. If that would overlap something, try placing it to the right of the progress tip, also with a margin.
  3. If the tip is already too close to another label, place the center label next to that label instead, with a wider margin to keep everything readable.

CSS Anchor Positioning is very good at this style of “try a few positions until one fits” layout. The @position-try at-rules let us declare those strategies explicitly and let the browser pick whichever one does not collide with the container or other constraints.

In this example, I use three named anchors:

  • --prog-bar: the progress bar itself (specifically, its right edge as the “tip”)
  • --left-label: the fixed label on the left
  • --right-label: the fixed label on the right.

The moving center label is then positioned relative to these anchors.

Defining @position-try strategies

Here are the two position-try rules that implement the logic above:

@position-try --bar-left {

position-area: none;

right: max(

calc(anchor(--prog-bar right) + var(--container-padding)),

calc(anchor(--right-label left) + var(--label-gap))

);

margin-left: calc(

var(--container-padding) + anchor-size(--left-label width) +

var(--label-gap)

);

}

@position-try --bar-right {

position-area: none;

left: max(

calc(anchor(--prog-bar right) + var(--container-padding)),

calc(anchor(--left-label right) + var(--label-gap))

);

margin-right: calc(

var(--label-gap) + anchor-size(--right-label width) +

var(--container-padding)

);

}

Conceptually:

  • --bar-left corresponds to “try to sit just to the left of the progress tip”.
  • --bar-right corresponds to “otherwise, sit just to the right of the progress tip”.

The “third rule” (move next to whichever label is closer) is effectively folded into the max() expressions:

  • For right / left we take the maximum of:
    • the tip position plus container padding, and
    • the neighbouring label plus a label gap.

This means:

  • If there’s plenty of room, the center label hugs the progress tip.
  • If the tip is about to collide with a side label, the center label gets pushed away so that it sits beside that label instead, maintaining at least var(--label-gap) of space.

Avoiding overlap with anchor-size()

The margins are where the overlap-avoidance really happens.

Take this line as an example:

margin-left: calc(

var(--container-padding) + anchor-size(--left-label width) +

var(--label-gap)

);

Here we:

  • Read the actual width of the left label via anchor-size(--left-label width).
  • Add the container’s padding and a label gap.
  • Use that as the center label’s margin, so its text always clears the left label by at least that gap.

In other words, instead of guessing spacing with hard-coded numbers, we attach the spacing directly to the real measured size of the anchors. That’s exactly the kind of thing anchor-size() is designed for.

The same idea is used for margin-right with the right label.

Putting it together

Once the @position-try rules are defined, the center label simply opts in to them, for example:

.label.center {

position: absolute;

top: var(--container-padding);

position-try: --bar-left, --bar-right;

position-anchor: --prog-bar;

position-area: left;

}

The browser will then:

  1. Try --bar-left.
  2. If that would cause an overlap or violate constraints, fall back to --bar-right.

Combined with the max() insets and anchor-size()-based margins, that’s enough to:

  • Keep the center label near the progress tip,
  • Prevent it from overlapping either side label,
  • Adjust spacing automatically if label text length changes,
  • Do all of this with zero JavaScript.

The full implementation – including the anchors and layout container – is in the CodePen embed above.

Browser support

CSS Anchor Positioning is still relatively new, and support is rolling out across browsers. Before using this technique in production, it’s worth checking current support status or adding a progressive enhancement fallback.

You can use the Baseline widget below to see the latest support details for anchor positioning across engines, and upvote the feature you want to see become interoperable across major browsers: