Question

Change HTML Input Placeholder Color with CSS

csshtmlplaceholderhtml-input

Question

How can you change the color of placeholder text in an HTML text input using CSS?

The following selector changes the color of the <input> element, but it does not change the placeholder text, which remains gray:

input[placeholder],
[placeholder],
*[placeholder] {
  color: red !important;
}
<input type="text" placeholder="Value">

Is there a CSS selector or pseudo-element that styles the placeholder text itself?

Short Answer

You will learn why attribute selectors do not target placeholder text and how to style it with the CSS ::placeholder pseudo-element. You will also see browser-compatible patterns, accessibility guidance, and practical form examples.

Concept

A placeholder is text displayed by the browser inside an empty form control to suggest an expected value. It is not a normal text node in your HTML document, so selectors such as [placeholder] cannot select the visible placeholder text itself.

This selector:

input[placeholder] {
  color: red;
}

selects an <input> element that has a placeholder attribute. The color property therefore applies to text the user types into the input, not necessarily to the browser-rendered placeholder.

To target the placeholder's generated text, use the ::placeholder pseudo-element:

input::placeholder {
  color: red;
}

This distinction matters because CSS has different tools for different targets:

  • Attribute selector: selects an actual element based on an attribute, such as input[placeholder].
  • Pseudo-element: styles a browser-created part of an element, such as input::placeholder.
  • Pseudo-class: matches an element in a state, such as input:focus or input:placeholder-shown.

In modern browsers, ::placeholder is the standard way to style placeholder text.

Mental Model

Think of an <input> as a labeled container.

  • The placeholder attribute is an instruction attached to the container: “When empty, show this hint.”
  • The visible hint is a temporary piece of browser-generated content inside the container.

Selecting input[placeholder] is like selecting every container that has the instruction attached. It does not select the temporary hint. To style that hint, use the special ::placeholder handle provided by CSS.

Take Quiz

Syntax and Examples

Use ::placeholder after the form-control selector.

selector::placeholder {
  color: value;
  opacity: value;
}

Basic example

<label for="email">Email address</label>
<input id="email" type="email" placeholder="you@example.com">
input::placeholder {
  color: red;
}

The placeholder you@example.com appears red while the field is empty. Once the user enters text, the input's normal color applies to the entered value.

Style entered text and placeholder text separately

input {
  color: #1f2937;
  border: 1px solid #94a3b8;
}

input::placeholder {
  color: #64748b;
  opacity: 1;
}

opacity: 1 is often included because some browsers apply reduced placeholder opacity by default. Setting it explicitly makes the selected color appear as intended.

Target only one field

<input class="search-box" type="search" placeholder="Search products">
.search-box::placeholder {
  color: #2563eb;
  font-style: italic;
}

The class keeps the rule limited to the search field instead of changing every input on the page.

Step by Step Execution

Consider this form:

<input class="username" type="text" placeholder="Enter your username">
.username {
  color: #111827;
}

.username::placeholder {
  color: #9ca3af;
  opacity: 1;
}

Here is what happens:

  1. The browser creates the <input> element.
  2. Because the field is empty, the browser displays Enter your username as placeholder text.
  3. .username matches the input element and sets the color for normal input text to #111827.
  4. .username::placeholder matches the placeholder portion generated inside that input.
  5. The placeholder receives #9ca3af and is displayed in that color.
  6. When the user types Sam, the placeholder disappears.
  7. Sam uses the normal .username color, #111827.
  8. If the user clears the field, the placeholder appears again.

You can detect this empty-with-placeholder state using :placeholder-shown:

.username:placeholder-shown {
  border-color: #9ca3af;
}

This styles the input element while it is showing placeholder text; it does not style the placeholder text itself.

Real World Use Cases

Placeholder styling is useful when a form needs to match an interface design while remaining readable.

  • Login forms: Make hints such as Email address visually distinct from entered text.
  • Search fields: Use a muted placeholder like Search documentation that fits a navigation bar.
  • Checkout forms: Clarify expected formats, such as MM / YY or 12345.
  • Data-entry tools: Show a lightweight example, such as e.g., INV-1042.
  • Dark themes: Set a light, muted placeholder color so hints are visible on dark backgrounds.
  • Error recovery: Use an input border, error message, and clear placeholder hint to guide users after invalid submission.

Use placeholders as short hints, not as the only label. A persistent <label> remains visible after a user starts typing and is generally more accessible.

Take Quiz

Real Codebase Usage

In real projects, placeholder styling is usually part of a reusable form-control component or design-system rule.

Reusable component style

.form-control {
  width: 100%;
  padding: 0.75rem;
  color: #0f172a;
  background: #ffffff;
  border: 1px solid #cbd5e1;
  border-radius: 0.375rem;
}

.form-control::placeholder {
  color: #64748b;
  opacity: 1;
}

.form-control:focus {
  outline: 2px solid #2563eb;
  outline-offset: 2px;
}

Developers commonly:

  • Apply styles through a class such as .form-control rather than broad selectors like input.
  • Set the actual input text color and placeholder color separately.
  • Keep labels visible and use placeholders only for examples or format hints.
  • Style :focus so keyboard users can tell which control is active.
  • Use :placeholder-shown when the empty state needs a different layout or visual treatment.
  • Check contrast in both light and dark themes.

