accessibility
what the system promises, and eight checks before a page ships.
how the system is accessible
built in, not bolted on
the stylesheet carries the focus ring, the sizes and the contrast. a page that uses the classes gets most of this for free.
color never alone
every state that is a color is also a shape or a word: alerts have icons, the current item has aria-current, errors have a message.
native first
dialog, details, radio, checkbox, range and select are the real elements with new clothes. keyboards and screen readers already know them.
- focus is visible everywhere.a 3 px blue outline, 2 px outside the element. inputs use a 5 px blue underline instead. the ring is never removed without a replacement.
- text contrast is 4.5 to 1 or better.ink on paper, white or yellow; white on red, blue or ink; yellow on ink. red and blue are never body text on paper.
- targets are 48 px, or 44 at the smallest.buttons, rows, tabs, chips. gaps between targets are at least 8 px.
- selected is yellow and named.aria-current for navigation, aria-selected for tabs, aria-pressed for toggles, checked for inputs.
- every icon is labeled or hidden.aria-hidden when a word sits beside it; an aria-label when it stands alone.
- text scales.sizes use clamp and rem-friendly pixels; the layout survives 200 percent zoom because nothing is fixed height except the tab bar.
- reduced motion is honored.transitions and the loader stop; nothing else changes.
- errors are explained.the field is marked aria-invalid, the message is linked with aria-describedby, and it says what to fix.
contrast
the pairs used for text.
ink on paper: 15.1 : 1ink on yellow: 10.1 : 1white on red: 4.4 : 1white on blue: 7.5 : 1yellow on ink: 10.1 : 1white on ink: 17.3 : 1
the full table with every pair, including the failing ones, is on the color page.
keyboard
| where | keys | what happens |
|---|---|---|
| everywhere | tab, shift tab | moves through links, buttons and fields in reading order. the skip link is first. |
| tabs | left, right | moves between tabs and selects them. tab then enters the panel. |
| menu | enter, escape | opens the menu; escape closes it and returns focus to the button. |
| dialog | escape | closes it. focus returns to the button that opened it. |
| segmented control, radios | left, right | moves the choice. |
| range | left, right, home, end | moves the thumb by one step, or to the ends. |
| accordion | enter, space | opens or closes the item. |
forms
the error pattern, with every attribute it needs.
<div class="ws-field ws-field--error">
<label for="pw">password</label>
<input class="ws-input" id="pw" type="password" aria-invalid="true" aria-describedby="pw-hint" autocomplete="new-password">
<span class="ws-hint ws-hint--error" id="pw-hint">use at least 8 characters.</span>
</div>test it
eight checks before a page ships. tick them off here; the boxes are the real checkbox component.