Chrome only: absolutely positioned floating label shifts/overflows differently when clicking label text vs input

3 days ago 9
ARTICLE AD BOX

I’m building a floating label input using Tailwind/React. The floating label is an absolutely positioned <span> inside a <label>, and it uses :has(+ input:is(:focus,:not(:placeholder-shown))) to apply a "floating" style when the adjacent <input> is focused or not placeholder‑shown.

Here is a minimal reproducible example (no JS, no Tailwind):

<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Floating Label :has() Repro</title> <style> .container { position: relative; width: 260px; height: 48px; border: 1px solid #999; border-radius: 4px; overflow: hidden; font-family: system-ui, sans-serif; margin: 40px; } .field-label { /* I've also tried: display: block; width: 100%; height: 100%; */ } .floating-label { position: absolute; padding: 12px; cursor: text; font-size: 16px; line-height: 1; user-select: none; transition: all 0.15s ease-out; background: rgba(255, 255, 0, 0.1); /* visualize box */ /* I've also tried explicit anchors like: top: 12px; inset-inline-start: 12px; and then top: 4px; on the floating state – same issue. */ } .floating-label:has(+ input:is(:focus, :not(:placeholder-shown))) { font-size: 12px; opacity: 0.65; padding: 4px 12px; background: rgba(0, 255, 0, 0.1); /* visualize floating state box */ } .field-input { width: 100%; box-sizing: border-box; margin: 16px 12px 4px; border: none; outline: none; font-size: 16px; background: transparent; } </style> </head> <body> <div class="container"> <label class="field-label"> <span class="floating-label">Name</span> <input class="field-input" placeholder=" " /> </label> </div> <p>Try this in Chrome and Firefox:</p> <ol> <li>Reload the page.</li> <li>Click directly on the <strong>input</strong> field: the label floats.</li> <li>Reload again.</li> <li>Click directly on the text <strong>"Name"</strong>: the label floats.</li> </ol> </body> </html>

What I’m seeing:

In Firefox:
The behavior is stable and looks "correct" regardless of where I click (label text vs input).
The green floating label box overflows the container slightly on the right side (about 24px), which makes sense given the padding and margins.

In Chrome:
When I click the input directly, the behavior matches Firefox: overflow only on the right side (~24px).
When I click the label text (<span class="floating-label">), the floating label still gets the :has(...): style (confirmed in devtools), and the computed padding is correct:

padding-top/bottom: 4px padding-left/right: 12px

However, visually the box appears shifted: it now overflows about 12px on the left (visible in devtools).
The parent container’s position, padding, border, margin, etc. do not change at all — the only difference is which element I click to focus the input.

So the CSS is:

Definitely applying :has(+ input:is(:focus,:not(:placeholder-shown))). Definitely applying the expected padding in both states (checked in devtools). Yet Chrome computes a different horizontal placement/overflow of the absolutely positioned span depending on whether focus comes from clicking the input or via the label activation mechanism.

I’ve also tried:

Adding explicit anchors: top: 12px; inset-inline-start: 12px; And then top: 4px; in the floating state. Changing the <label> to display: block; position: relative; width: 100%; height: 100%; to make it a clear positioning container.

But in Chrome, I still see that when I click the label text directly, the floating label’s box shifts differently (overflow left) compared to clicking the input (overflow only right), while Firefox remains consistent in both cases.

My questions:

Is this a known Chrome quirk/bug involving :has(+ input:is(...)), label activation, and absolutely positioned descendants? Is there a spec‑based explanation for why the static position or shrink‑to‑fit width of the absolute span could be computed differently when focus is triggered by clicking the label text vs the input itself? Is there a pure‑CSS way to make this robust and consistent across browsers (i.e., avoid this difference between label‑click and input‑click), without resorting to JS?

Any insight into what Chrome is doing here, or how to structure this floating label layout to avoid this behavior, would be appreciated.


While writing I noticed that removing overflow: hidden on the container kinda solves the issue. Since Safari and Firefox still work correctly, I feel like this is still just a bug in Chrome, but I'm not sure.

Read Entire Article