Alternate Titles:
- “Something’s Rotten in The Consortium”
- “It’s Batpoop Crazy Easy To Break Anchors”
I feel like an idiot, because I’m very guilty of telling people that one of the amazing benefits of Anchor Positioning in CSS is that you can position elements relative to other elements regardless of where they are in the DOM. It’s that italic, regardless, that’s the problem.
No, Chris, you can’t. Sorry about that. There are a bunch of limitations which can feel quite inscrutable at first. New types of problems that, to my knowledge, haven’t existed quite like this in CSS before.
Here’s a little rant about it:
I’m trying to be dramatic there on purpose because I really do think that the CSS powers that be should do something about this. I’m sure there are reasons why it behaves the way it does now, and I’ll bet a dollar that speed is a part of it. But it’s way too footgunny (as in: easy to do the wrong thing) right now. I gotta imagine the anchor-resolving part of the grand CSS machine could do a “second pass” or the like to find the anchor.
If you’re logged into CodePen, open this demo and move the DOM positions as I did in the video to see it happen.
It’s Fixable.
It’s a smidge convoluted that I’d move the tooltip before the anchor, I suppose. You can just: not do that. But it’s symbolic that you can’t just do whatever you want with DOM placement of these things an expect it to work.
Temani Afif has a good article about all this, which has a strong callout that I’ll echo:
The anchor element must be fully laid out before the element that is anchored to it.
So you have to be thinking about the position value quite a bit. There is almost a 100% chance that the element you’re trying to position to an anchor is position: absolute;. It’s the anchor itself that’s more concerning. If they are siblings, and the anchor has any position value other than the default static, the anchor has to come first. If they are in other positions in the DOM, like the anchor is a parent or totally elsewhere, you need to ensure they are in the same “containing block” or that the anchor parent still has that static positioning. Again, Temani has a deeper dive into this that explains it well.
James Stuckey Weber also has an article on this. His callout is a bit more specific:
For the best chance of having anchor positioning work, here’s my recommendation:
- Make the anchor and the positioned element siblings.
- Put the anchor first in the DOM.
Part of me likes that simplified advice as it’s understandable and teachable.
A bigger part of me hates that. This is a weird new problem that CSS has given us. We haven’t had to root out problems like this in CSS before and I don’t exactly welcome a new class of troubleshooting. So again: I think CSS should fix this going forward if they can.
If you’re further confused by how to position things even if you have the anchor working…
- First, anchor-tool is very helpful to remember how the “span” thing works which I’ve yet to have fully sink into my briain.
- Second, the area you’re anchoring to is kinda like a grid cell, so you can
alignandjustifystuff inside of it. But where does this “cell” occupy? It’s called the Inset-Modified Containing Block (IMCB) and Bramus has a good explanation. Theinsetpart basically means shrinking it by pushing against the cell walls. Also IMCB is so weirdly close to ICBM, but I guess they can both blow you up.

Love the rant. Another CSS trap that will make people lose hours trying to fix the bug before finding the ridiculously simple “solution”.
I talk about this a little bit in my article on anchored container queries: https://piccalil.li/blog/building-dynamic-toggletips-using-anchored-container-queries/ — it certainly didn’t align with my mental model of how it should work, but I guess it makes sense once you understand it.
Don’t accept it! Fight!
Sir I am 5′ 3″
This is something that could be meaningfully addressed by chrome having a little tooltip in the inspector when the anchor tag can’t be found (greyed out) like “anchor name could not be found at this position. make sure the anchored element is defined after the anchor element in the DOM”
Yeah totally agree. I think the reason they’ll need to show is more complicated than that but they can figure it out. (and maybe when they figure out how to display it, they’ll figure out how to just fix it instead (EVIL LAUGHTER)).
This is exactly the kind of nuance that makes modern CSS both powerful yet occasionally frustrating. I spent quite some time wondering why my anchor wasn’t resolving until I realized the DOM order was the culprit. Your suggestion for a ‘second pass’ in the resolving engine would be a massive DX improvement. Thanks for the heads-up and the clear breakdown, Chris!