{"id":8803,"date":"2026-03-05T10:41:27","date_gmt":"2026-03-05T15:41:27","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=8803"},"modified":"2026-03-05T10:41:28","modified_gmt":"2026-03-05T15:41:28","slug":"the-big-gotcha-of-anchor-positioning","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/the-big-gotcha-of-anchor-positioning\/","title":{"rendered":"The Big Gotcha of Anchor Positioning"},"content":{"rendered":"\n<p>Alternate Titles:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>&#8220;Something&#8217;s Rotten in The Consortium&#8221;<\/li>\n\n\n\n<li>&#8220;It&#8217;s Batpoop Crazy Easy To Break Anchors&#8221;<\/li>\n<\/ul>\n\n\n\n<p>I feel like an idiot, because I&#8217;m very guilty of telling people that one of the <em>amazing benefits<\/em> of Anchor Positioning in CSS is that you can position elements relative to other elements <em>regardless<\/em> of where they are in the DOM. <span style=\"box-sizing: border-box; margin: 0px; padding: 0px;\">It&#8217;s that italic,&nbsp;<em>regardles<\/em><\/span>s,&nbsp;that&#8217;s the problem.<\/p>\n\n\n\n<p>No, Chris, you can&#8217;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&#8217;t existed quite like this in CSS before.<\/p>\n\n\n\n<p>Here&#8217;s a little rant about it:<\/p>\n\n\n\n\t\t<figure class=\"wp-block-jetpack-videopress jetpack-videopress-player aligncenter wp-block-jetpack-videopress--has-max-width\" style=\"max-width: 448px;\" >\n\t\t\t<div class=\"jetpack-videopress-player__wrapper\"> <iframe title=\"VideoPress Video Player\" aria-label='VideoPress Video Player' width='420' height='750' src='https:\/\/videopress.com\/embed\/sSKz4YXg?cover=1&amp;autoPlay=0&amp;controls=1&amp;loop=0&amp;muted=0&amp;persistVolume=1&amp;playsinline=0&amp;preloadContent=metadata&amp;useAverageColor=1&amp;hd=0' frameborder='0' allowfullscreen data-resize-to-parent=\"true\" allow='clipboard-write'><\/iframe><script src='https:\/\/v0.wordpress.com\/js\/next\/videopress-iframe.js?m=1770107250'><\/script><\/div>\n\t\t\t\n\t\t\t\n\t\t<\/figure>\n\t\t\n\n\n<p class=\"learn-more\">I&#8217;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&#8217;m <em>sure<\/em> there are reasons why it behaves the way it does now, and I&#8217;ll bet a dollar that speed is a part of it. But it&#8217;s <em>way<\/em> 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 &#8220;second pass&#8221; or the like to find the anchor.<\/p>\n\n\n\n<p>If you&#8217;re logged into CodePen, <a href=\"https:\/\/codepen.io\/editor\/chriscoyier\/pen\/019c9cfc-d6b3-7f43-8be6-9430d3c42f63\">open this demo<\/a> and move the DOM positions as I did in the video to see it happen.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_019c9cfc-d6b3-7f43-8be6-9430d3c42f63\" src=\"\/\/codepen.io\/editor\/anon\/embed\/019c9cfc-d6b3-7f43-8be6-9430d3c42f63?height=450&amp;theme-id=1&amp;slug-hash=019c9cfc-d6b3-7f43-8be6-9430d3c42f63&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed 019c9cfc-d6b3-7f43-8be6-9430d3c42f63\" title=\"CodePen Embed 019c9cfc-d6b3-7f43-8be6-9430d3c42f63\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">It&#8217;s Fixable. <\/h2>\n\n\n\n<p>It&#8217;s a <em>smidge<\/em> convoluted that I&#8217;d move the tooltip <em>before<\/em> the anchor, I suppose. You can just: not do that. But it&#8217;s symbolic that you can&#8217;t just <em>do whatever you want<\/em> with DOM placement of these things an expect it to work. <\/p>\n\n\n\n<p><a href=\"https:\/\/css-tip.com\/anchor-issues\/\">Temani Afif has a good article <\/a>about all this, which has a strong callout that I&#8217;ll echo:<\/p>\n\n\n\n<p class=\"learn-more\"><strong>The anchor element must be fully laid out before the element that is anchored to it.<\/strong><\/p>\n\n\n\n<p>So you have to be thinking about the <code>position<\/code> value quite a bit. There is almost a 100% chance that the element you&#8217;re trying to position to an anchor is <code>position: absolute;<\/code>. It&#8217;s the anchor itself that&#8217;s more concerning. If they are siblings, and the anchor has any <code>position<\/code> value other than the default <code>static<\/code>, the anchor <em>has<\/em> 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 &#8220;containing block&#8221; or that the anchor parent still has that <code>static<\/code> positioning. Again, Temani has <a href=\"https:\/\/css-tip.com\/anchor-issues\/\">a deeper dive<\/a> into this that explains it well. <\/p>\n\n\n\n<p><a href=\"https:\/\/www.oddbird.net\/2025\/01\/29\/anchor-position-validity\/\">James Stuckey Weber also has an article on this<\/a>. His callout is a bit more specific:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>For the best chance of having anchor positioning work, here\u2019s my recommendation:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Make the anchor and the positioned element siblings.<\/li>\n\n\n\n<li>Put the anchor first in the\u00a0DOM.<\/li>\n<\/ol>\n<\/blockquote>\n\n\n\n<p>Part of me likes that simplified advice as it&#8217;s understandable and teachable. <\/p>\n\n\n\n<p>A bigger part of me hates that. This is a weird new problem that CSS has given us. We haven&#8217;t had to root out problems like this in CSS before and I don&#8217;t exactly welcome a new class of troubleshooting. So again: I think CSS should fix this going forward if they can.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>If you&#8217;re further confused by how to position things even if you have the anchor working&#8230;<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>First, <a href=\"https:\/\/anchor-tool.com\/\">anchor-tool <\/a>is very helpful to remember how the &#8220;span&#8221; thing works which I&#8217;ve yet to have fully sink into my briain.<\/li>\n\n\n\n<li>Second, the area you&#8217;re anchoring to is <em>kinda<\/em> like a grid cell, so you can <code>align<\/code> and <code>justify<\/code> stuff inside of it. But where does this &#8220;cell&#8221; occupy? It&#8217;s called the Inset-Modified Containing Block (IMCB) and <a href=\"https:\/\/www.bram.us\/2025\/12\/02\/anchor-positioning-and-the-inset-modified-containing-block-imcb\/\">Bramus has a good explanation<\/a>. The <code>inset<\/code> part 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. <\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>As it stands, you have to think about the layout engine and whether an element is &#8220;fully laid out&#8221; before an anchor is allowed to apply to it. Boooooo.<\/p>\n","protected":false},"author":1,"featured_media":8876,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[121,7,459],"class_list":["post-8803","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-anchor","tag-css","tag-imcb"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2026\/03\/anchor-pos.jpg?fit=2000%2C1200&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/8803","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/comments?post=8803"}],"version-history":[{"count":9,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/8803\/revisions"}],"predecessor-version":[{"id":8877,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/8803\/revisions\/8877"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/8876"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=8803"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=8803"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=8803"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}