Skip to main content

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

Bruk

Laster...

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. onChange er event-basert (verdien ligger i event.target.value), slik at et {...register('felt')} fra React Hook Form kan spres rett på komponenten, se Form-validering:

const [kundetype, setKundetype] = useState<string>('privat');

<RadioGroup
legend="Velg kundetype"
name="kundetype"
value={kundetype}
onChange={(event) => setKundetype(event.target.value)}
options={[
{ value: 'privat', label: 'Privat' },
{ value: 'bedrift', label: 'Bedrift' },
{ value: 'annet', label: 'Annet' },
]}
/>

Trenger du deaktiverte alternativer, egne id-er eller en ref, bruker du RadioButton-barn i stedet:

Laster...

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.

TODO – diskuter
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 utløses fra siden. Du må slå den på i nettleseren for å se den faktiske visningen.

Chromium (Chrome, Edge, Brave):

  1. Åpne DevTools (F12 eller Ctrl+Shift+I).
  2. Ctrl+Shift+P → skriv "Show Rendering" → Enter.
  3. I Rendering-panelet, scroll til Emulate CSS media feature forced-colors og velg active.
  4. Kombiner gjerne med Emulate CSS media feature prefers-color-scheme = dark for å sjekke høykontrast på mørk bakgrunn.

Firefox:

  1. about:config → sett ui.systemUsesDarkTheme = 1 og browser.display.document_color_use = 2.
  2. Last siden på nytt.

Windows 11 (ekte HCM):

  • Innstillinger → Tilgjengelighet → Kontrasttemaer → velg f.eks. Aquatic eller Nattlig.
  • Hurtigtast: Venstre Alt + Venstre Shift + Print Screen veksler.

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.

Laster...

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.

Laster...

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.

Laster...

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.

Laster...

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.

Laster...

Retningslinjer

Bruk radioknapper bare i gruppe

En radioknapp alene har ingen mening: poenget er at valget utelukker de andre. Gruppen trenger en legend som sier hva som velges, for eksempel "Kundetype".

Vis alle alternativene samtidig

Radioknapper er til for å sammenlignes. Brukeren skal se alle valgene før hen bestemmer seg, uten å åpne noe. Er listen for lang til det, bruk Select eller Combobox i stedet.

Bruk vertikal orientering

Én kolonne er enklest å skanne, tåler zoom og brekker ikke på smal skjerm. Horisontal rekke fungerer bare for to eller tre korte alternativer, som "Ja" og "Nei".

Sorter uten å styre valget

Logisk eller alfabetisk rekkefølge er utgangspunktet. Skal det anbefalte valget ligge først, gjør det med åpne øyne: alternativet øverst blir valgt oftere enn de andre.

Bruk forhåndsvalg med omtanke

Et forhåndsvalgt alternativ sparer tid i skjemaer der svaret er opplagt for de fleste. Det koster også noe: brukeren kan sende inn et forhåndsvalg uten å ha tenkt over det. Sett det bare når standardvalget er trygt å bli sittende med.

Designvalg

RadioGroup bruker role="radiogroup" framfor <fieldset>, og RadioButton har ingen egen web component: gruppen setter opp ARIA og disabled for alle inputs under seg.

Designvalg for RadioGroup forklarer hvorfor.

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: errorMessage viser feilen, men teksten er ditt ansvar
  • Vurder disabled med omtanke. Et deaktivert alternativ er ofte vanskelig å forstå
  • Sett required nå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 riktig
  • aria-labelledby til legend-elementet: gruppens tilgjengelige navn
  • aria-describedby til description og error: leses etter legend
  • aria-live="polite" på error-elementet slik at endringer kunngjøres uten å avbryte
  • aria-invalid på containeren og alle inputs synkroniseres med error-innholdet via MutationObserver
  • Felles name på alle inputs: sikrer mutual exclusivity (kun ett valg av gangen) og ArrowKey-navigasjon
  • htmlFor/id mellom hver label og input: klikk på label velger alternativet
  • disabled/readonly propagerer fra container til alle inputs

Tastaturnavigasjon

