Forms
axe Accessibility Linter
Error Lens
A CSS pseudo-class is a keyword added to a selector that specifies a special state of the selected element(s). For example, :hover can be used to change a button's color when the user's pointer hovers over it.
:valid
represents any <input> or other <form> element whose contents validate successfully
input:valid {
border-color: green;
}
needs "required"
:invalid
any <input> or other <form> element whose contents fail to validate.
input:invalid {
border-color: red;
}
needs "required"
:disabled
represents any disabled element
:checked
selector represents any radio, checkbox, or option element that is checked or toggled to an on state
:focus/:focus-visible
represents an element that has received focus
:placeholder-shown
represents any <input> or <textarea> element that is currently displaying placeholder text.
:not(
:not(
:not(
:not(
)
)
)
)
:disabled
doesn't represents any disabled element
:checked
selector represents any radio, checkbox, or option element that is not checked or toggled to an on state
:focus/:focus-visible
represents an element that hasn't received focus
:placeholder-shown
represents any <input> or <textarea> element that is currently not displaying placeholder text.
:not(
:not(
:not(
:not(
)
)
)
)
input:invalid:not(:focus, :placeholder-shown) { ... }
input:invalid:not(:focus, :placeholder-shown) ~ .error-message { ... }
JS er påkrævet for at overholde a11y-guidelines
input:user-invalid { ... }
input:user-invalid ~ .error-message { ... }
@supports (margin: 10px) {...}
@supports selector(:has(+ *)) {...}
Browser-kompatibilitet
if(CSS.supports("margin: 10px"))
@supports not (margin: 10px) {...}
@supports not selector(:has(+ *)) {...}
Ikke browser-kompatibel
if(!CSS.supports("margin: 10px"))
.form-group:has(input:user-invalid) { ... }
.form-group:has(input:user-invalid) .error-message { ... }
.form-group:has(input:not(:focus, :placeholder-shown):invalid) label { ... }
.form-group:has(input:invalid) { ... }
.form-group:has(input:not(:focus, :placeholder-shown):invalid) .error-message { ... }
label:has( + input:user-invalid) { ... }
label {
color: var(--color);
}
.form-group:has(:user-invalid) {
--color: red;
}
.form-group:has(:user-valid) {
--color: green;
}
textarea
øvelse
Gennemfør alle 8 levels og bliv opmærksom på, hvor vigtige "focus states" er i forhold til keyboard accessibility (link på Fronter).
Safari 💩
Firefox 💩
:focus-visible {
outline: 2px solid #000;
outline-offset: -2px;
box-shadow: 0 0 0 2px #fff, inset 0 0 0 3px #fff;
}
input {
appearance: none; /* Safari fix */
}
form { accent-color: deeppink; }
Rule of Least Power
input[type="checkbox"] { appearance: none; ... } /* Checked state */ input:checked::before { ... }
Remove browser styles
Style custom checkmark with pseudo-elements
Preparing an SVG in Figma / Illustrator
Resources
@layer reset, components, states; @layer components { /* Buttons, inputs etc. */ } @layer states { /* Make sure stats override, no matter specificity count */ :disabled { background-color: #ddd; color: #999; } :focus-visible { outline: 2px solid var(--focus-color, currentColor); outline-offset: 2px; } }
@layer reset, global, components, utilities, states;
Default styling
:root { --theme-color: 258 29% 43%; --accent-color: 180 50% 43%; } input { font: inherit; font-size: max(16px, 1em); padding: 0.25em 0.5em; background-color: #fff; border: 2px solid hsl(var(--theme-color)); } input:is(:focus-visible, :hover) { border-color: hsl(var(--accent-color)); }
Default styling
input:is([type="checkbox"], [type="radio"]) { appearance: none; /* custom styling */ }
Or with accent-color
form { accent-color: var(--theme-color, hotpink); /* checkbox, radio, progress, range etc. */ }
Form layout
form { display: grid; gap: 1.5rem; } .form-group { display: grid; gap: .3125rem; }
form {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
form > input {
flex: 1 1 10ch;
}
input[type="email"] {
flex: 3 1 30ch;
}
.container {
container-type: inline-size;
}
@container (width > 25rem) {
.newsletter { ... }
}