Tabs
Faner lar brukeren veksle mellom likeverdige innholdsseksjoner på samme side — uten å navigere til en ny side. Bare én seksjon vises om gangen, og en horisontal fane-liste styrer hvilken. Fanene supplerer SegmentedControl, som brukes til gjensidig utelukkende tilstander og filtre.
Egnet til
- Å dele opp relatert innhold i seksjoner der brukeren ser én om gangen
- Detaljvisninger med flere fasetter (oversikt, transaksjoner, innstillinger)
- Å redusere skrolling ved å samle innhold bak likeverdige valg
Uegnet til
- Sekvensielle steg brukeren skal gjennom i rekkefølge — bruk en stegindikator
- Navigasjon mellom sider — bruk lenker eller meny
- Gjensidig utelukkende filtre eller på/av-tilstander — bruk SegmentedControl
- Innhold brukeren må se samtidig — vis det åpent ved siden av hverandre
Kom i gang
Marker start-fanen med defaultValue (i HTML: aria-selected="true" på fanen og hidden på de skjulte panelene). Hver fane kobles til sitt panel via samme value — i HTML med et delt data-value på fanen og panelet. Koblingen følger data-value, ikke rekkefølgen, så fanene og panelene kan stå i vilkårlig orden.
Kode
<Tabs defaultValue="oversikt"> <Tabs.List ariaLabel="Kontoinformasjon"> <Tabs.Tab value="oversikt">Oversikt</Tabs.Tab> <Tabs.Tab value="transaksjoner">Transaksjoner</Tabs.Tab> <Tabs.Tab value="innstillinger">Innstillinger</Tabs.Tab> </Tabs.List> <Tabs.Panel value="oversikt"> <p>Saldo og nøkkeltall for kontoen.</p> </Tabs.Panel> <Tabs.Panel value="transaksjoner"> <p>De siste inn- og utbetalingene.</p> </Tabs.Panel> <Tabs.Panel value="innstillinger"> <p>Navn, varsler og kontoinnstillinger.</p> </Tabs.Panel> </Tabs>
Eksempler
Med ikon
En fane kan ha et ikon foran teksten. Ikonet følger samme tilstandsfarge som teksten (aktiv/passiv) og er kun støtte — teksten er hovedbæreren.
Kode
<Tabs defaultValue="konto"> <Tabs.List ariaLabel="Bankoversikt"> <Tabs.Tab value="konto"> <Icon name="account_balance" /> Konto </Tabs.Tab> <Tabs.Tab value="betalinger"> <Icon name="payments" /> Betalinger </Tabs.Tab> <Tabs.Tab value="sparing"> <Icon name="savings" /> Sparing </Tabs.Tab> </Tabs.List> <Tabs.Panel value="konto"> <p>Oversikt over kontoene dine.</p> </Tabs.Panel> <Tabs.Panel value="betalinger"> <p>Kommende og utførte betalinger.</p> </Tabs.Panel> <Tabs.Panel value="sparing"> <p>Sparemål og renter.</p> </Tabs.Panel> </Tabs>
Kun ikon
Faner uten synlig tekst må ha et tilgjengelig navn (på brukerens språk) — ellers får skjermlesere ingen fane-etikett. I HTML settes det med aria-label på fanen; i React med ariaLabel.
Kode
<Tabs defaultValue="hjem"> <Tabs.List ariaLabel="Navigasjon"> <Tabs.Tab value="hjem" ariaLabel="Hjem"> <Icon name="home" /> </Tabs.Tab> <Tabs.Tab value="profil" ariaLabel="Profil"> <Icon name="person" /> </Tabs.Tab> <Tabs.Tab value="innstillinger" ariaLabel="Innstillinger"> <Icon name="settings" /> </Tabs.Tab> </Tabs.List> <Tabs.Panel value="hjem"> <p>Hjem-innhold.</p> </Tabs.Panel> <Tabs.Panel value="profil"> <p>Profil-innhold.</p> </Tabs.Panel> <Tabs.Panel value="innstillinger"> <p>Innstillinger-innhold.</p> </Tabs.Panel> </Tabs>
Retningslinjer
Innhold og formulering
- Skriv korte, beskrivende fane-etiketter som gir mening lest alene.
- Start med det viktigste ordet — lista skal være lett å skanne.
- Bruk konsistent nivå på etikettene (f.eks. alle substantiv) i samme fane-sett.
Manuell aktivering
Å flytte fokus mellom faner med piltast bytter ikke panel automatisk — brukeren aktiverer den fokuserte fanen med Enter eller Mellomrom (eller klikk). Det gir forutsigbar oppførsel og unngår at skjermleserbrukere hopper gjennom flere paneler ved ren navigasjon.
Mange faner
Ved plassmangel scroller fane-lista horisontalt i én rad — rekkefølgen bevares og siden får ingen horisontal scroll. Har du svært mange seksjoner, vurder om innholdet heller bør deles på flere sider.
Kontrollert og ukontrollert
I React kan Tabs være ukontrollert (defaultValue — web componenten eier videre tilstand) eller kontrollert (value + onChange — React eier tilstanden). Bruk kontrollert modus når valgt fane må styres utenfra, f.eks. synkronisert med URL.
function Konto() {
const [fane, setFane] = useState('oversikt');
return (
<Tabs value={fane} onChange={setFane}>
<Tabs.List ariaLabel="Kontoinformasjon">
<Tabs.Tab value="oversikt">Oversikt</Tabs.Tab>
<Tabs.Tab value="transaksjoner">Transaksjoner</Tabs.Tab>
</Tabs.List>
<Tabs.Panel value="oversikt">…</Tabs.Panel>
<Tabs.Panel value="transaksjoner">…</Tabs.Panel>
</Tabs>
);
}
Props
Props-tabellen genereres automatisk fra Storybook (tags: ['autodocs']).
Tilpasning med CSS
Trenger du ix-tabs-stylingen på HTML du setter sammen selv — uten React-komponenten — kan du bruke klassene direkte. Web componenten <ix-tabs> kobler roller, aria-controls, roving tabindex, tastatur og panel-visning ved mount; du skriver semantisk markup, gir hver fane og sitt panel et delt data-value, og markerer start-fanen med aria-selected="true" og de skjulte panelene med hidden.
Tilgjengelige klasser og selektorer
| Element/tilstand | Selektor / attributt |
|---|---|
| Rot | .ix-tabs på <ix-tabs> |
| Fane-liste (tablist) | .ix-tabs__list på <ix-tab-list> |
| Enkelt-fane | .ix-tabs__tab på <ix-tab> |
| Fane↔panel-kobling | delt data-value på <ix-tab> og <ix-tab-panel> |
| Aktiv fane | [aria-selected="true"] på fanen |
| Innholdspanel | .ix-tabs__panel på <ix-tab-panel> |
| Skjult panel | [hidden] på panelet (native) |
Understreken er synlig i alle tilstander og markerer tilstand med farge: passiv bruker --ix-color-border-main-default, hover --ix-color-border-main-hover og aktiv --ix-color-fill-main-default (brand-farge). Passiv fane-tekst bruker --ix-color-foreground-main-subtle, aktiv/hover-tekst --ix-color-foreground-main-default. Overstyr disse tokenene for å tilpasse fargene.
Eksempel: ren HTML
<ix-tabs class="ix-tabs">
<ix-tab-list class="ix-tabs__list" aria-label="Kontoinformasjon">
<ix-tab class="ix-tabs__tab" data-value="oversikt" aria-selected="true">Oversikt</ix-tab>
<ix-tab class="ix-tabs__tab" data-value="detaljer" aria-selected="false">Detaljer</ix-tab>
</ix-tab-list>
<ix-tab-panel class="ix-tabs__panel" data-value="oversikt">
<p>Innhold for oversikt.</p>
</ix-tab-panel>
<ix-tab-panel class="ix-tabs__panel" data-value="detaljer" hidden>
<p>Innhold for detaljer.</p>
</ix-tab-panel>
</ix-tabs>
Universell utforming
Hva du selv må sørge for
- Gi kun-ikon-faner et
ariaLabel— en fane uten synlig tekst trenger et tilgjengelig navn på brukerens språk. Komponenten har ingen hardkodet fallback. - Merk fane-settet med
ariaLabelpåTabs.Listnår flere uavhengige fane-sett finnes på samme side, så skjermleserbrukere kan skille dem. - Skriv korte, beskrivende etiketter som beskriver innholdet i tilhørende panel og gir mening lest alene.
- Bruk faner til likeverdig innhold — ikke til sekvensielle steg (bruk stegindikator) eller navigasjon mellom sider (bruk lenker).
Hva komponenten gjør automatisk
- Roller og relasjoner — web componenten setter
role="tablist"/"tab"/"tabpanel",aria-selected,aria-controls(fane → panel) ogaria-labelledby(panel → fane) ved mount. Ingen ekstra ARIA er nødvendig. - Tastaturnavigasjon (manuell aktivering) — roving
tabindexgir én tab-stopp; pil venstre/høyre flytter fokus, Home/End går til første/siste, og Enter/Mellomrom aktiverer. - Tilstand annonseres — aktiv fane formidles av
aria-selected, ikke av farge alene. - Fokusindikator — tydelig fokusring rundt hele fanen (
:focus-visible); tablisten reserverer vertikal plass så ringen ikke klippes av scroll-containeren. - Reflow og touch-mål — fane-lista scroller horisontalt ved plassmangel (siden får ingen horisontal scroll ned til 320 px), og hver fane har min. 44×44 px touch-mål.
- Redusert bevegelse — indikator-overgangen respekterer
prefers-reduced-motion: reduce.
Tastaturnavigasjon
| Tast | Handling |
|---|---|
| Tab | Flytter fokus inn i tablisten (til aktiv fane) og videre ut til første fokuserbare element etter tablisten — kun én tab-stopp i tablisten. Panelet er ikke en egen tab-stopp. |
| Shift+Tab | Flytter fokus til forrige fokuserbare element |
| Pil venstre / Pil høyre | Flytter fokus til forrige/neste fane, looper rundt endene (aktiverer ikke) |
| Home | Flytter fokus til første fane |
| End | Flytter fokus til siste fane |
| Enter | Aktiverer den fokuserte fanen og viser tilhørende panel |
| Space | Aktiverer den fokuserte fanen og viser tilhørende panel |
Skjermleser
- Ved fokus på en fane: «[etikett], fane, valgt/ikke valgt, [posisjon] av [antall]»
- Å aktivere en fane bytter det synlige panelet uten å flytte fokus bort fra fanen; panelet er programmessig knyttet til fanen via aria-controls/aria-labelledby
WCAG-kriterier
Sist gjennomgått: 2026-07-23 — alle 56 WCAG 2.2-kriterier vurdert
WCAG-kriterier5 ditt ansvar · 16 håndtert · 36 ikke relevant · 0 ikke på plass
Ditt ansvar (5)
| Kriterium | Nivå | Hva du må gjøre |
|---|---|---|
| 4.1.2 Navn, rolle, verdi | A | Gi kun-ikon-faner et tilgjengelig navn med ariaLabel. En fane som bare inneholder et ikon har ingen synlig tekst skjermlesere kan lese. Sett `ariaLabel` på `Tabs.Tab` (i HTML: `aria-label` på `<ix-tab>`) med en kort, beskrivende etikett på brukerens språk (bokmål, nynorsk eller engelsk). Komponenten har ingen hardkodet fallback. |
| 2.4.4 Formål med lenke (i kontekst) | A | Gi kun-ikon-faner et tilgjengelig navn med ariaLabel. En fane som bare inneholder et ikon har ingen synlig tekst skjermlesere kan lese. Sett `ariaLabel` på `Tabs.Tab` (i HTML: `aria-label` på `<ix-tab>`) med en kort, beskrivende etikett på brukerens språk (bokmål, nynorsk eller engelsk). Komponenten har ingen hardkodet fallback. |
| 1.3.1 Informasjon og relasjoner | A | Merk fane-settet med ariaLabel når flere finnes på samme side. Har siden flere uavhengige fane-sett, gi hver `Tabs.List` et eget `ariaLabel` (i HTML: `aria-label` på `<ix-tab-list>`) slik at skjermleserbrukere kan skille dem fra hverandre. Teksten er i18n-ansvaret til konsumenten. |
| 2.4.6 Overskrifter og ledetekster | AA | Skriv korte, beskrivende fane-etiketter. Fane-etiketten skal gi mening lest alene og beskrive innholdet i tilhørende panel. Hold den kort så lista kan skannes raskt. Et valgfritt prefiks-ikon støtter forståelsen, men teksten er hovedbæreren. |
| 1.3.1 Informasjon og relasjoner | A | Bruk faner til likeverdig innhold — ikke steg eller navigasjon. Faner er for å veksle mellom likeverdige innholdsseksjoner på samme side. Bruk dem ikke for sekvensielle steg (bruk en stegindikator) eller for navigasjon mellom sider (bruk lenker). Feil bruk gir skjermleserbrukere misvisende semantikk. |
Håndtert av komponenten (16)
| Kriterium | Nivå | Hva komponenten gjør |
|---|---|---|
| 1.3.1 Informasjon og relasjoner | A | Web componenten kobler `role="tablist"`/`"tab"`/`"tabpanel"`, `aria-selected`, `aria-controls` (tab → panel) og `aria-labelledby` (panel → tab) ved mount. Relasjonene er dermed programmessig eksponert, ikke bare visuelle. |
| 1.3.2 Meningsfull rekkefølge | A | Innhold følger naturlig leserekkefølge i DOM: tablist først, deretter det synlige panelet. Skjulte paneler har native `hidden` og er tatt ut av leserekkefølgen. |
| 1.4.1 Bruk av farge | A | Aktiv fane formidles av `aria-selected` (annonseres av skjermleser) i tillegg til understrek-indikatoren — ikke av farge alene. |
| 1.4.3 Kontrast (minimum) | AA | Fane-tekst bruker `--ix-color-foreground-main-default` (aktiv) og `--ix-color-foreground-main-subtle` (passiv) mot `--ix-color-surface-main`, som oppfyller kontrastkravet i både lys og mørk modus. |
| 1.4.4 Endre tekststørrelse | AA | Relative enheter (font-size-tokens) — tekst skalerer korrekt ved 200 % zoom uten at innhold brytes. |
| 1.4.10 Omflyt | AA | Ved plassmangel scroller kun tablisten horisontalt (én rad, bevart rekkefølge); siden får ingen horisontal scroll. Reflower korrekt ned til 320 px viewport. |
| 1.4.11 Kontrast for ikke-tekstlig innhold | AA | Fokusindikatoren på fanene oppfyller 3:1 kontrastkrav via `--ix-outline-default`. Aktiv-indikatoren (understreken) bruker brand-fargen `--ix-color-fill-main-default`; passiv/hover-understrek bruker `--ix-color-border-main-default`/`--ix-color-border-main-hover`. |
| 2.1.1 Tastatur | A | Full tastaturstøtte: Tab inn/ut av tablisten (roving tabindex — kun én tab-stopp), pil venstre/høyre flytter fokus mellom faner, Home/End til første/siste, Enter/Mellomrom aktiverer fokusert fane. |
| 2.1.2 Ingen tastaturfelle | A | Ingen tastaturfeller — fokus navigeres fritt ut av tablisten med Tab/Shift+Tab. |
| 2.4.3 Fokusrekkefølge | A | Roving tabindex gir én tab-stopp for hele tablisten; fokusrekkefølgen følger DOM: tablist før panel. |
| 2.4.7 Synlig fokus | AA | Tydelig fokusindikator rundt hele fanen (`:focus-visible`); tablisten reserverer vertikal plass (`padding-block`) så ringen ikke klippes av scroll-containeren. |
| 2.3.3 2.3.3 | ? | Overgangen på aktiv-indikatoren respekterer `prefers-reduced-motion: reduce` — transition settes til `none`. |
| 2.5.8 Målstørrelse (minimum) | AA | Hver fane har min. 44×44 px klikk-/touch-mål via `min-height`/`min-width` + padding. |
| 3.2.1 Ved fokus | A | Ingen kontekstendring ved fokus. Manuell aktivering: å flytte fokus mellom faner med piltast bytter ikke panel før brukeren trykker Enter/Mellomrom. |
| 3.2.2 Ved inndata | A | Å aktivere en fane gjør kun det forventede (viser tilhørende panel) — ingen automatisk kontekstendring eller navigasjon. |
| 4.1.2 Navn, rolle, verdi | A | Roller, navn og tilstand (`aria-selected`) eksponeres korrekt via ARIA satt av web componenten. Aktiv/valgt fane annonseres til skjermlesere. |
Ikke relevant (36)
| Kriterium | Nivå | Hvorfor ikke relevant |
|---|---|---|
| 1.1.1 Ikke-tekstlig innhold | A | Komponenten har ikke eget bildeinnhold. Et valgfritt prefiks-ikon i en fane er konsumentens ansvar (Icon-komponenten håndterer alt-tekst/aria-hidden), og kun-ikon-faner krever `ariaLabel` (se konsumentansvar). |
| 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 | Formidler ikke instruksjoner basert på sensoriske egenskaper. |
| 1.3.4 Visningsretning | AA | Ingen fast orientering — tilpasser seg visningsretning. |
| 1.3.5 Identifiser formål med inndata | AA | Ikke et skjemafelt som ber om personlig informasjon. |
| 1.4.2 Styring av lyd | A | Ingen lydelementer. |
| 1.4.5 Bilder av tekst | AA | Ingen bilder av tekst. |
| 1.4.12 Tekstavstand | AA | |
| 1.4.13 Innhold ved hover eller fokus | AA | |
| 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 | Indikator-overgangen er kort, respekterer prefers-reduced-motion og blinker ikke. |
| 2.4.1 Hoppe over blokker | A | Sidekrav — gjelder ikke enkeltkomponenter. |
| 2.4.2 Sidetitler | A | Sidekrav — gjelder ikke enkeltkomponenter. |
| 2.4.5 Flere måter | AA | Sidekrav — gjelder ikke enkeltkomponenter. |
| 2.5.1 Pekerbevegelser | A | Ingen gestbaserte interaksjoner — enkelt klikk/tap eller tastatur. |
| 2.5.2 Avbryt peker | A | Aktivering skjer på pekeropp; et klikk kan avbrytes ved å dra bort før slipp. |
| 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.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.1 Identifikasjon av feil | A | |
| 3.3.2 Ledetekster eller instruksjoner | A | |
| 3.3.3 Forslag ved feil | AA | |
| 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. |