{"id":8194,"date":"2026-01-08T12:13:43","date_gmt":"2026-01-08T17:13:43","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=8194"},"modified":"2026-01-08T12:13:44","modified_gmt":"2026-01-08T17:13:44","slug":"popover-context-menus-with-anchor-positioning","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/popover-context-menus-with-anchor-positioning\/","title":{"rendered":"Popover Context Menus with Anchor Positioning"},"content":{"rendered":"\n<p>Tooltips are the classic use case for anchor positioning in CSS. You click a thing, and <em>right next to it<\/em> another thing opens up. That <em>other thing<\/em> could also be a menu. I mean \u2014 what&#8217;s a context menu aside from a tooltip with links, right? <\/p>\n\n\n\n<p>I&#8217;ll illustrate this with some appropriately common and vague components, like a &#8220;Kebab&#8221; menu button within a &#8220;Card&#8221; component:<\/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: 370px;\" >\n\t\t\t<div class=\"jetpack-videopress-player__wrapper\"> <iframe title=\"VideoPress Video Player\" aria-label='VideoPress Video Player' width='454' height='750' src='https:\/\/videopress.com\/embed\/OQ8m1U1e?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=1739540970'><\/script><\/div>\n\t\t\t<figcaption>This video comes from <a href=\"https:\/\/codepen.io\/editor\/chriscoyier\/pen\/019ad6ff-0e99-739c-9ddf-f1d3c311f288\">the complete demo<\/a> for this post.<\/figcaption>\n\t\t\t\n\t\t<\/figure>\n\t\t\n\n\n<p>The positioning of that menu happens via the magic of anchor positioning. Lemme show you all the HTML first, as that is interesting in it&#8217;s own right. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The HTML for the Menu Button &amp; Menu<\/h2>\n\n\n\n<p>We&#8217;ll use a <code>&lt;button&gt;<\/code> to toggle the menu (duh!) and put the attributes on it to set up an <strong><a href=\"https:\/\/frontendmasters.com\/blog\/menus-toasts-and-more\/\">invoker<\/a><\/strong>. Invokers are super cool, allowing us to open\/close the menu without any JavaScript at all. Just these declarative instructions will do. The <code>interestfor<\/code> attribute is extra-new, allowing <code><a href=\"https:\/\/frontendmasters.com\/blog\/what-is-popoverhint\/\">popover=\"hint\"<\/a><\/code> to work meaning we can even open the popover on hover\/focus (which is kinda amazing that it can be done in HTML alone). <\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>\n  <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"menu-toggle\"<\/span>\n\n  &lt;!<span class=\"hljs-attr\">--<\/span> <span class=\"hljs-attr\">interest<\/span> <span class=\"hljs-attr\">invoker<\/span>! <span class=\"hljs-attr\">--<\/span>&gt;<\/span>\n  command=\"toggle-popover\"\n  <span class=\"hljs-comment\">&lt;!-- connect to id of the popover menu --&gt;<\/span>\n  commandfor=\"card-menu\"\n  <span class=\"hljs-comment\">&lt;!-- for \"hint\" type (open menu on hover) --&gt;<\/span>\n  interestfor=\"card-menu\"\n\n  style=\"anchor-name: --card;\"\n&gt;\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"screenreader-only\"<\/span>&gt;<\/span>Open Menu<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">class<\/span>=<span class=\"hljs-string\">\"aria-hidden\"<\/span>&gt;<\/span>\u2022\u2022\u2022<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n\n<span class=\"hljs-comment\">&lt;!-- \n  These two things \u2b06\ufe0f\u2b07\ufe0f could be anywhere \n  in DOM, thanks to anchor positioning,\n  but it's still probably smart to keep \n  them nearby for tabbing accessibility.\n--&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">menu<\/span> \n  <span class=\"hljs-attr\">popover<\/span>=<span class=\"hljs-string\">\"hint\"<\/span> \n  <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"card-menu\"<\/span> \n  <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">\"position-anchor: --card;\"<\/span>\n&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>&gt;<\/span>This<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>&gt;<\/span>Little<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>&gt;<\/span>Piggy<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>&gt;<\/span>Went<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">li<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span>&gt;<\/span>to Market<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">li<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">menu<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Did you know <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTML\/Reference\/Elements\/menu\">the <code>&lt;menu&gt;<\/code> tag is just an <code>&lt;ul&gt;<\/code><\/a>? I love that. <\/p>\n\n\n\n<p>I put the <code>style<\/code> tag on both of those elements, naming an anchor and styling against that named anchor, because &#8220;in the real world&#8221; I think that will be extremely common. The rest of the CSS can happen in a CSS file, but those things will likely be in the HTML because a page is likely to have lots of context menus and they will all need &#8211;unique-names.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"642\" height=\"782\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-08-at-10.26.40-AM.png?resize=642%2C782&#038;ssl=1\" alt=\"\" class=\"wp-image-8223\" style=\"width:365px;height:auto\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-08-at-10.26.40-AM.png?w=642&amp;ssl=1 642w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-08-at-10.26.40-AM.png?resize=246%2C300&amp;ssl=1 246w\" sizes=\"auto, (max-width: 642px) 100vw, 642px\" \/><figcaption class=\"wp-element-caption\">The typical\/ideal situation.<\/figcaption><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\">The CSS for the Menu<\/h2>\n\n\n\n<p>The CSS for the <em>button<\/em> isn&#8217;t terribly interesting aside from the named anchor we already gave it, so we&#8217;ll skip over that (just make sure it has nice hover\/focus styles). <\/p>\n\n\n\n<p>The CSS for the menu is much more interesting because&#8230;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>We get to use anchor positioning to put it right where we want, including fallbacks.<\/li>\n\n\n\n<li>We can animate the opening and closing.<\/li>\n<\/ul>\n\n\n\n<p>The menu is going to be properly closed to start, with <code>display: none;<\/code>. Normally this means we can&#8217;t animate it, but with modern CSS these days, we can!<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">menu<\/span> {\n  <span class=\"hljs-comment\">\/* Already has this from the HTML *\/<\/span>\n  <span class=\"hljs-comment\">\/* position-anchor: --card; *\/<\/span>\n\n  <span class=\"hljs-comment\">\/* Put it in place *\/<\/span>\n  <span class=\"hljs-attribute\">position-area<\/span>: block-start span-inline-start;\n\n  <span class=\"hljs-attribute\">transition-property<\/span>: translate, opacity, display, overlay;\n  <span class=\"hljs-attribute\">transition-duration<\/span>: <span class=\"hljs-number\">0.45s<\/span>;\n  <span class=\"hljs-comment\">\/* Important for swapping timing of when the display properly flips *\/<\/span>\n  <span class=\"hljs-attribute\">transition-behavior<\/span>: allow-discrete;\n\n  <span class=\"hljs-comment\">\/* OUTGOING style *\/<\/span>\n  <span class=\"hljs-attribute\">opacity<\/span>: <span class=\"hljs-number\">0<\/span>;\n  <span class=\"hljs-attribute\">display<\/span>: none;\n  <span class=\"hljs-attribute\">translate<\/span>: <span class=\"hljs-number\">10px<\/span> <span class=\"hljs-number\">0<\/span>;\n\n  &amp;:popover-open {\n    <span class=\"hljs-comment\">\/* MENU OPEN style *\/<\/span>\n    <span class=\"hljs-attribute\">opacity<\/span>: <span class=\"hljs-number\">1<\/span>;\n    <span class=\"hljs-attribute\">display<\/span>: block;\n    <span class=\"hljs-attribute\">translate<\/span>: <span class=\"hljs-number\">0<\/span> <span class=\"hljs-number\">0<\/span>;\n\n    <span class=\"hljs-comment\">\/* INCOMING style *\/<\/span>\n    @starting-style {\n      <span class=\"hljs-attribute\">opacity<\/span>: <span class=\"hljs-number\">0<\/span>;\n      <span class=\"hljs-attribute\">translate<\/span>: <span class=\"hljs-number\">0<\/span> -<span class=\"hljs-number\">20px<\/span>;\n    }\n  }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>That <code>position-area<\/code> is decently complex all in itself. You might think there are basically <em>eight<\/em> places to put it (four sides and four corners) but there is really <em>sixteen<\/em> as the direction it &#8220;spans&#8221; can be sort of reversed from the natural flow. Ours does! <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"698\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-08-at-10.28.45-AM.png?resize=1024%2C698&#038;ssl=1\" alt=\"Diagram showcasing various anchor positioning options with labeled elements and a tooltip displaying the styled position properties.\" class=\"wp-image-8224\" style=\"aspect-ratio:1.467083951023994;width:578px;height:auto\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-08-at-10.28.45-AM.png?resize=1024%2C698&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-08-at-10.28.45-AM.png?resize=300%2C204&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-08-at-10.28.45-AM.png?resize=768%2C523&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-08-at-10.28.45-AM.png?resize=1536%2C1047&amp;ssl=1 1536w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-08-at-10.28.45-AM.png?w=1708&amp;ssl=1 1708w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><figcaption class=\"wp-element-caption\"><a href=\"https:\/\/chrome.dev\/anchor-tool\/\">https:\/\/chrome.dev\/anchor-tool\/<\/a><\/figcaption><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\">The Positioning Fallbacks<\/h2>\n\n\n\n<p>This is actually why I originally made this demo and why I&#8217;m writing this article. I found the anchor positioning fallbacks to be very mind-bending. Now that I have the right solution in place, it seems more obvious, but it&#8217;s been a mental journey for me getting here \ud83d\ude35\u200d\ud83d\udcab. <\/p>\n\n\n\n<p>Why fallbacks? If we didn&#8217;t have them, we&#8217;d risk opening our menus in into areas where they are unusable. Like if the menu button was toward the top of the screen, our initial <code>position-area<\/code> has the menu opening upwards, and we&#8217;d be hosed:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"902\" height=\"772\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-08-at-10.24.35-AM-1.png?resize=902%2C772&#038;ssl=1\" alt=\"A kebab menu button opened, displaying menu items including 'Went' and 'to Market', set against a colorful, blurred background.\" class=\"wp-image-8222\" style=\"aspect-ratio:1.168396906850805;width:432px;height:auto\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-08-at-10.24.35-AM-1.png?w=902&amp;ssl=1 902w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-08-at-10.24.35-AM-1.png?resize=300%2C257&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2026\/01\/Screenshot-2026-01-08-at-10.24.35-AM-1.png?resize=768%2C657&amp;ssl=1 768w\" sizes=\"auto, (max-width: 902px) 100vw, 902px\" \/><figcaption class=\"wp-element-caption\">The top edge here is the top of the browser window, and the menu options are cut off. We can&#8217;t read them or click them.<\/figcaption><\/figure>\n<\/div>\n\n\n<p>In this situation, what we <em>want<\/em> to happen is for the menu to open <em>downwards<\/em> instead. That&#8217;s pretty straightforward, we add:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">menu<\/span> {\n  ...\n\n  <span class=\"hljs-attribute\">position-try<\/span>: flip-block;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This is basically saying:<em> if you need to and there is space, go ahead and flip the position in the block direction.<\/em> So from top to bottom for us. So if we had that situation where it&#8217;s cutting off on top, it&#8217;ll flip to the bottom if it can. That works great:<\/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: 500px;\" >\n\t\t\t<div class=\"jetpack-videopress-player__wrapper\"> <iframe title=\"VideoPress Video Player\" aria-label='VideoPress Video Player' width='500' height='426' src='https:\/\/videopress.com\/embed\/TnVgGaAT?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=1739540970'><\/script><\/div>\n\t\t\t\n\t\t\t\n\t\t<\/figure>\n\t\t\n\n\n<p>But top and bottom aren&#8217;t the only places a menu like this could get cut off. The left and right edges of the browser window are just as plausible. So in my mind, we&#8217;d just do this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">position-try<\/span>: <span class=\"hljs-selector-tag\">flip-inline<\/span> <span class=\"hljs-selector-tag\">flip-block<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>My mind: OK you have everything you need now, if you need to flip in the block direction, you&#8217;ve been given permission, and if you need to flip in the inline direction, you&#8217;ve also been given permission:<\/p>\n\n\n\n<p>Spoiler: This is now how it works. <\/p>\n\n\n\n<p>What I&#8217;ve written above <em>actually<\/em> says: If you&#8217;re getting cut off with your initial positioning, try flipping in <em>both<\/em> the inline and block directions and if and only if that is better, do it. <\/p>\n\n\n\n<p>That&#8217;s not really what I want. <\/p>\n\n\n\n<p>What I want is: If the initial positioning is cut off, try flipping in the block direction, if that doesn&#8217;t work, try flipping in the inline direction, if that doesn&#8217;t work, then try flipping in both directions. What we need to that is this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">position-try<\/span>: <span class=\"hljs-selector-tag\">flip-block<\/span>, <span class=\"hljs-selector-tag\">flip-inline<\/span>, <span class=\"hljs-selector-tag\">flip-block<\/span> <span class=\"hljs-selector-tag\">flip-inline<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">The Most Useful <code>position-try<\/code> Incantation<\/h2>\n\n\n\n<p>I&#8217;m going to say this again, because I&#8217;ve always thought this is just how it should work naturally without even having to ask for it (but it doesn&#8217;t). If you want positioning fallbacks that attempt to flip <em>all the different directions<\/em> to best fit, do this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.good-positioning-fallbacks<\/span> {\n  <span class=\"hljs-attribute\">position-try<\/span>: flip-block, flip-inline, flip-block flip-inline;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Behold, a menu that works no matter where it shows up in a browser window:<\/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: 483px;\" >\n\t\t\t<div class=\"jetpack-videopress-player__wrapper\"> <iframe title=\"VideoPress Video Player\" aria-label='VideoPress Video Player' width='465' height='750' src='https:\/\/videopress.com\/embed\/tQPX1kyB?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=1739540970'><\/script><\/div>\n\t\t\t\n\t\t\t\n\t\t<\/figure>\n\t\t\n\n\n<h2 class=\"wp-block-heading\">We Could Write it Longhand<\/h2>\n\n\n\n<p>There is also a special <code>@position-try<\/code> syntax which we could use to do the exact same thing, like&#8230;<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">position-try-fallbacks<\/span>: \n  <span class=\"hljs-selector-tag\">--flip-block<\/span>, \n  <span class=\"hljs-selector-tag\">--flip-inline<\/span>, \n  <span class=\"hljs-selector-tag\">--flip-both<\/span>;\n\n<span class=\"hljs-keyword\">@position-try<\/span> --flip-block {\n  <span class=\"hljs-selector-tag\">position-area<\/span>: <span class=\"hljs-selector-tag\">block-end<\/span> <span class=\"hljs-selector-tag\">span-inline-start<\/span>;\n}\n\n<span class=\"hljs-keyword\">@position-try<\/span> --flip-inline {\n  <span class=\"hljs-selector-tag\">position-area<\/span>: <span class=\"hljs-selector-tag\">block-start<\/span> <span class=\"hljs-selector-tag\">span-inline-end<\/span>;\n}\n\n<span class=\"hljs-keyword\">@position-try<\/span> --flip-both {\n  <span class=\"hljs-selector-tag\">position-area<\/span>: <span class=\"hljs-selector-tag\">block-end<\/span> <span class=\"hljs-selector-tag\">span-inline-end<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The advantage to doing it this way is those @rule blocks allow us to do more stuff when they &#8220;hit&#8221;, for example adjust the <code>margin<\/code> differently or change alignment. That&#8217;s certainly nice if you need it!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Demo<\/h2>\n\n\n\n<p>Here&#8217;s the demo page. Feel free to see <a href=\"https:\/\/witty-bonus-lemur.codepen.app\/\">a full page preview<\/a>. <\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_019ad6ff-0e99-739c-9ddf-f1d3c311f288\" src=\"\/\/codepen.io\/editor\/anon\/embed\/019ad6ff-0e99-739c-9ddf-f1d3c311f288?height=450&amp;theme-id=1&amp;slug-hash=019ad6ff-0e99-739c-9ddf-f1d3c311f288&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed 019ad6ff-0e99-739c-9ddf-f1d3c311f288\" title=\"CodePen Embed 019ad6ff-0e99-739c-9ddf-f1d3c311f288\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n","protected":false},"excerpt":{"rendered":"<p>A context menu is like a tooltip in that it opens right next to the the thing that opened it. Here, we animate the opening and ensure it opens somewhere where it doesn&#8217;t get cut off.<\/p>\n","protected":false},"author":1,"featured_media":8230,"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,397],"class_list":["post-8194","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-anchor","tag-css","tag-menu"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2026\/01\/menus-positioned.jpg?fit=2000%2C1200&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/8194","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=8194"}],"version-history":[{"count":13,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/8194\/revisions"}],"predecessor-version":[{"id":8234,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/8194\/revisions\/8234"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/8230"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=8194"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=8194"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=8194"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}