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:focusorinput: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
placeholderattribute 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.
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:
- The browser creates the
<input>element. - Because the field is empty, the browser displays
Enter your usernameas placeholder text. .usernamematches the input element and sets the color for normal input text to#111827..username::placeholdermatches the placeholder portion generated inside that input.- The placeholder receives
#9ca3afand is displayed in that color. - When the user types
Sam, the placeholder disappears. Samuses the normal.usernamecolor,#111827.- 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 addressvisually distinct from entered text. - Search fields: Use a muted placeholder like
Search documentationthat fits a navigation bar. - Checkout forms: Clarify expected formats, such as
MM / YYor12345. - 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.
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-controlrather than broad selectors likeinput. - Set the actual input text color and placeholder color separately.
- Keep labels visible and use placeholders only for examples or format hints.
- Style
:focusso keyboard users can tell which control is active. - Use
:placeholder-shownwhen 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 feature | What it targets | Example | Typical use |
|---|---|---|---|
[placeholder] | An element that has a placeholder attribute | input[placeholder] | Select all inputs that define a placeholder |
::placeholder | The generated placeholder text | input::placeholder | Change placeholder color or font style |
:placeholder-shown | An input currently showing its placeholder | input:placeholder-shown | Style the empty field state |
:focus | An input currently focused | input:focus | Add 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.
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
::placeholderfor the visible placeholder text. - Use
[placeholder]to select elements that have the attribute; it does not select placeholder text. - Use
:placeholder-shownfor the element's empty state. - Add
opacity: 1when 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.
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
- Add name and email fields with visible labels.
- Add a message textarea with a placeholder hint.
- Style normal entered text separately from placeholder text.
- Set placeholder opacity explicitly.
- Add a visible focus style for keyboard and mouse users.
Keep learning
Related questions
Angular ngClass Conditional Class Binding Explained
Learn how to use Angular ngClass for conditional classes, fix common binding mistakes, and understand why this template error happens.
Apply CSS to an iframe: Same-Origin Styling in HTML
Learn why parent-page CSS does not style iframe content, how same-origin rules work, and practical ways to style embedded pages safely.
Apply Multiple CSS Transforms: rotate() and translate()
Learn how to combine multiple CSS transform functions such as rotate() and translate(), understand transform order, and avoid overwritten rules.