Styling Text Inputs
Restyle text inputs, textareas, and other text-type inputs — custom borders, focus animations, floating labels, and placeholder styles.
Styling Text Inputs
Text inputs are the most common form element on the web — search bars, login forms, contact forms. In this episode you will learn how to completely restyle text inputs with custom borders, animated focus states, floating labels, and beautiful placeholder text.
Resetting Browser Defaults
input[type="text"],
input[type="email"],
input[type="password"],
input[type="number"],
input[type="tel"],
input[type="url"],
input[type="search"],
textarea {
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
border: none;
outline: none;
background: none;
font-family: inherit;
font-size: inherit;
color: inherit;
width: 100%;
box-sizing: border-box;
}
The appearance: none property strips all browser-applied styles from the input. Combined with resetting border, outline, and background, this gives us a completely blank canvas. We also inherit the font family and size from the parent so inputs match the surrounding text.
Base Input Style
.styled-form input[type="text"],
.styled-form input[type="email"],
.styled-form input[type="password"],
.styled-form textarea {
padding: 12px 16px;
border: 2px solid #e5e7eb;
border-radius: 8px;
font-size: 15px;
color: #1f2937;
background: #fff;
transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.styled-form textarea {
min-height: 120px;
resize: vertical;
}
A clean, modern input with rounded corners, a light gray border, and smooth transitions for the focus state. Textareas get a minimum height and vertical-only resizing.
Placeholder Styling
.styled-form input::placeholder,
.styled-form textarea::placeholder {
color: #9ca3af;
font-style: italic;
opacity: 1; /* Firefox sets placeholder opacity to less than 1 */
}
The ::placeholder pseudo-element styles the placeholder text. Setting opacity: 1 is important because Firefox applies a default opacity less than 1 to placeholders, making them lighter than expected.
Focus State — Glowing Border
.styled-form input:focus,
.styled-form textarea:focus {
border-color: #4A90D9;
box-shadow: 0 0 0 3px rgba(74, 144, 217, 0.15);
}
When the input is focused, the border turns blue and a subtle glow appears around it using box-shadow. The box-shadow approach is better than outline because it respects border-radius and can be transitioned smoothly.
Focus Glow vs Outline
| Technique | Follows border-radius | Can be transitioned | Color customizable |
|---|---|---|---|
outline | Sometimes (browser-dependent) | No | Yes |
box-shadow | Always | Yes | Yes |
Underline Input Style
.input-underline {
border: none;
border-bottom: 2px solid #d1d5db;
border-radius: 0;
padding: 12px 4px;
background: transparent;
transition: border-color 0.3s ease;
}
.input-underline:focus {
border-bottom-color: #4A90D9;
box-shadow: none;
}
A minimal, Material Design-inspired input with only a bottom border. This style works well on light backgrounds and gives a clean, modern look.
Animated Underline with Pseudo-Element
.input-wrapper {
position: relative;
}
.input-wrapper::after {
content: "";
position: absolute;
bottom: 0;
left: 50%;
width: 0;
height: 2px;
background: #4A90D9;
transition: width 0.3s ease, left 0.3s ease;
}
.input-wrapper:focus-within::after {
width: 100%;
left: 0;
}
This creates a blue underline that expands from the center when the input is focused. The :focus-within pseudo-class activates when any child element inside the wrapper receives focus.
Floating Label Pattern
<div class="floating-group">
<input type="text" id="name" placeholder=" " required>
<label for="name">Full Name</label>
</div>
.floating-group {
position: relative;
margin-bottom: 24px;
}
.floating-group input {
padding: 20px 16px 8px;
border: 2px solid #e5e7eb;
border-radius: 8px;
font-size: 15px;
width: 100%;
transition: border-color 0.3s ease;
}
.floating-group label {
position: absolute;
left: 16px;
top: 50%;
transform: translateY(-50%);
font-size: 15px;
color: #9ca3af;
pointer-events: none;
transition: all 0.2s ease;
}
/* Float up when focused or has content */
.floating-group input:focus + label,
.floating-group input:not(:placeholder-shown) + label {
top: 8px;
transform: translateY(0);
font-size: 11px;
color: #4A90D9;
font-weight: 600;
}
The floating label sits inside the input as a placeholder and floats up to the top when the input is focused or has content. The trick uses :placeholder-shown — when the placeholder is not visible (meaning the user has typed something), the label stays floated up even after focus leaves. The placeholder is set to a single space (" ") so it is technically present but invisible.
Input with Icon
.input-icon-wrapper {
position: relative;
}
.input-icon-wrapper input {
padding-left: 44px;
}
.input-icon-wrapper .icon {
position: absolute;
left: 14px;
top: 50%;
transform: translateY(-50%);
color: #9ca3af;
font-size: 18px;
pointer-events: none;
transition: color 0.3s ease;
}
.input-icon-wrapper:focus-within .icon {
color: #4A90D9;
}
The icon is positioned absolutely inside the wrapper and extra left padding on the input prevents the text from overlapping it. The icon changes color when the input is focused using :focus-within.
Key Takeaways
appearance: nonestrips all browser default styles so you can build from scratch- Use
box-shadowinstead ofoutlinefor focus rings that followborder-radiusand can be transitioned ::placeholderstyles the placeholder text — setopacity: 1for cross-browser consistency- The floating label pattern uses
:placeholder-shownand:focusto animate the label position :focus-withinactivates styles on a parent when any child element is focused- Always inherit
font-familyandfont-sizeso inputs match the surrounding design