For example, a floating-label pattern may use the placeholder state to move a label only when the field has content:

.field-label {
  transition: transform 0.2s ease;
}

.field:focus + .field-label,
.field:not(:placeholder-shown) + .field-label {
  transform: translateY(-1.25rem) scale(0.85);
}

This pattern depends on :placeholder-shown, while ::placeholder remains responsible for styling the hint text.

Common Mistakes

Using an attribute selector to style the placeholder

/* This selects the input element, not its placeholder text. */
input[placeholder] {
  color: red;
}

Use input::placeholder instead.

input::placeholder {
  color: red;
}

Confusing :placeholder-shown with ::placeholder

/* This styles the input while its placeholder is visible. */
input:placeholder-shown {
  color: red;
}

:placeholder-shown is a pseudo-class and matches the input's state. It is useful for borders, backgrounds, or layout changes. To target the placeholder characters, use the pseudo-element:

input::placeholder {
  color: red;
}

Styling only color and seeing a faded result

Some browser styles use reduced opacity for placeholders. If the color appears lighter than expected, explicitly set opacity:

input::placeholder {
  color: #475569;
  opacity: 1;
}

Relying on a placeholder instead of a label

This is less clear once text is entered:

<input type="email" placeholder="Email address">

Prefer a visible label plus an optional format hint:

<label for="email">Email address</label>
<input id="email" type="email" placeholder="name@example.com">

Using !important unnecessarily

input::placeholder {
  color: red !important;
}

!important can make future overrides difficult. First use a sufficiently specific selector or ensure your stylesheet loads after the conflicting rule:

.account-form .email-input::placeholder {
  color: #334155;
}

Comparisons

CSS featureWhat it targetsExampleTypical use
[placeholder]An element that has a placeholder attributeinput[placeholder]Select all inputs that define a placeholder
::placeholderThe generated placeholder textinput::placeholderChange placeholder color or font style
:placeholder-shownAn input currently showing its placeholderinput:placeholder-shownStyle the empty field state
:focusAn input currently focusedinput:focusAdd a focus outline or border

::placeholder versus :placeholder-shown

/* Changes the hint text itself. */
input::placeholder {
  color: #94a3b8;
}

/* Changes the input box while it is empty. */
input:placeholder-shown {
  background-color: #f8fafc;
}

The double colon in ::placeholder indicates a pseudo-element. The single colon in :placeholder-shown indicates a pseudo-class.

Take Quiz

Cheat Sheet

/* Standard placeholder styling */
input::placeholder {
  color: #64748b;
  opacity: 1;
}

/* Scope to a reusable class */
.form-control::placeholder {
  color: #94a3b8;
}

/* Style the field when it is empty and showing a placeholder */
.form-control:placeholder-shown {
  background: #f8fafc;
}

/* Style typed text */
.form-control {
  color: #0f172a;
}
  • Use ::placeholder for the visible placeholder text.
  • Use [placeholder] to select elements that have the attribute; it does not select placeholder text.
  • Use :placeholder-shown for the element's empty state.
  • Add opacity: 1 when browser default placeholder opacity makes the color look faded.
  • Use a visible <label> for the field name; reserve placeholders for short examples or hints.
  • Scope rules with component classes to avoid unintentionally styling every form field.

FAQ

How do I change placeholder text color in CSS?

Use the ::placeholder pseudo-element:

input::placeholder {
  color: red;
}

Why does input[placeholder] not change the placeholder color?

It selects the <input> element based on the presence of its attribute. It does not select the browser-generated placeholder text. Use input::placeholder.

What is the difference between ::placeholder and :placeholder-shown?

::placeholder styles the hint text. :placeholder-shown matches an input that is empty and currently displaying its placeholder.

Can I style placeholders on textarea elements?

Yes.

textarea::placeholder {
  color: #64748b;
}

Why does my chosen placeholder color look too light?

Browsers may apply placeholder opacity. Set opacity: 1 alongside your chosen color.

input::placeholder {
  color: #475569;
  opacity: 1;
}

Should a placeholder replace an HTML label?

No. Use a visible <label> to name the field. A placeholder is best for a brief example, expected format, or extra hint.

Do I need browser-specific placeholder prefixes?

For modern browsers, use the standard ::placeholder selector. Legacy browser support may require older vendor-prefixed selectors, but they are generally unnecessary unless your project explicitly supports old browser versions.

Take Quiz

Mini Project

Description

Build a small contact-form style that clearly separates labels, entered text, placeholder hints, and focused fields. This reflects the form styling commonly used in application settings, checkout pages, and support forms.

Goal

Create a readable contact form with custom placeholder colors and accessible labels.

Requirements

  1. Add name and email fields with visible labels.
  2. Add a message textarea with a placeholder hint.
  3. Style normal entered text separately from placeholder text.
  4. Set placeholder opacity explicitly.
  5. Add a visible focus style for keyboard and mouse users.
Take Quiz

Keep learning

Related questions

View more