CSS pseudo-classPseudo-classes

:placeholder-shown

Matches an input or textarea field that is currently showing its placeholder text, meaning it’s empty and has a placeholder attribute.

On this page

Example

#
CSS
.float {
  position: relative;
}

.float label {
  position: absolute;
  left: 12px;
  top: 50%;
  translate: 0 -50%;
  color: #a1a1aa;
  pointer-events: none;
  transition: all 0.15s;
}

.float input:focus + label,
.float input:not(:placeholder-shown) + label {
  top: 0;
  padding: 0 4px;
  background: #0c0c10;
  color: #c4b5fd;
  font-size: 12px;
}
Preview

The field has placeholder=" ", a single space, since the pseudo-class won’t work without the attribute. Click the field and type something: the label slides up onto the border and stays there as long as the field isn’t empty.

Definition and usage

#

The :placeholder-shown pseudo-class matches a text field as long as its placeholder attribute hint is visible. Once the user types a single character, the hint disappears and the field stops matching. A field with no placeholder attribute never matches it.

It’s an indirect way to check whether a field is empty, since CSS has no "field with a value" selector. That’s why the combination :not(:placeholder-shown), meaning "the user has typed something," is so popular. Floating labels and showing validation errors only after text is entered are both built on it.

Don’t confuse it with the ::placeholder pseudo-element. The pseudo-class lets you style the whole field in its empty state (the border, the background, a label next to it), while the pseudo-element only styles the hint text itself.

Syntax

#
Syntax
selector:placeholder-shown { property: value; }

Common uses

#
  • input:placeholder-shown

    An empty field with a visible hint gets a dashed border. Type something, and the border becomes solid.
  • input:not(:placeholder-shown)

    A field that has something typed into it. The second field matches right away, since it already has a value.

Common uses in practice

#

input:placeholder-shown

An empty field with a visible hint gets a dashed border. Type something, and the border becomes solid.
input:placeholder-shown {
  border-style: dashed;
  border-color: #71717a;
}

input:not(:placeholder-shown)

A field that has something typed into it. The second field matches right away, since it already has a value.
input:not(:placeholder-shown) { border-color: #10b981; }

Browser support

#

Widely available

Works in all modern browsers, phones included. You can use it without worry.

  • Chrome
  • Edge
  • Firefox
  • Safari

Good practices

#
  • If you don’t want a visible hint but still need this pseudo-class, set placeholder=" ". The field will look empty, and the selector will still work.
  • A placeholder doesn’t replace a label: it disappears while typing and often has weak contrast. A floating label is a good compromise, since it always stays visible.

Related entries

#

Spotted a mistake or missing an example? Write to us.