Styling for UX
Forms
Extensions
axe Accessibility Linter


Error Lens
UI States

Pseudo-classes
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.
Pseudo-classes
Pseudo-classes
:valid
represents any <input> or other <form> element whose contents validate successfully
input:valid {
border-color: green;
}
needs "required"
Pseudo-classes
:invalid
any <input> or other <form> element whose contents fail to validate.
input:invalid {
border-color: red;
}
needs "required"
Pseudo-classes = states


Pseudo-classes = states

Pseudo-classes = states
Pseudo-classes / states
: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(
)
)
)
)
Pseudo-classes / states
: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) { ... }
Placeholder-shown
input:invalid:not(:focus, :placeholder-shown) ~ .error-message { ... }
JS er påkrævet for at overholde a11y-guidelines
input:user-invalid { ... }
:user-valid/-invalid
input:user-invalid ~ .error-message { ... }
@supports (margin: 10px) {...}
@supports selector(:has(+ *)) {...}
@supports
Browser-kompatibilitet
if(CSS.supports("margin: 10px"))
@supports not (margin: 10px) {...}
@supports not selector(:has(+ *)) {...}
@supports
Ikke browser-kompatibel
if(!CSS.supports("margin: 10px"))
:has()
.form-group:has(input:user-invalid) { ... }
.form-group:has(input:user-invalid) .error-message { ... }
.form-group:has(input:not(:focus, :placeholder-shown):invalid) label { ... }
:has()
.form-group:has(input:invalid) { ... }
.form-group:has(input:not(:focus, :placeholder-shown):invalid) .error-message { ... }
label:has( + input:user-invalid) { ... }
:has()
label {
color: var(--color);
}
.form-group:has(:user-invalid) {
--color: red;
}
.form-group:has(:user-valid) {
--color: green;
}
:has()
:has()
field-sizing
textarea
field-sizing
Browser compatibility
🫢

field-sizing
Browser compatibility

øvelse
Hocus :focus
Gennemfør alle 8 levels og bliv opmærksom på, hvor vigtige "focus states" er i forhold til keyboard accessibility (link på Fronter).

Focus states
Focus states

Safari 💩
Focus states
Firefox 💩

Focus states


: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 */
}
Tilføj "states" (pseudo-klasser) til din formular
- :focus
- :user-valid
- :user-invalid (with error messages)
Tilføj styles for følgende pseudo-klasser:
Custom Checkboxes / Radios

User Agent styles



UA styles

form { accent-color: deeppink; }
Rule of Least Power
Customize
input[type="checkbox"] { appearance: none; ... } /* Checked state */ input:checked::before { ... }
Remove browser styles
Style custom checkmark with pseudo-elements
Ressourcer

Gør det mere spændende

Reducerer cognitive load


Gør det mere spændende
Animated checkmark
Animated checkmark

Preparing an SVG in Figma / Illustrator
Animated checkmark
Animated checkmark
Animated checkmark
Resources







😭
Cascade layers
@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; } }
Cascade layers
@layer reset, global, components, utilities, states;
A sensible CSS reset
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)); }
A sensible CSS reset
Default styling
input:is([type="checkbox"], [type="radio"]) { appearance: none; /* custom styling */ }

A sensible CSS reset
Or with accent-color
form { accent-color: var(--theme-color, hotpink); /* checkbox, radio, progress, range etc. */ }
A sensible CSS reset
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 { ... }
}
Form Styling & UX
By Dannie Vinther
Form Styling & UX
Styling forms
- 99