defuss-shadcn / Forms & Inputs / label
LabelATM
Renders an accessible label associated with form controls. Built on the native <label> element with :has() for focus-reactive styling. No JavaScript required. The label’s for and the control’s id must carry the exact same value - that pairing is the association: it is what makes clicking the label focus the field and lets a screen reader announce the control’s name. Change one side and leave the other, and the label keeps looking right while quietly stopping working.
On this page (8)
§Default
Basic label paired with an input. Click the label to focus the input - for='demo-email' and id='demo-email' must always match; changing one without the other breaks the link.
§Required
The red asterisk renders automatically from :has(+ input[required]) - no markup to add or forget.
§Optional hint
Hint text indicating the field is optional.
§Disabled
Dimmed label for disabled fields. The label auto-detects the disabled input via :has() - no data-disabled attribute needed.
§With Checkbox
Inline label paired with a checkbox control.
§With Switch
Inline label paired with a switch control.
§Form Field
Label composed with an input and description text, as used in forms.
§CSS view file
/* -- Label component -------------------------------------------- */@layer components { .label { font-size: 0.875rem; font-weight: 500; font-family: var(--font-sans); line-height: 1; color: var(--foreground); display: block; margin-bottom: 0.375rem; cursor: default; /* Required - the adjacent control carries `required`: render the star. Pure CSS (no span to remember, nothing to desync); decorative only — the native attribute already conveys the requirement to AT. */ &:has(+ input[required])::after, &:has(+ textarea[required])::after { content: ' \00a0*'; color: var(--destructive); font-weight: 600; } /* Disabled - explicit attribute */ &[data-disabled] { opacity: 0.7; cursor: not-allowed; } /* Disabled - auto-detect via adjacent disabled control */ &:has(+ :disabled), &:has(+ [data-disabled]) { opacity: 0.7; cursor: not-allowed; } } /* -- Hint text (optional, required indicators) ----------- */ .label-hint { font-weight: 400; font-size: 0.8125rem; color: var(--muted-foreground); } /* -- Accessibility ---------------------------------------- */ @media (prefers-contrast: more) { .label[data-disabled], .label:has(+ :disabled), .label:has(+ [data-disabled]) { opacity: 0.85; } } @media (forced-colors: active) { .label { color: LinkText; } .label[data-disabled], .label:has(+ :disabled), .label:has(+ [data-disabled]) { opacity: 1; color: GrayText; } }}Comments, ideas or improvements? Edit this page's source on GitHub