RadioGroup
RadioGroup lar brukeren velge ett alternativ fra en liste av gjensidig utelukkende valg. Når ett valg gjøres, blir eventuelle tidligere valg automatisk fjernet.
Egnet til
- Når brukeren skal velge ett alternativ fra en liste
- Valg som er gjensidig utelukkende
- Situasjoner der alle alternativer bør være synlige samtidig
- Kortere lister med tydelige forskjeller mellom alternativene
Uegnet til
- Når flere valg skal kunne velges (bruk
Checkbox) - Lange lister med mange alternativer (vurder
Select) - Når det ikke er nødvendig å vise alle alternativer samtidig
- Situasjoner der det er naturlig å kunne angre eller fjerne valg uten å velge et nytt
Kom i gang
Kode
<RadioGroup legend="Velg kundetype" name="kundetype" defaultValue="privat" options={[ { value: 'privat', label: 'Privat' }, { value: 'bedrift', label: 'Bedrift' }, { value: 'annet', label: 'Annet' }, ]} />
For enkle lister er options-propen den raskeste veien — på samme måte som Select. Hver option har value og label.
I praksis vil du som regel holde valgt verdi i state og koble den via value/onChange:
const [kundetype, setKundetype] = useState<string>('privat');
<RadioGroup
legend="Velg kundetype"
name="kundetype"
value={kundetype}
onChange={setKundetype}
options={[
{ value: 'privat', label: 'Privat' },
{ value: 'bedrift', label: 'Bedrift' },
{ value: 'annet', label: 'Annet' },
]}
/>
Trenger du mer — deaktiverte alternativer, custom id-er eller ref — bruk RadioButton-barn i stedet:
Kode
<RadioGroup legend="Velg kundetype" name="kundetype-children" defaultValue="privat"> <RadioButton value="privat" label="Privat" /> <RadioButton value="bedrift" label="Bedrift" /> <RadioButton value="annet" label="Annet" /> </RadioGroup>
Komponenten håndterer name-propagering og ARIA-kobling automatisk. Hver RadioButton må ha en unik value innenfor gruppen. Hvis både options og children er satt, vinner options.
Eksempler
Med beskrivelse
Bruk description for å gi ekstra kontekst til hele gruppen.
Verifiser forced-colors (Windows høykontrast) selv
Radio-indikatoren har en @media (forced-colors: active)-fallback i indeks-css/css/components/form/radio-group.css, men forced-colors kan ikke triggers fra siden — du må slå den på i nettleseren for å se den faktiske visningen.
Chromium (Chrome, Edge, Brave):
- Åpne DevTools (F12 eller
Ctrl+Shift+I). Ctrl+Shift+P→ skriv "Show Rendering" → Enter.- I Rendering-panelet, scroll til Emulate CSS media feature
forced-colorsog velgactive. - Kombiner gjerne med Emulate CSS media feature
prefers-color-scheme=darkfor å sjekke høykontrast på mørk bakgrunn.
Firefox:
about:config→ settui.systemUsesDarkTheme = 1ogbrowser.display.document_color_use = 2.- Last siden på nytt.
Windows 11 (ekte HCM):
- Innstillinger → Tilgjengelighet → Kontrasttemaer → velg f.eks. Aquatic eller Nattlig.
- Hurtigtast:
Venstre Alt + Venstre Shift + Print Screenveksler.
Sjekk at: ringen er synlig (CanvasText), valgt prikk har brukerens accent-farge (Highlight), fokus-outline er synlig, og at deaktiverte/feil-tilstander fortsatt er forskjellbare. Se _strategier/high-contrast-mode-strategy.md punkt 5a for begrunnelsen bak fargevalget.
Kode
<RadioGroup legend="Velg abonnement" description="Du kan endre dette senere" name="abonnement" defaultValue="basis" options={[ { value: 'basis', label: 'Basis' }, { value: 'premium', label: 'Premium' }, ]} />
Horisontal orientering
For svært korte lister kan alternativene vises ved siden av hverandre. Bruk det med omtanke — vertikal er enklere å skanne, og horisontal bryter til vertikal automatisk på smale skjermer.
Kode
<RadioGroup legend="Kontaktes på e-post?" name="kontakt" orientation="horizontal" defaultValue="ja" options={[ { value: 'ja', label: 'Ja' }, { value: 'nei', label: 'Nei' }, ]} />
Med feilmelding
Når validering feiler, vis en feilmelding som forklarer hva som er galt og hva brukeren skal gjøre. <ix-radio-group> setter aria-invalid="true" på containeren og alle inputs automatisk når error-elementet har innhold.
Kode
<RadioGroup legend="Hvilken bydel bor du i?" name="bydel" defaultValue="ostbyen" errorMessage="Du må velge en bydel før du kan fortsette" options={[ { value: 'ostbyen', label: 'Østbyen' }, { value: 'lerkendal', label: 'Lerkendal' }, { value: 'heimdal', label: 'Heimdal' }, ]} />
Skjult legend
I tabeller eller andre kontekster der gruppe-konteksten allerede er gitt, kan legend skjules visuelt. Den skal fortsatt være meningsfull — skjermlesere leser den.
Kode
<RadioGroup legend="Velg favoritt for rad 1" name="rad-1" orientation="horizontal" hideLegend defaultValue="a" options={[ { value: 'a', label: 'A' }, { value: 'b', label: 'B' }, ]} />
Skrivebeskyttet og deaktivert
readOnly viser valget men hindrer endring. disabled gjør hele gruppen inaktiv. Vurder om disabled er riktig — alternativet kan ofte heller skjules eller forklares.
Kode
<> <RadioGroup legend="Skrivebeskyttet" name="ro" readOnly defaultValue="a" options={[ { value: 'a', label: 'Alternativ A' }, { value: 'b', label: 'Alternativ B' }, ]} /> <RadioGroup legend="Deaktivert" name="dis" disabled defaultValue="a" options={[ { value: 'a', label: 'Alternativ A' }, { value: 'b', label: 'Alternativ B' }, ]} /> </>
Retningslinjer
Tydelige labels gir forutsigbarhet
Hver RadioButton skal ha en synlig og beskrivende label. Labelen skal beskrive hva alternativet er, ikke hva brukeren skal gjøre.
| Gjør dette | Ikke dette |
|---|---|
| Privat | Velg privat |
| Bedrift | Trykk her for bedrift |
RadioGroup skal alltid brukes i gruppe
Radioknapper gir mening kun som del av en gruppe — de representerer gjensidig utelukkende valg. Gruppen må ha en legend som forklarer hva valget gjelder, f.eks. "Velg kundetype".
Alle alternativer skal være synlige
Radioknapper egner seg når alle alternativene vises samtidig. Brukeren får oversikt og kan sammenligne valgene før de bestemmer seg. Hvis listen blir lang, vurder Select.
Vertikalt er hovedregelen
Vertikal orientering er enklere å skanne og fungerer bedre ved zoom og smale skjermer. Bruk horisontal kun for svært korte og få alternativer.
Rekkefølgen påvirker valget
Sorter alternativene logisk eller alfabetisk. I noen tilfeller kan det være riktig å plassere det mest sannsynlige eller anbefalte valget først — vær bevisst på at det påvirker brukerens beslutning.
Standardvalg bør brukes med omtanke
Et forhåndsvalgt alternativ kan gjøre det raskere å fylle ut skjemaet, men kan også føre til at brukeren ikke tar et aktivt valg. Bruk det kun når det finnes et tydelig og trygt default-valg.
Hele raden er klikkbar
Både radioknappen og labelen er klikkbar. Det gir en stor trefflate (44 × 44 px minimum) og fungerer godt på mobil.
Universell utforming
Hva du selv må sørge for
- Beskrivende legend — komponenten kobler legend til gruppen, men du må skrive god tekst
- Beskrivende labels — hver RadioButton må ha en label som forklarer hva alternativet er
- Konkret feilmelding —
errorMessageviser feilen, men teksten er ditt ansvar - Vurder
disabledmed omtanke — et deaktivert alternativ er ofte vanskelig å forstå - Sett
requirednår gruppen er påkrevd, så native validering virker
Hva komponenten gjør automatisk
Når du bruker <ix-radio-group> eller React-komponenten, settes dette opp for deg:
role="radiogroup"på containeren slik at skjermlesere annonserer gruppen riktigaria-labelledbytil legend-elementet — gruppens tilgjengelige navnaria-describedbytil description og error — leses etter legendaria-live="polite"på error-elementet slik at endringer kunngjøres uten å avbrytearia-invalidpå containeren og alle inputs synkroniseres med error-innholdet via MutationObserver- Felles
namepå alle inputs — sikrer mutual exclusivity (kun ett valg av gangen) og ArrowKey-navigasjon htmlFor/idmellom hver label og input — klikk på label velger alternativetdisabled/readonlypropagerer fra container til alle inputs
Tastaturnavigasjon
| Tast | Handling |
|---|---|
| Tab | Flytter fokus til den valgte radioknappen i gruppen, eller til første radioknapp om ingen er valgt |
| Pil ned / Pil høyre | Flytter fokus og valg til neste alternativ i gruppen |
| Pil opp / Pil venstre | Flytter fokus og valg til forrige alternativ i gruppen |
| Space | Velger radioknappen som har fokus (når ingen var valgt fra før) |
Skjermleser
- Ved fokus inn i gruppen: "[legend-tekst], gruppe" — leses opp som radiogroup
- Ved fokus på en radioknapp: "[label], radioknapp, [n] av [m], [valgt/ikke valgt]"
- Når description er satt: leses opp etter legend som del av gruppe-konteksten
- Ved feiltilstand: aria-invalid annonseres som «ugyldig», og feilmeldingsteksten leses opp polite via aria-live
- Når required er satt: feltet annonseres som «påkrevd»
WCAG-kriterier
Sist gjennomgått: 2026-05-29 — alle 56 WCAG 2.2-kriterier vurdert
WCAG-kriterier8 ditt ansvar · 14 håndtert · 39 ikke relevant · 0 ikke på plass
Ditt ansvar (8)
| Kriterium | Nivå | Hva du må gjøre |
|---|---|---|
| 1.3.1 Informasjon og relasjoner | A | Skriv beskrivende legend for gruppen. Legend forklarer hva brukeren skal velge mellom. Skjermlesere leser legend som gruppens tilgjengelige navn. "Velg kundetype" er bedre enn "Type". Du kan skjule legend visuelt med hideLegend, men den må fortsatt være meningsfull — den leses opp av skjermlesere. |
| 2.4.6 Overskrifter og ledetekster | AA | Skriv beskrivende legend for gruppen. Legend forklarer hva brukeren skal velge mellom. Skjermlesere leser legend som gruppens tilgjengelige navn. "Velg kundetype" er bedre enn "Type". Du kan skjule legend visuelt med hideLegend, men den må fortsatt være meningsfull — den leses opp av skjermlesere. |
| 3.3.2 Ledetekster eller instruksjoner | A | Skriv beskrivende legend for gruppen. Legend forklarer hva brukeren skal velge mellom. Skjermlesere leser legend som gruppens tilgjengelige navn. "Velg kundetype" er bedre enn "Type". Du kan skjule legend visuelt med hideLegend, men den må fortsatt være meningsfull — den leses opp av skjermlesere. |
| 3.3.2 Ledetekster eller instruksjoner | A | Skriv beskrivende label på hver RadioButton. Labelen skal beskrive hva alternativet er, ikke hva brukeren skal gjøre. "Privat" er bedre enn "Velg privat". Hold labelen kort og presis — beskrivelser hører hjemme i description-propen. |
| 3.3.1 Identifikasjon av feil | A | Skriv konkret feilmelding. errorMessage skal forklare hva brukeren må gjøre, ikke bare at noe er feil. "Du må velge et alternativ" er bedre enn "Påkrevd felt". Komponenten viser meldingen og setter aria-invalid automatisk, men du skriver innholdet. |
| 3.3.3 Forslag ved feil | AA | Skriv konkret feilmelding. errorMessage skal forklare hva brukeren må gjøre, ikke bare at noe er feil. "Du må velge et alternativ" er bedre enn "Påkrevd felt". Komponenten viser meldingen og setter aria-invalid automatisk, men du skriver innholdet. |
| 3.3.2 Ledetekster eller instruksjoner | A | Vurder bruk av disabled. En deaktivert radioknapp er vanskelig å forstå uten forklaring. Vurder om alternativet heller bør skjules, forklares eller presenteres som utilgjengelig på en tydeligere måte. Disabled bryter dessuten kontrastkravet (1.4.3 unntar disabled-elementer). |
| 3.3.2 Ledetekster eller instruksjoner | A | Sett required for påkrevde gruppe. Når gruppen er påkrevd, sett required-propen. Komponenten propagerer det til alle inputs slik at native validering virker, og skjermlesere annonserer feltet som påkrevd. |
Håndtert av komponenten (14)
| Kriterium | Nivå | Hva komponenten gjør |
|---|---|---|
| 1.3.1 Informasjon og relasjoner | A | ix-radio-group setter role="radiogroup", aria-labelledby til legend, og aria-describedby til description og error. Native input[type="radio"] med felles name gir mutual exclusivity. |
| 1.4.1 Bruk av farge | A | Selected state vises både med fylt sirkel (form) og endret farge — ikke kun farge. |
| 1.4.3 Kontrast (minimum) | AA | Tekst og indikator bruker --ix-color-foreground-main-default og --ix-color-fill-main-default. Forventes å oppfylle 4,5:1 mot standard bakgrunn. Verifiser ved egendefinerte bakgrunnsfarger. |
| 1.4.10 Omflyt | AA | Reflower korrekt ned til 320 px. Horisontal orientering bryter til vertikal ved smal skjerm via media query. |
| 1.4.11 Kontrast for ikke-tekstlig innhold | AA | Radio-indikatorens border bruker --ix-color-border-main-default. Selected/focus/error bruker --ix-color-fill-main-default eller --ix-color-fill-danger-default — forventes å oppfylle 3:1 mot bakgrunn. |
| 1.4.12 Tekstavstand | AA | Bruker --ix-font-size-md (relativ enhet) og tåler økt line-height, bokstav- og ordavstand uten tap av innhold. |
| 2.1.1 Tastatur | A | Native input[type="radio"] med felles name gir tastatur-tilgang gratis: Tab flytter fokus til gruppen, ArrowKeys navigerer og velger, Space velger fokusert radio. |
| 2.4.7 Synlig fokus | AA | :focus-visible på input gir tydelig outline rundt label via CSS. |
| 2.5.5 2.5.5 | ? | Hver label har min-height 44px, slik at klikkeflaten oppfyller AAA-kravet for målstørrelse (44×44 px). |
| 2.5.8 Målstørrelse (minimum) | AA | Klikkeflaten på 44×44 px oppfyller WCAG 2.2 AA-kravet (24×24 px) med god margin. |
| 3.3.1 Identifikasjon av feil | A | ix-radio-group setter aria-invalid="true" på host og alle inputs når errorMessage har innhold, og kobler feilmeldingen via aria-describedby. |
| 3.3.3 Forslag ved feil | AA | errorMessage-propen brukes til å gi konkret feilmelding. Komponenten viser den, men teksten er konsumentens ansvar. |
| 4.1.2 Navn, rolle, verdi | A | Native input[type="radio"] gir rolle, navn (via label) og verdi automatisk. role="radiogroup" på containeren grupperer dem. |
| 4.1.3 Statusmeldinger | AA | ix-radio-group setter aria-live="polite" på error-elementet slik at skjermlesere annonserer endringer i feilmeldingen uten å avbryte brukeren. |
Ikke relevant (39)
| Kriterium | Nivå | Hvorfor ikke relevant |
|---|---|---|
| 1.1.1 Ikke-tekstlig innhold | A | |
| 1.2.1 Bare lyd og bare video (forhåndsinnspilt) | A | Ingen medieelementer. |
| 1.2.2 Teksting (forhåndsinnspilt) | A | Ingen medieelementer. |
| 1.2.3 Synstolking eller mediealternativ (forhåndsinnspilt) | A | Ingen medieelementer. |
| 1.2.4 Teksting (direkte) | AA | Ingen medieelementer. |
| 1.2.5 Synstolking (forhåndsinnspilt) | AA | Ingen medieelementer. |
| 1.3.3 Sensoriske egenskaper | A | |
| 1.3.4 Visningsretning | AA | Ingen fast orientering — tilpasser seg visningsretning. |
| 1.3.5 Identifiser formål med inndata | AA | RadioGroup samler ikke standardiserte personopplysninger som dekkes av autocomplete-token. |
| 1.4.2 Styring av lyd | A | Ingen lydelementer. |
| 1.4.4 Endre tekststørrelse | AA | |
| 1.4.5 Bilder av tekst | AA | Ingen bilder av tekst. |
| 1.4.13 Innhold ved hover eller fokus | AA | |
| 2.1.2 Ingen tastaturfelle | A | |
| 2.1.4 Tastatursnarveier | A | Ingen egendefinerte tastatursnarveier. |
| 2.2.1 Justerbar hastighet | A | Ingen tidsbegrensede funksjoner. |
| 2.2.2 Pause, stopp, skjul | A | Ingen animasjon eller automatisk oppdatering. |
| 2.3.1 Terskelverdi på tre glimt | A | Ingen blinkende eller glimtende innhold. |
| 2.4.1 Hoppe over blokker | A | Sidekrav — gjelder ikke enkeltkomponenter. |
| 2.4.2 Sidetitler | A | Sidekrav — gjelder ikke enkeltkomponenter. |
| 2.4.3 Fokusrekkefølge | A | |
| 2.4.4 Formål med lenke (i kontekst) | A | Ingen lenker i komponenten. |
| 2.4.5 Flere måter | AA | Sidekrav — gjelder ikke enkeltkomponenter. |
| 2.4.11 Fokus ikke skjult (minimum) | AA | Ingen sticky/overlappende elementer som kan skjule fokus. |
| 2.5.1 Pekerbevegelser | A | Ingen drag-and-drop eller sveipebevegelser. |
| 2.5.2 Avbryt peker | A | |
| 2.5.4 Bevegelsesaktivering | A | Ingen bevegelsesbasert interaksjon. |
| 2.5.6 Samtidige inndatamekanismer | A | |
| 2.5.7 Drabevegelser | A | Ingen drag-and-drop. |
| 3.1.1 Språk på siden | A | Sidekrav — gjelder ikke enkeltkomponenter. |
| 3.1.2 Språk på deler av innhold | AA | Komponenten setter ikke lang-attributt — innhold er på sidespråket. |
| 3.2.1 Ved fokus | A | |
| 3.2.2 Ved inndata | A | |
| 3.2.3 Konsistent navigasjon | AA | Sidekrav — gjelder ikke enkeltkomponenter. |
| 3.2.4 Konsistent identifikasjon | AA | Systemkrav — gjelder konsistens på tvers av sider, ikke enkeltkomponenter. |
| 3.2.6 Konsistent hjelp | A | Sidekrav — gjelder plassering av hjelpefunksjon på tvers av sider. |
| 3.3.4 Forhindring av feil (juridisk, økonomisk, data) | AA | Flytkrav — gjelder bekreftelse/reversering av transaksjoner, ikke enkeltfelter. |
| 3.3.7 Redundant oppføring | A | Flytkrav — gjelder at brukeren ikke skal gjenta informasjon i en prosess. |
| 3.3.8 Tilgjengelig autentisering (minimum) | AA | Ikke en autentiseringskomponent. |
Props / API
RadioGroupProps
| Prop | Type | Påkrevd | Standard | Beskrivelse |
|---|---|---|---|---|
legend | string | Ja | Gruppens label. Vises og leses opp av skjermlesere | |
description | string | Nei | Hjelpetekst for hele gruppen | |
errorMessage | string | Nei | Feilmelding. Trigger aria-invalid automatisk når satt | |
name | string | Nei | auto-generert | name-attributtet på alle inputs. Genereres hvis utelatt |
value | string | Nei | Kontrollert modus: hvilket alternativ som er valgt. Bruk sammen med onChange | |
defaultValue | string | Nei | Ukontrollert modus: initiell verdi. Brukeren kan endre fritt | |
onChange | (value: string) => void | Nei | Kalles med ny value når brukeren velger | |
required | boolean | Nei | false | Setter required på alle inputs |
disabled | boolean | Nei | false | Deaktiverer hele gruppen |
readOnly | boolean | Nei | false | Skrivebeskytter hele gruppen |
orientation | 'vertical' | 'horizontal' | Nei | 'vertical' | Layout-orientering |
hideLegend | boolean | Nei | false | Skjuler legend visuelt — leses fortsatt av skjermlesere |
className | string | Nei | CSS-klasse på <ix-radio-group>-rotelementet | |
options | RadioOption[] | Nei* | Liste med alternativer. Snarvei for enkle lister — alternativ til children | |
children | ReactNode | Nei* | RadioButton-elementer. Brukes når du trenger mer kontroll enn options gir |
*Enten options eller children må være satt. Hvis begge er satt, vinner options.
RadioOption
| Felt | Type | Påkrevd | Beskrivelse |
|---|---|---|---|
value | string | Ja | Verdien som settes på input |
label | string | Ja | Synlig labeltekst |
RadioButtonProps
| Prop | Type | Påkrevd | Standard | Beskrivelse |
|---|---|---|---|---|
value | string | Ja | Verdien som settes på input. Brukes for å identifisere alternativet i gruppen | |
label | string | Ja | Synlig labeltekst | |
disabled | boolean | Nei | false | Deaktiverer denne enkelt-knappen (kommer i tillegg til gruppe-disabled) |
className | string | Nei | CSS-klasse på wrapper-div | |
ref | Ref<HTMLInputElement> | Nei | Ref videresendes til <input>-elementet |
I tillegg støttes alle standard HTML input-attributter (name, id, autoFocus, required, defaultChecked, aria-*, osv.) som settes direkte på komponenten — de sendes videre til <input>. value, type, size, children og onChange håndteres av komponenten.
RadioButton er designet for bruk inni RadioGroup. onChange er ikke tilgjengelig som prop fordi endringshåndteringen skjer via gruppen. For standalone radio input, bruk native <input type="radio"> direkte.
Tilpasning med CSS
Inni <ix-radio-group> styles naken <input type="radio"> og <label> automatisk — du trenger ikke skrive klasser. BEM-klassene finnes som hooks for konsumenter som vil bruke radio-styling utenfor <ix-radio-group>.
Tilgjengelige klasser og selektorer
| Element | Selektor |
|---|---|
| Gruppe-wrapper | .ix-radio-group (eller tagnavn ix-radio-group) |
| Legend | [data-field="legend"] |
| Description | [data-field="description"] |
| Items-container | [data-field="items"] |
| Radio-wrapper (utenfor gruppen) | .ix-radio-button |
| Input — visuelt skjult (utenfor gruppen) | .ix-radio-button__input |
| Label med radio-indikator (utenfor gruppen) | .ix-radio-button__label |
| Feilmelding | [data-field="error"] |
| Skjult legend | .ix-sr-only |
Eksempel: bruk i egen HTML-struktur
Inni <ix-radio-group> trengs ingen klasser, og heller ikke id eller for — komponenten kobler input og label automatisk:
<ix-radio-group name="kundetype">
<span data-field="legend">Velg kundetype</span>
<div data-field="items">
<div>
<input type="radio" value="privat" />
<label>Privat</label>
</div>
</div>
<span data-field="error"></span>
</ix-radio-group>
Bygger du radio-styling utenfor <ix-radio-group>, bruk BEM-klassene direkte:
<div class="ix-radio-button">
<input type="radio" class="ix-radio-button__input" id="r-1" name="x" value="1" />
<label class="ix-radio-button__label" for="r-1">Alternativ 1</label>
</div>
Designvalg
Bak komponenten ligger en rekke tekniske valg — om hvorfor vi bruker role="radiogroup" istedenfor <fieldset>, hvordan ARIA og disabled-tilstand synkroniseres, hvorfor RadioButton ikke har sin egen web component, og mer.
Se Designvalg for RadioGroup hvis du er nysgjerrig på avveiningene.
Relatert
- Label — ledetekst for skjemafelt
- Select — for lange lister med mange alternativer
- ValidationMessage — feilmeldingsteksten
- Designvalg for RadioGroup — tekniske avveininger