TastHandling
TabFlytter fokus til den valgte radioknappen i gruppen, eller til første radioknapp om ingen er valgt
Pil ned / Pil høyreFlytter fokus og valg til neste alternativ i gruppen
Pil opp / Pil venstreFlytter fokus og valg til forrige alternativ i gruppen
SpaceVelger 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)
KriteriumNivåHva du må gjøre
1.3.1 Informasjon og relasjonerASkriv 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 ledeteksterAASkriv 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 instruksjonerASkriv 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 instruksjonerASkriv 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 feilASkriv 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 feilAASkriv 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 instruksjonerAVurder 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 instruksjonerASett 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)
KriteriumNivåHva komponenten gjør
1.3.1 Informasjon og relasjonerAix-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 fargeASelected state vises både med fylt sirkel (form) og endret farge — ikke kun farge.
1.4.3 Kontrast (minimum)AATekst 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 OmflytAAReflower korrekt ned til 320 px. Horisontal orientering bryter til vertikal ved smal skjerm via media query.
1.4.11 Kontrast for ikke-tekstlig innholdAARadio-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 TekstavstandAABruker --ix-font-size-md (relativ enhet) og tåler økt line-height, bokstav- og ordavstand uten tap av innhold.
2.1.1 TastaturANative 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 fokusAA: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)AAKlikkeflaten på 44×44 px oppfyller WCAG 2.2 AA-kravet (24×24 px) med god margin.
3.3.1 Identifikasjon av feilAix-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 feilAAerrorMessage-propen brukes til å gi konkret feilmelding. Komponenten viser den, men teksten er konsumentens ansvar.
4.1.2 Navn, rolle, verdiANative input[type="radio"] gir rolle, navn (via label) og verdi automatisk. role="radiogroup" på containeren grupperer dem.
4.1.3 StatusmeldingerAAix-radio-group setter aria-live="polite" på error-elementet slik at skjermlesere annonserer endringer i feilmeldingen uten å avbryte brukeren.
Ikke relevant (39)
KriteriumNivåHvorfor ikke relevant
1.1.1 Ikke-tekstlig innholdA
1.2.1 Bare lyd og bare video (forhåndsinnspilt)AIngen medieelementer.
1.2.2 Teksting (forhåndsinnspilt)AIngen medieelementer.
1.2.3 Synstolking eller mediealternativ (forhåndsinnspilt)AIngen medieelementer.
1.2.4 Teksting (direkte)AAIngen medieelementer.
1.2.5 Synstolking (forhåndsinnspilt)AAIngen medieelementer.
1.3.3 Sensoriske egenskaperA
1.3.4 VisningsretningAAIngen fast orientering — tilpasser seg visningsretning.
1.3.5 Identifiser formål med inndataAARadioGroup samler ikke standardiserte personopplysninger som dekkes av autocomplete-token.
1.4.2 Styring av lydAIngen lydelementer.
1.4.4 Endre tekststørrelseAA
1.4.5 Bilder av tekstAAIngen bilder av tekst.
1.4.13 Innhold ved hover eller fokusAA
2.1.2 Ingen tastaturfelleA
2.1.4 TastatursnarveierAIngen egendefinerte tastatursnarveier.
2.2.1 Justerbar hastighetAIngen tidsbegrensede funksjoner.
2.2.2 Pause, stopp, skjulAIngen animasjon eller automatisk oppdatering.
2.3.1 Terskelverdi på tre glimtAIngen blinkende eller glimtende innhold.
2.4.1 Hoppe over blokkerASidekrav — gjelder ikke enkeltkomponenter.
2.4.2 SidetitlerASidekrav — gjelder ikke enkeltkomponenter.
2.4.3 FokusrekkefølgeA
2.4.4 Formål med lenke (i kontekst)AIngen lenker i komponenten.
2.4.5 Flere måterAASidekrav — gjelder ikke enkeltkomponenter.
2.4.11 Fokus ikke skjult (minimum)AAIngen sticky/overlappende elementer som kan skjule fokus.
2.5.1 PekerbevegelserAIngen drag-and-drop eller sveipebevegelser.
2.5.2 Avbryt pekerA
2.5.4 BevegelsesaktiveringAIngen bevegelsesbasert interaksjon.
2.5.6 Samtidige inndatamekanismerA
2.5.7 DrabevegelserAIngen drag-and-drop.
3.1.1 Språk på sidenASidekrav — gjelder ikke enkeltkomponenter.
3.1.2 Språk på deler av innholdAAKomponenten setter ikke lang-attributt — innhold er på sidespråket.
3.2.1 Ved fokusA
3.2.2 Ved inndataA
3.2.3 Konsistent navigasjonAASidekrav — gjelder ikke enkeltkomponenter.
3.2.4 Konsistent identifikasjonAASystemkrav — gjelder konsistens på tvers av sider, ikke enkeltkomponenter.
3.2.6 Konsistent hjelpASidekrav — gjelder plassering av hjelpefunksjon på tvers av sider.
3.3.4 Forhindring av feil (juridisk, økonomisk, data)AAFlytkrav — gjelder bekreftelse/reversering av transaksjoner, ikke enkeltfelter.
3.3.7 Redundant oppføringAFlytkrav — gjelder at brukeren ikke skal gjenta informasjon i en prosess.
3.3.8 Tilgjengelig autentisering (minimum)AAIkke en autentiseringskomponent.

