Pure TailwindMIT licensed

Tailwind Dropdown Matching Anchor Width

A panel exactly as wide as the control that opened it reads as part of that control. supports-[anchor-name:--a]:w-[anchor-size(width)] sizes the panel from its anchor live, with no offsetWidth — and because the variant is emitted after the base w-[min(23rem,…)], the fallback width is declared first for free. Resize the frame and the seam never opens.

Live Demo
Plain CSSTailwind v4
Try it

Untitled UI Pro: 5,000+ React + Tailwind CSS v4 components · from $349 one-time

Untitled UI React · Affiliate link

Get Untitled UI Pro

The code

<section class="tpop-09 transition-[--tpop09-d] duration-300 ease-in-out motion-reduce:transition-none dark:[--tpop09-d:1] [[data-theme=dark]_&]:[--tpop09-d:1] [[data-theme=light]_&]:[--tpop09-d:0] group/root w-full min-h-svh bg-tpop09-bg px-4.5 py-10 font-tpop09-sans text-tpop09-ink" aria-label="Dropdown matching anchor width demo">
  <div class="grid min-h-[calc(100svh-80px)] max-w-full place-items-center">
    <form class="w-full min-w-0 max-w-[25rem] rounded-xl border border-tpop09-rule bg-tpop09-surface px-4.5 pt-5 pb-4.5 shadow-[0_16px_36px_-28px_oklch(0.25_0.05_255/0.5)]" aria-label="Deployment target">
      <p class="mb-4 text-[10.5px] font-bold uppercase tracking-[0.2em] text-tpop09-brand">Deploy target</p>
      <label for="tpop-09-trigger" class="mb-1.5 block text-[12.5px] font-semibold text-tpop09-mut">Environment</label>
      <button id="tpop-09-trigger" type="button" popovertarget="tpop-09-list" class="flex min-h-11 w-full cursor-pointer items-center justify-between gap-2.5 rounded-lg border border-tpop09-rule bg-tpop09-surface px-3 text-left text-[14px] font-medium text-tpop09-ink transition-[border-color,border-radius,box-shadow] duration-150 [anchor-name:--tpop09-a] hover:border-tpop09-brand focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpop09-brand group-has-[#tpop-09-list:popover-open]/root:border-tpop09-brand group-has-[#tpop-09-list:popover-open]/root:shadow-[0_0_0_3px_oklch(0.5_0.15_255/0.14)] supports-[anchor-name:--a]:group-has-[#tpop-09-list:popover-open]/root:rounded-b-none">
        <span class="flex min-w-0 items-center gap-2"><span aria-hidden="true" class="size-2 flex-none rounded-full bg-tpop09-ok"></span><span class="truncate">Production · eu-west-1</span></span>
        <svg class="flex-none text-tpop09-mut transition-transform duration-200 motion-reduce:transition-none group-has-[#tpop-09-list:popover-open]/root:rotate-180" viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.9" aria-hidden="true"><path d="M4 6.5 8 10.5 12 6.5"/></svg>
      </button>
      <p class="mt-2 mb-3.5 text-[12.5px] text-tpop09-mut">The list below takes its width from this button, live. Resize the frame.</p>
      <div class="flex flex-wrap gap-1.5">
        <span class="rounded-md bg-tpop09-brand/10 px-2 py-1.5 font-tpop09-mono text-[11px] font-semibold leading-tight text-tpop09-brand">w-[anchor-size(width)]</span>
        <span class="rounded-md bg-tpop09-bg px-2 py-1.5 font-tpop09-mono text-[11px] font-semibold leading-tight text-tpop09-mut">min-w variant in notes</span>
      </div>
    </form>
  </div>

  <div popover="auto" id="tpop-09-list" role="group" aria-label="Environments" class="fixed m-auto w-[min(23rem,calc(100vw-32px))] rounded-lg border border-tpop09-brand bg-tpop09-surface p-1.5 text-tpop09-ink opacity-0 shadow-[0_18px_36px_-20px_oklch(0.25_0.05_255/0.55)] transition-[opacity,translate,display,overlay] duration-150 ease-out transition-discrete [position-anchor:--tpop09-a] [position-area:block-end_span-inline-end] open:opacity-100 starting:open:-translate-y-1 starting:open:opacity-0 motion-reduce:transition-none supports-[anchor-name:--a]:inset-auto supports-[anchor-name:--a]:m-0 supports-[anchor-name:--a]:w-[anchor-size(width)] supports-[anchor-name:--a]:rounded-t-none supports-[anchor-name:--a]:border-t-0">
    <p class="flex min-w-0 items-center gap-2.5 rounded-md bg-tpop09-brand/9 px-2.5 py-2.5 text-[13.5px] font-semibold text-tpop09-brand"><span aria-hidden="true" class="size-2 flex-none rounded-full bg-tpop09-ok"></span><span class="min-w-0 flex-auto truncate">Production · eu-west-1</span><svg class="flex-none" viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" aria-label="current"><path d="M3 8.5l3.2 3.2L13 4.8"/></svg></p>
    <p class="flex min-w-0 items-center gap-2.5 rounded-md px-2.5 py-2.5 text-[13.5px]"><span aria-hidden="true" class="size-2 flex-none rounded-full bg-tpop09-ok"></span><span class="min-w-0 flex-auto truncate">Staging · eu-west-1</span></p>
    <p class="flex min-w-0 items-center gap-2.5 rounded-md px-2.5 py-2.5 text-[13.5px]"><span aria-hidden="true" class="size-2 flex-none rounded-full bg-tpop09-warn"></span><span class="min-w-0 flex-auto truncate">Preview · ephemeral per branch</span><span class="flex-none text-[11px] text-tpop09-mut">degraded</span></p>
    <p class="flex min-w-0 items-center gap-2.5 rounded-md px-2.5 py-2.5 text-[13.5px]"><span aria-hidden="true" class="size-2 flex-none rounded-full bg-tpop09-rule"></span><span class="min-w-0 flex-auto truncate">Local · docker compose</span><span class="flex-none text-[11px] text-tpop09-mut">offline</span></p>
  </div>
