Input, Textarea & Select Styling
Form inputs, textareas, and selects have browser defaults that can be hard to customize. With CSS, you can style these elements to match your design while maintaining usability and accessibility. Key properties include appearance, border, padding, focus styles, and placeholder colors.
Styling text inputs and textareas
CSS
<!-- Basic input styling -->
input[type="text"],
input[type="email"],
input[type="password"],
textarea {
width: 100%;
padding: 10px 12px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 16px;
font-family: inherit;
transition: all 0.3s ease;
}
input:focus,
textarea:focus {
outline: none;
border-color: #3498db;
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
}
<!-- Clean, focused styling -->
/* Error state -->
input.error,
textarea.error {
border-color: #e74c3c;
background: #fadbd8;
}
input.error:focus {
box-shadow: 0 0 0 3px rgba(231, 76, 60, 0.1);
}
<!-- Visual error indication -->
/* Success state -->
input.success {
border-color: #27ae60;
background: #d5f4e6;
}
input.success:focus {
box-shadow: 0 0 0 3px rgba(39, 174, 96, 0.1);
}
<!-- Visual success indication -->
/* Disabled state -->
input:disabled,
textarea:disabled {
background: #f5f5f5;
border-color: #ddd;
color: #999;
cursor: not-allowed;
}
<!-- Visual disabled state -->
/* Placeholder styling -->
::placeholder {
color: #999;
opacity: 1; /* Firefox requires explicit opacity -->
}
input:focus::placeholder {
color: #bbb;
}
<!-- Better placeholder visibility -->Form input styling patterns
Style | When to Use | Best For |
|---|---|---|
Bordered | Most forms | Traditional, clear |
Borderless with underline | Modern design | Material Design |
Filled background | Dense forms | Compact layouts |
Floating label | Elegant | User-friendly |
CSS
<!-- Material Design style: border + underline -->
input {
appearance: none;
background: transparent;
border: none;
border-bottom: 1px solid #ccc;
padding: 8px 0;
font-size: 16px;
transition: border-color 0.3s;
}
input:focus {
outline: none;
border-bottom-color: #3498db;
border-bottom-width: 2px;
}
<!-- Clean underline style -->
/* Filled background input -->
input {
appearance: none;
background: #f5f5f5;
border: 1px solid transparent;
padding: 12px;
border-radius: 4px;
font-size: 16px;
transition: all 0.3s;
}
input:hover {
background: #efefef;
}
input:focus {
outline: none;
background: white;
border-color: #3498db;
}
<!-- Filled background style -->
/* Floating label pattern -->
.form-group {
position: relative;
margin-bottom: 20px;
}
input {
width: 100%;
padding: 12px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 16px;
background: white;
}
label {
position: absolute;
top: 12px;
left: 12px;
background: white;
padding: 0 4px;
color: #999;
transition: all 0.3s;
pointer-events: none;
}
input:focus + label,
input:not(:placeholder-shown) + label {
top: -10px;
left: 8px;
font-size: 12px;
color: #3498db;
}
<!-- Label floats above on focus -->
/* Large input field -->
input.large {
padding: 16px;
font-size: 18px;
border-radius: 8px;
}
<!-- Bigger touch target -->
/* Compact input -->
input.small {
padding: 6px 8px;
font-size: 14px;
border-radius: 3px;
}
<!-- Smaller for dense layouts -->Textarea specific styling
CSS
<!-- Textarea styling -->
textarea {
appearance: none;
width: 100%;
min-height: 120px;
padding: 12px;
border: 1px solid #ccc;
border-radius: 4px;
font-family: 'Courier New', monospace; /* monospace for code -->
font-size: 14px;
resize: vertical; /* allow vertical resize only -->
transition: all 0.3s;
}
textarea:focus {
outline: none;
border-color: #3498db;
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
}
<!-- Usable, focused textarea -->
/* Disable resize -->
textarea {
resize: none;
/* User can't resize -->
}
/* Auto-growing textarea with JavaScript -->
textarea {
resize: none;
overflow: hidden;
min-height: 100px;
}
/* With resize handle -->
textarea {
resize: both; /* allow both directions -->
}
<!-- Give users control -->
/* Character counter -->
textarea {
position: relative;
}
.char-count {
font-size: 12px;
color: #999;
margin-top: 4px;
text-align: right;
}
.textarea-with-counter {
position: relative;
}
.textarea-with-counter::after {
content: attr(data-char-count);
position: absolute;
bottom: 8px;
right: 12px;
font-size: 12px;
color: #999;
}
<!-- Character limit indicator -->Select element styling
CSS
<!-- Basic select styling -->
select {
appearance: none;
width: 100%;
padding: 10px 12px;
padding-right: 32px; <!-- room for dropdown arrow -->
border: 1px solid #ccc;
border-radius: 4px;
background: white;
font-size: 16px;
cursor: pointer;
transition: all 0.3s;
}
select:focus {
outline: none;
border-color: #3498db;
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
}
<!-- Basic styled select -->
/* Custom dropdown arrow -->
select {
background: white url('data:image/svg+xml;charset=UTF-8,...') no-repeat right 12px center;
background-size: 16px;
padding-right: 40px;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
}
<!-- Custom arrow icon -->
/* Option styling (limited browser support) -->
option {
padding: 8px;
background: white;
color: #333;
}
option:checked {
background: linear-gradient(#3498db, #3498db);
color: white;
}
<!-- Some styling works, but limited -->
/* Disabled select -->
select:disabled {
background-color: #f5f5f5;
color: #999;
cursor: not-allowed;
border-color: #ddd;
}
<!-- Visual disabled state -->
/* Multiple select -->
select[multiple] {
min-height: 120px;
padding: 8px;
}
select[multiple] option {
padding: 4px 8px;
}
<!-- Multi-select with size -->Accessibility best practices
CSS
<!-- Clear focus indicators -->
input:focus,
textarea:focus,
select:focus {
outline: 2px solid #3498db;
outline-offset: 2px;
}
<!-- Always visible focus -->
/* Large enough touch targets (44px minimum) -->
input,
textarea,
select {
min-height: 44px;
min-width: 44px;
}
<!-- Mobile-friendly sizing -->
/* Labels properly associated -->
<label for="email">Email</label>
<input id="email" type="email" required>
<!-- Always use id/for -->
/* Error messages -->
<input id="password" type="password" aria-describedby="pwd-error">
<span id="pwd-error" role="alert">Password must be 8+ characters</span>
<!-- Link errors to inputs with aria-describedby -->
/* High contrast mode support -->
@media (prefers-contrast: more) {
input {
border-width: 2px;
border-color: #000;
}
input:focus {
outline-width: 3px;
}
}
<!-- Stronger visuals in high contrast mode -->
/* Reduced motion support -->
@media (prefers-reduced-motion: reduce) {
input,
textarea,
select {
transition: none;
}
}
<!-- Respect motion preferences -->Note
Style form inputs with `appearance: none` to remove browser defaults. Use consistent padding, borders, and focus states. Textareas need explicit height control. Selects are tricky to style fully (custom arrows work, but options have limited styling). Always ensure 44×44px minimum touch targets, clear focus indicators, and proper label associations for accessibility.
Next
Range slider styling: [Styling Range Sliders](/css/range-slider).