Forms are semantic HTML. CSS should make them clear without hiding their meaning.
Start with real form controls:
<label for="email">Email</label>
<input id="email" name="email" type="email" required />
Then style the controls:
label {
display: block;
font-weight: 600;
}
input {
inline-size: 100%;
padding: 0.75rem;
border: 1px solid rgb(170 180 195);
border-radius: 0.375rem;
font: inherit;
}
Interaction states
Buttons and links need state styles:
.button {
background: royalblue;
color: white;
border: 0;
border-radius: 0.375rem;
padding: 0.75rem 1rem;
}
.button:hover {
background: rgb(35 80 190);
}
.button:active {
translate: 0 1px;
}
.button:disabled {
opacity: 0.55;
cursor: not-allowed;
}
Hover is not universal. Touch devices may not have hover, so do not make essential information hover-only.
Focus and focus-visible
Focus shows which control receives keyboard input:
:focus-visible {
outline: 3px solid color-mix(in oklab, royalblue, white 25%);
outline-offset: 3px;
}
Use :focus-visible for keyboard-friendly focus styles that do not show on every mouse click.
Validation states
CSS can respond to form validity:
input:user-invalid {
border-color: rgb(180 35 35);
}
input:user-valid {
border-color: rgb(20 130 85);
}
:user-invalid and :user-valid avoid showing error styles before the user interacts in supporting browsers.
Fallback:
input:invalid:not(:placeholder-shown) {
border-color: rgb(180 35 35);
}
Other useful states:
input:required {
border-inline-start-width: 4px;
}
input:checked + label {
font-weight: 700;
}
Accent color
For native checkboxes, radios, and range controls:
:root {
accent-color: royalblue;
}
This keeps native controls recognizable while matching your theme.
Placeholder text
Placeholder text is not a label:
input::placeholder {
color: rgb(110 120 135);
}
Use placeholders for examples or hints, not required instructions.
What to carry forward
- use semantic form controls first
- keep labels visible or accessibly available
- style hover, active, disabled, and focus states intentionally
:focus-visiblesupports keyboard users- validation styles should avoid yelling before interaction
accent-coloris a low-risk way to theme native controls
Quick Check
One answerWhy is `:focus-visible` useful?
Choose the best answer and use it to track your progress through the lesson.
Why that answer is correct
`:focus-visible` lets browsers apply focus indication when users need it, such as keyboard navigation.
The next lesson broadens state styling into accessibility: contrast, motion preferences, forced colors, and pointer behavior.