</section>
@import "tailwindcss";

@theme {
  --color-tpop09-bg: #f2f5f9;
  --color-tpop09-bg: oklch(0.97 0.006 250);
  --color-tpop09-surface: #ffffff;
  --color-tpop09-surface: oklch(1 0 0);
  --color-tpop09-ink: #111b2b;
  --color-tpop09-ink: oklch(0.22 0.035 260);
  --color-tpop09-mut: #515e75;
  --color-tpop09-mut: oklch(0.48 0.04 260);
  --color-tpop09-rule: #ccd5e2;
  --color-tpop09-rule: oklch(0.87 0.02 255);
  --color-tpop09-brand: #1558ad;
  --color-tpop09-brand: oklch(0.47 0.15 257);
  --color-tpop09-ok: #29ac68;
  --color-tpop09-ok: oklch(0.66 0.15 155);
  --color-tpop09-warn: #e8a127;
  --color-tpop09-warn: oklch(0.76 0.15 75);
  --font-tpop09-sans: 'Geist', system-ui, sans-serif;
  --font-tpop09-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Theme dial: 0 = light, 1 = dark. Registered so the root can transition it. */

@property --tpop09-d {
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
   stage is sized before the browser build compiles — plus the dark palette. Each @theme colour is
   re-declared on the root as a light/dark mix of the dial, so every utility (and every open
   popover, which inherits from the root) follows it. Light value last, dark value first. */

.tpop-09 {
  width: 100%;
  min-height: 100svh;
  --color-tpop09-bg: color-mix(in oklch, oklch(0.16 0.018 258) calc(var(--tpop09-d) * 100%), oklch(0.97 0.006 250));
  --color-tpop09-surface: color-mix(in oklch, oklch(0.21 0.022 258) calc(var(--tpop09-d) * 100%), oklch(1 0 0));
  --color-tpop09-ink: color-mix(in oklch, oklch(0.95 0.01 255) calc(var(--tpop09-d) * 100%), oklch(0.22 0.035 260));
  --color-tpop09-mut: color-mix(in oklch, oklch(0.73 0.03 258) calc(var(--tpop09-d) * 100%), oklch(0.48 0.04 260));
  --color-tpop09-rule: color-mix(in oklch, oklch(0.32 0.03 258) calc(var(--tpop09-d) * 100%), oklch(0.87 0.02 255));
  --color-tpop09-brand: color-mix(in oklch, oklch(0.72 0.13 257) calc(var(--tpop09-d) * 100%), oklch(0.47 0.15 257));
  --color-tpop09-ok: color-mix(in oklch, oklch(0.74 0.15 155) calc(var(--tpop09-d) * 100%), oklch(0.66 0.15 155));
  --color-tpop09-warn: color-mix(in oklch, oklch(0.8 0.14 75) calc(var(--tpop09-d) * 100%), oklch(0.76 0.15 75));
}

Setup — do this once per project

Skip this if your project already runs Tailwind v4.

1Load Tailwind
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>

Compiles in the browser — perfect for a CodePen or a quick test, not for production.

2Add the stylesheetRequiredthe @theme block is what makes the custom utilities exist
@import "tailwindcss";

@theme {
  --color-tpop09-bg: #f2f5f9;
  --color-tpop09-bg: oklch(0.97 0.006 250);
  --color-tpop09-surface: #ffffff;
  --color-tpop09-surface: oklch(1 0 0);
  --color-tpop09-ink: #111b2b;
  --color-tpop09-ink: oklch(0.22 0.035 260);
  --color-tpop09-mut: #515e75;
  --color-tpop09-mut: oklch(0.48 0.04 260);
  --color-tpop09-rule: #ccd5e2;
  --color-tpop09-rule: oklch(0.87 0.02 255);
  --color-tpop09-brand: #1558ad;
  --color-tpop09-brand: oklch(0.47 0.15 257);
  --color-tpop09-ok: #29ac68;
  --color-tpop09-ok: oklch(0.66 0.15 155);
  --color-tpop09-warn: #e8a127;
  --color-tpop09-warn: oklch(0.76 0.15 75);
  --font-tpop09-sans: 'Geist', system-ui, sans-serif;
  --font-tpop09-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Theme dial: 0 = light, 1 = dark. Registered so the root can transition it. */

@property --tpop09-d {
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
   stage is sized before the browser build compiles — plus the dark palette. Each @theme colour is
   re-declared on the root as a light/dark mix of the dial, so every utility (and every open
   popover, which inherits from the root) follows it. Light value last, dark value first. */

.tpop-09 {
  width: 100%;
  min-height: 100svh;
  --color-tpop09-bg: color-mix(in oklch, oklch(0.16 0.018 258) calc(var(--tpop09-d) * 100%), oklch(0.97 0.006 250));
  --color-tpop09-surface: color-mix(in oklch, oklch(0.21 0.022 258) calc(var(--tpop09-d) * 100%), oklch(1 0 0));
  --color-tpop09-ink: color-mix(in oklch, oklch(0.95 0.01 255) calc(var(--tpop09-d) * 100%), oklch(0.22 0.035 260));
  --color-tpop09-mut: color-mix(in oklch, oklch(0.73 0.03 258) calc(var(--tpop09-d) * 100%), oklch(0.48 0.04 260));
  --color-tpop09-rule: color-mix(in oklch, oklch(0.32 0.03 258) calc(var(--tpop09-d) * 100%), oklch(0.87 0.02 255));
  --color-tpop09-brand: color-mix(in oklch, oklch(0.72 0.13 257) calc(var(--tpop09-d) * 100%), oklch(0.47 0.15 257));
  --color-tpop09-ok: color-mix(in oklch, oklch(0.74 0.15 155) calc(var(--tpop09-d) * 100%), oklch(0.66 0.15 155));
  --color-tpop09-warn: color-mix(in oklch, oklch(0.8 0.14 75) calc(var(--tpop09-d) * 100%), oklch(0.76 0.15 75));
}
3Fonts used by this demooptional — skip if you have your own type stack
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Geist:wght@400..800&family=Geist+Mono:wght@400..600&display=swap">

What changed in the port

Which parts became utilities, which stayed CSS, and why.

  • The fixed-width rule and its @supports override became two width utilities on one element — base w-[min(…)], then supports-[anchor-name:--a]:w-[anchor-size(width)] — and Tailwind's emit order guarantees the fallback comes first.
  • .pop-09__opt + .pop-09__opt and overflow/text-overflow/white-space became truncate on the label span.
  • UI upgrade from the CSS original: field and list fuse into one shape while open — the field loses its bottom radius, the list its top border and radius — gated so the seam only closes where anchoring actually tethers them.
  • UI upgrade: a focus-style halo and rotating chevron on the open field, environment health dots paired with text labels (degraded, offline), a checkmark on the current option, and the list now drops in from the field.
  • UI upgrade — dark mode: the stage now follows prefers-color-scheme (and a data-theme override on any ancestor) through one registered dial, --tpop09-d. The root rule re-declares each @theme colour as color-mix(dark calc(var(--tpop09-d)*100%), light), the root sets the dial with dark:[--tpop09-d:1], and transition-[--tpop09-d] crossfades page and open popovers together — the markup's colour utilities are unchanged.
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS demo from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Tailwind Dropdown Matching Anchor Width
Source: https://codefronts.com/snippets/tailwind-css-popovers/tailwind-dropdown-matching-anchor-width/

A panel exactly as wide as the control that opened it reads as part of that control. supports-[anchor-name:--a]:w-[anchor-size(width)] sizes the panel from its anchor live, with no offsetWidth — and because the variant is emitted after the base w-[min(23rem,…)], the fallback width is declared first for free. Resize the frame and the seam never opens.
## HTML
```html
<section class="tpop-09 transition-[--tpop09-d] duration-300 ease-in-out motion-reduce:transition-none dark:[--tpop09-d:1] [[data-theme=dark]_&]:[--tpop09-d:1] [[data-theme=light]_&]:[--tpop09-d:0] group/root w-full min-h-svh bg-tpop09-bg px-4.5 py-10 font-tpop09-sans text-tpop09-ink" aria-label="Dropdown matching anchor width demo">
  <div class="grid min-h-[calc(100svh-80px)] max-w-full place-items-center">
    <form class="w-full min-w-0 max-w-[25rem] rounded-xl border border-tpop09-rule bg-tpop09-surface px-4.5 pt-5 pb-4.5 shadow-[0_16px_36px_-28px_oklch(0.25_0.05_255/0.5)]" aria-label="Deployment target">
      <p class="mb-4 text-[10.5px] font-bold uppercase tracking-[0.2em] text-tpop09-brand">Deploy target</p>
      <label for="tpop-09-trigger" class="mb-1.5 block text-[12.5px] font-semibold text-tpop09-mut">Environment</label>
      <button id="tpop-09-trigger" type="button" popovertarget="tpop-09-list" class="flex min-h-11 w-full cursor-pointer items-center justify-between gap-2.5 rounded-lg border border-tpop09-rule bg-tpop09-surface px-3 text-left text-[14px] font-medium text-tpop09-ink transition-[border-color,border-radius,box-shadow] duration-150 [anchor-name:--tpop09-a] hover:border-tpop09-brand focus-visible:outline-3 focus-visible:outline-offset-2 focus-visible:outline-tpop09-brand group-has-[#tpop-09-list:popover-open]/root:border-tpop09-brand group-has-[#tpop-09-list:popover-open]/root:shadow-[0_0_0_3px_oklch(0.5_0.15_255/0.14)] supports-[anchor-name:--a]:group-has-[#tpop-09-list:popover-open]/root:rounded-b-none">
        <span class="flex min-w-0 items-center gap-2"><span aria-hidden="true" class="size-2 flex-none rounded-full bg-tpop09-ok"></span><span class="truncate">Production · eu-west-1</span></span>
        <svg class="flex-none text-tpop09-mut transition-transform duration-200 motion-reduce:transition-none group-has-[#tpop-09-list:popover-open]/root:rotate-180" viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.9" aria-hidden="true"><path d="M4 6.5 8 10.5 12 6.5"/></svg>
      </button>
      <p class="mt-2 mb-3.5 text-[12.5px] text-tpop09-mut">The list below takes its width from this button, live. Resize the frame.</p>
      <div class="flex flex-wrap gap-1.5">
        <span class="rounded-md bg-tpop09-brand/10 px-2 py-1.5 font-tpop09-mono text-[11px] font-semibold leading-tight text-tpop09-brand">w-[anchor-size(width)]</span>
        <span class="rounded-md bg-tpop09-bg px-2 py-1.5 font-tpop09-mono text-[11px] font-semibold leading-tight text-tpop09-mut">min-w variant in notes</span>
      </div>
    </form>
  </div>

  <div popover="auto" id="tpop-09-list" role="group" aria-label="Environments" class="fixed m-auto w-[min(23rem,calc(100vw-32px))] rounded-lg border border-tpop09-brand bg-tpop09-surface p-1.5 text-tpop09-ink opacity-0 shadow-[0_18px_36px_-20px_oklch(0.25_0.05_255/0.55)] transition-[opacity,translate,display,overlay] duration-150 ease-out transition-discrete [position-anchor:--tpop09-a] [position-area:block-end_span-inline-end] open:opacity-100 starting:open:-translate-y-1 starting:open:opacity-0 motion-reduce:transition-none supports-[anchor-name:--a]:inset-auto supports-[anchor-name:--a]:m-0 supports-[anchor-name:--a]:w-[anchor-size(width)] supports-[anchor-name:--a]:rounded-t-none supports-[anchor-name:--a]:border-t-0">
    <p class="flex min-w-0 items-center gap-2.5 rounded-md bg-tpop09-brand/9 px-2.5 py-2.5 text-[13.5px] font-semibold text-tpop09-brand"><span aria-hidden="true" class="size-2 flex-none rounded-full bg-tpop09-ok"></span><span class="min-w-0 flex-auto truncate">Production · eu-west-1</span><svg class="flex-none" viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2" aria-label="current"><path d="M3 8.5l3.2 3.2L13 4.8"/></svg></p>
    <p class="flex min-w-0 items-center gap-2.5 rounded-md px-2.5 py-2.5 text-[13.5px]"><span aria-hidden="true" class="size-2 flex-none rounded-full bg-tpop09-ok"></span><span class="min-w-0 flex-auto truncate">Staging · eu-west-1</span></p>
    <p class="flex min-w-0 items-center gap-2.5 rounded-md px-2.5 py-2.5 text-[13.5px]"><span aria-hidden="true" class="size-2 flex-none rounded-full bg-tpop09-warn"></span><span class="min-w-0 flex-auto truncate">Preview · ephemeral per branch</span><span class="flex-none text-[11px] text-tpop09-mut">degraded</span></p>
    <p class="flex min-w-0 items-center gap-2.5 rounded-md px-2.5 py-2.5 text-[13.5px]"><span aria-hidden="true" class="size-2 flex-none rounded-full bg-tpop09-rule"></span><span class="min-w-0 flex-auto truncate">Local · docker compose</span><span class="flex-none text-[11px] text-tpop09-mut">offline</span></p>
  </div>
</section>
```
## CSS
```css
@import "tailwindcss";

@theme {
  --color-tpop09-bg: #f2f5f9;
  --color-tpop09-bg: oklch(0.97 0.006 250);
  --color-tpop09-surface: #ffffff;
  --color-tpop09-surface: oklch(1 0 0);
  --color-tpop09-ink: #111b2b;
  --color-tpop09-ink: oklch(0.22 0.035 260);
  --color-tpop09-mut: #515e75;
  --color-tpop09-mut: oklch(0.48 0.04 260);
  --color-tpop09-rule: #ccd5e2;
  --color-tpop09-rule: oklch(0.87 0.02 255);
  --color-tpop09-brand: #1558ad;
  --color-tpop09-brand: oklch(0.47 0.15 257);
  --color-tpop09-ok: #29ac68;
  --color-tpop09-ok: oklch(0.66 0.15 155);
  --color-tpop09-warn: #e8a127;
  --color-tpop09-warn: oklch(0.76 0.15 75);
  --font-tpop09-sans: 'Geist', system-ui, sans-serif;
  --font-tpop09-mono: 'Geist Mono', ui-monospace, monospace;
}
/* Theme dial: 0 = light, 1 = dark. Registered so the root can transition it. */

@property --tpop09-d {
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}
/* Root rule: the full-bleed contract, stated in CSS as well as in the markup's utilities, so the
   stage is sized before the browser build compiles — plus the dark palette. Each @theme colour is
   re-declared on the root as a light/dark mix of the dial, so every utility (and every open
   popover, which inherits from the root) follows it. Light value last, dark value first. */

.tpop-09 {
  width: 100%;
  min-height: 100svh;
  --color-tpop09-bg: color-mix(in oklch, oklch(0.16 0.018 258) calc(var(--tpop09-d) * 100%), oklch(0.97 0.006 250));
  --color-tpop09-surface: color-mix(in oklch, oklch(0.21 0.022 258) calc(var(--tpop09-d) * 100%), oklch(1 0 0));
  --color-tpop09-ink: color-mix(in oklch, oklch(0.95 0.01 255) calc(var(--tpop09-d) * 100%), oklch(0.22 0.035 260));
  --color-tpop09-mut: color-mix(in oklch, oklch(0.73 0.03 258) calc(var(--tpop09-d) * 100%), oklch(0.48 0.04 260));
  --color-tpop09-rule: color-mix(in oklch, oklch(0.32 0.03 258) calc(var(--tpop09-d) * 100%), oklch(0.87 0.02 255));
  --color-tpop09-brand: color-mix(in oklch, oklch(0.72 0.13 257) calc(var(--tpop09-d) * 100%), oklch(0.47 0.15 257));
  --color-tpop09-ok: color-mix(in oklch, oklch(0.74 0.15 155) calc(var(--tpop09-d) * 100%), oklch(0.66 0.15 155));
  --color-tpop09-warn: color-mix(in oklch, oklch(0.8 0.14 75) calc(var(--tpop09-d) * 100%), oklch(0.76 0.15 75));
}
```

How this works

anchor-size() turns the anchor's box into a length.

<button class="w-full [anchor-name:--tpop09-a]" popovertarget="tpop-09-list">
<div popover id="tpop-09-list" class="fixed m-auto
  w-[min(23rem,calc(100vw-32px))]
  supports-[anchor-name:--a]:w-[anchor-size(width)]
  [position-anchor:--tpop09-a]
  [position-area:block-end_span-inline-end]">

Order is the fallback. The CSS version had to declare the fixed width before the gated one by hand. In Tailwind, variant utilities are always emitted after base utilities, so the unanchored width is the floor and anchor-size(width) overrides it wherever it's supported.

Fusing the seam. While the list is open the field drops its bottom radius and the list drops its top radius and top border (rounded-t-none border-t-0) — the two boxes become one shape, the detail that separates a dropdown from a floating box.

Name the right element. anchor-size() reads whatever position-anchor names; put anchor-name on the button, not its chevron.

Make it yours

  • Grow-only: use supports-[anchor-name:--a]:min-w-[anchor-size(width)] and w-max so long labels widen the panel.
  • Overhang: supports-[anchor-name:--a]:w-[calc(anchor-size(width)+1.5rem)] with [justify-self:anchor-center].
  • Open upward: [position-area:block-start_span-inline-end] and swap the fused radii to the other edge.

Gotchas — read before shipping

  • Naming the chevron instead of the button gives you the chevron's width.
  • An exact width truncates long labels — keep truncate on options, or use the min-width variant.
  • A trigger that changes width on hover resizes the open panel mid-interaction; keep its box stable.

Browser support

ChromeSafariFirefoxEdge
125+26+131+125+

anchor-size() shares anchor positioning's floor. A popover-only engine opens the list centred at 23rem, and the fused-seam styling stays harmless.

Techniques used in this demo

Utilitiesfirst-class utility or variant

Search CodeFronts

Loading…