Props / API

RadioGroupProps

PropTypePåkrevdStandardBeskrivelse
legendstringJaGruppens label. Vises og leses opp av skjermlesere
descriptionstringNeiHjelpetekst for hele gruppen
errorMessagestringNeiFeilmelding. Trigger aria-invalid automatisk når satt
namestringNeiauto-generertname-attributtet på alle inputs. Genereres hvis utelatt
valuestringNeiKontrollert modus: hvilket alternativ som er valgt. Bruk sammen med onChange
defaultValuestringNeiUkontrollert modus: initiell verdi. Brukeren kan endre fritt
onChangeChangeEventHandler<HTMLInputElement>NeiEvent-basert. Kalles med det native change-eventet — valgt verdi ligger i event.target.value. Lar {...register()} spres rett på
onBlurFocusEventHandler<HTMLInputElement>NeiVideresendes til hver input (RHF touched-state ved mode: 'onBlur')
refRef<HTMLInputElement>NeiRutes ned på hver native radio-input. RHF akkumulerer dem og eier checked (register-modus)
requiredbooleanNeifalseSetter required på alle inputs
disabledbooleanNeifalseDeaktiverer hele gruppen
readOnlybooleanNeifalseSkrivebeskytter hele gruppen
orientation'vertical' | 'horizontal'Nei'vertical'Layout-orientering
hideLegendbooleanNeifalseSkjuler legend visuelt — leses fortsatt av skjermlesere
classNamestringNeiCSS-klasse på <ix-radio-group>-rotelementet
optionsRadioOption[]Nei*Liste med alternativer. Snarvei for enkle lister — alternativ til children
childrenReactNodeNei*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.

I tillegg sendes øvrige HTML-attributter (id, tabIndex, role, aria-*, data-*, osv.) videre til <ix-radio-group>-rotelementet. Det er id + tabIndex={-1} som gjør at en feiloppsummering kan lenke til gruppen: rotelementet har role="radiogroup", så skjermleseren leser legend og feilmelding når fokus lander der.

<RadioGroup legend="Er du privat- eller bedriftskunde?" id="kundetype" tabIndex={-1}/>

// og i feiloppsummeringen:
<a href="#kundetype">Velg om du er privat- eller bedriftskunde</a>

To unntak:

  • aria-describedby kommer ikke gjennom. <ix-radio-group> eier den (den peker på description og feilmeldingen) og overskriver verdien du sender inn. Trenger du ekstra hjelpetekst, bruk description.
  • data-state, data-variant, data-size, data-orientation, disabled, readonly og required kan ikke overstyres — de utledes av propene med samme navn.

RadioOption

FeltTypePåkrevdBeskrivelse
valuestringJaVerdien som settes på input
labelstringJaSynlig labeltekst

RadioButtonProps

PropTypePåkrevdStandardBeskrivelse
valuestringJaVerdien som settes på input. Brukes for å identifisere alternativet i gruppen
labelstringJaSynlig labeltekst
disabledbooleanNeifalseDeaktiverer denne enkelt-knappen (kommer i tillegg til gruppe-disabled)
classNamestringNeiCSS-klasse på wrapper-div
refRef<HTMLInputElement>NeiRef 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 og sendes videre til <input>. value, type, size, children og onChange håndteres av komponenten.

RadioButton er laget for bruk inne i RadioGroup. Den har ingen onChange-prop, fordi gruppen håndterer endringene. Trenger du én enkeltstående radioknapp, 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

ElementSelektor
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> kobler komponenten input og label automatisk, så du trenger verken klasser, id eller for:

<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>

Relatert