WebCraft

:placeholder-shown

A label that floats out of the way

CaveatThe trick needs a real placeholder attribute — even a single space — because the selector matches the placeholder being shown, not the value being empty. Drop the attribute and the label never moves.

FallbackThe label has to come after the input in the markup for the sibling selector to reach it. Order it visually with CSS, never by moving it back in the DOM.

HTML + CSS
<input placeholder=" "><label>Project</label>

/* label follows input, so + can reach it */
input:not(:placeholder-shown) + label,
input:focus + label { translate: 0 -8px; }

Published

Questions

<details name>

Why does my floating label never move?

Almost always a missing placeholder attribute. The selector matches the placeholder being shown, not the value being empty, so without one — even a single space — there is no state to react to.

Why does the sibling selector not reach my label?

The label has to come after the input in the markup for + to find it. Order it visually with CSS; moving it back before the input in the DOM to "fix" the layout is what breaks the selector.

Is a placeholder enough on its own, without a label?

No. A placeholder disappears the moment someone types, takes the field's accessible name with it if there is no label, and gives screen readers nothing to announce. The floating label exists precisely so the field keeps a real one.