Uansett valg deler vi aldri dine data med andre. Mer om informasjonskapsler på aksel.nav.no

  • Godta alle: Hjelper oss gjøre tjenestene bedre for deg basert på anonymisert bruk.
  • Bare nødvendige: Sikrer at tjenesten fungerer og er trygg. Kan ikke velges bort.
Hopp til innhold
Aksel

Søk

Ctrl+K for å søkeEsc for å lukke

Aksel

Designsystemet
God praksisBloggen

Komponenter

Modal

En modal er et midlertidig vindu som åpnes på en nettside. Modalen fanger brukerens oppmerksomhet, samtidig som konteksten til nettsiden beholdes. Den er nyttig når brukeren må ta stilling til informasjon eller fokusere på en spesifikk oppgave.

StabilOppdatert 9. mai 2025

Egnet til:

  • Å få brukeren til å fokusere på en spesifikk oppgave
  • Å sikre at brukeren får med seg viktig informasjon

Uegnet til:

  • Omfattende eller komplekst innhold som krever langvarig interaksjon
  • Informasjon som brukeren må ha tilgang til kontinuerlig

Eksempler

Sandbox
Åpne eksempel i nytt vindu
TSX
<div className="py-16">
<Button onClick={() => ref.current?.showModal()}>Åpne modal</Button>
<Modal ref={ref} header={{ heading: "Overskrift" }}>
<Modal.Body>
<BodyLong>
Culpa aliquip ut cupidatat laborum minim quis ex in aliqua. Qui
incididunt dolor do ad ut. Incididunt eiusmod nostrud deserunt duis
laborum. Proident aute culpa qui nostrud velit adipisicing minim.
Consequat aliqua aute dolor do sit Lorem nisi mollit velit. Aliqua
exercitation non minim minim pariatur sunt laborum ipsum. Exercitation
nostrud est laborum magna non non aliqua qui esse.
</BodyLong>
</Modal.Body>
<Modal.Footer>
<Button type="button" onClick={() => ref.current?.close()}>
Primær
</Button>
<Button
type="button"
variant="secondary"
onClick={() => ref.current?.close()}
>
Sekundær
</Button>
<Button
type="button"
variant="tertiary"
onClick={() => ref.current?.close()}
>
Tertiær
</Button>
</Modal.Footer>
</Modal>
</div>

Modal på mobil

Under brekkpunktet sm (768px) fjernes margene på modalen slik at hele viewporten utnyttes.

Retningslinjer

Design

Modal er bygd opp i 3 deler: header, body og footer.

Illustrasjon av modalens tre deler

Header

Det er mulig å tilpasse innholdet i headeren. Du kan vise et ikon, optional label og lukk-knapp.

Body

Body er hovedinnholdet i modalen.

Footer

Kan inneholde en primær-, en sekundær- og en tertiærknapp. Primærknapp ligger helt til høyre i footeren. Ved bruk av to knapper brukes primær- og sekundærknapp. Hvis du trenger tre knapper plasseres tertiærknappen til venstre.

Bruk

  • Begrens bruk av modaler.
  • Ikke bruk mer enn tre knapper.
  • Sørg for at formålet er tydelig og at all nødvendig informasjon er tilgjengelig i modalen.
  • Ikke bruk modal når det kreves navigering mellom flere trinn.

Innhold

  • Tittelen bør alltid være med for å tydeliggjøre for brukeren at konteksten er endret. For skjermleserbrukere er dette ekstra viktig fordi de ikke vil se det som ligger utenfor modalen.
  • Hold innholdet kortfattet og fokusert. Bruk overskrifter, underoverskrifter og punktlister for å gjøre innholdet skannbart.

Lukke modal

Sørg for at det alltid er en synlig og enkel måte å lukke modalen på. Det vanligste er å ha en lukk-knapp øverst til høyre. Hvis det ikke passer må du ha en annen knapp i modalen som kan brukes til å lukke den, for eksempel en avbryt-knapp.

Automatisk testing

Modalen har en kort animasjon når den åpnes, som du kanskje må ta høyde for i automatiske tester. Du kan f.eks. legge på en liten forsinkelse, eller aktivere "prefers-reduced-motion" hvis testmiljøet støtter dette.

Tilgjengelighet

Tilgjengelig navn

Hvis du bruker header-propen vil modalen automatisk få aria-labelledby knyttet opp mot header.heading. Hvis du ikke bruker header-propen må du huske å sette enten aria-label eller aria-labelledby selv. Se eksempel "Custom header".

Fokushåndtering

Fokus skal flyttes inn i modalen når den åpnes, og tilbake når den lukkes. Dette hånteres i de fleste tilfeller automatisk. Modalen bruker dialog-elementet, hvor standard oppførsel er at første fokuserbare element får fokus når modalen åpnes. Siden dette ofte vil være lukk-knappen, har vi valgt å sette autoFocusdialog-elementet, slik at det elementet får fokus i stedet. I skrivende stund fungerer dette imidlertid bare i Firefox.

Når modalen lukkes, flyttes fokus tilbake der det var da modalen ble åpnet. Hvis dette elementet ikke finnes lenger, kan det være hensiktsmessig å manuelt sette fokus på det neste elementet. Fokus kan bare settes utenfor modalen etter at den er lukket. Hvis du lukker modalen ved hjelp av open-propen vil det gå en render-syklus før den lukkes. I så fall kan du for eksempel sette fokus i onClose.

Interaksjon med tastatur

Modalen kan som standard lukkes med Escape-tasten. Dette kan i noen tilfeller overstyres slik: onCancel={(e) => e.preventDefault()}. Se Props/JSDoc for mer info.

Tab-rekkefølge

Legg merke til at elementene i footer vises i motsatt rekkefølge. Dette er for at primærknappen skal komme til høyre og samtidig være først i tab-rekkefølgen.

Sideskroll

Når modalen åpnes, settes det en klasse på body-elementet med CSSen overflow: hidden for å hindre at resten av siden kan skrolles. For å unngå at innholdet flytter på seg når scrollbaren skjules/vises kan du bruke scrollbar-gutter: stable.

Figma

I Figma er komponenten designet med en slot-komponent som gjør det mulig å legge til eget innhold samtidig som variantene bevares.

Bytte ut innhold i Figma

Props

Modal

size?

  • Type:
    "small" | "medium"
  • Default:
    "null"
  • Description:

    Affects internal padding

header?

  • Type:
    { label?: string; icon?: ReactNode; heading: string; size?: "small" | "medium"; closeButton?: boolean | undefined; } | undefined
  • Description:

    Content for the header. Alteratively you can use <Modal.Header> instead for more control, but then you have to set aria-label or aria-labelledby on the modal manually.

children

  • Type:
    ReactNode
  • Description:

    Modal content.

open?

  • Type:
    boolean
  • Description:

    Whether the modal should be visible or not. Remember to use the onClose callback to keep your local state in sync. You can also use ref.current.openModal() and ref.current.close().

onClose?

  • Type:
    ReactEventHandler<HTMLDialogElement>
  • Description:

    Called when the modal has been closed

onBeforeClose?

  • Type:
    (() => boolean)
  • Description:

    Called when the user tries to close the modal by one of the built-in methods. Used if you want to ask the user for confirmation before closing. @warning Will not always be called when pressing Esc. See onCancel for more info.

onCancel?

  • Type:
    ReactEventHandler<HTMLDialogElement>
  • Description:

    Sometimes* called when the user presses the Esc key.

    *: Some browsers does not always trigger this event. Chrome only triggers it if you have interacted with the modal, and will not trigger it a second time if you press Esc twice in a row.

closeOnBackdropClick?

  • Type:
    boolean
  • Default:
    false
  • Description:

    Whether to close when clicking on the backdrop. @warning Users may click outside by accident. Don't use if closing can cause data loss, or the modal contains important info.

width?

  • Type:
    number | "small" | "medium" | `${number}${string}`
  • Default:
    fit-content (up to 700px)

placement?

  • Type:
    "top" | "center"
  • Default:
    ""center""
  • Description:

    Where to place the modal in the viewport. (Will always be centered on mobile and old browsers.)

portal?

  • Type:
    boolean
  • Description:

    Lets you render the modal into a different part of the DOM. Will use rootElement from Provider if defined, otherwise document.body.

className?

  • Type:
    string
  • Description:

    User defined classname for modal

aria-labelledby?

  • Type:
    string
  • Description:

    ID of the element that labels the modal. No need to set this manually if the header prop is used. A reference to header.heading will be created automatically. @warning If not using header, you should set either aria-labelledby or aria-label.

aria-label?

  • Type:
    string
  • Description:

    String value that labels the modal. No need to set this if the header prop is used. @warning If not using header, you should set either aria-labelledby or aria-label.

data-color?

  • Type:
    (string & {}) | AkselColor

ref?

  • Type:
    LegacyRef<HTMLDialogElement>
  • Description:

    Allows getting a ref to the component instance. Once the component unmounts, React will set ref.current to null (or call the ref with null if you passed a callback ref). React Docs

Modal.Header

closeButton?

  • Type:
    boolean
  • Default:
    true
  • Description:

    Removes close-button (X) when false

className?

  • Type:
    string

data-color?

  • Type:
    (string & {}) | AkselColor

ref?

  • Type:
    LegacyRef<HTMLDivElement>
  • Description:

    Allows getting a ref to the component instance. Once the component unmounts, React will set ref.current to null (or call the ref with null if you passed a callback ref). React Docs

Modal.Body

className?

  • Type:
    string

data-color?

  • Type:
    (string & {}) | AkselColor

ref?

  • Type:
    LegacyRef<HTMLDivElement>
  • Description:

    Allows getting a ref to the component instance. Once the component unmounts, React will set ref.current to null (or call the ref with null if you passed a callback ref). React Docs

Modal.Footer

className?

  • Type:
    string

data-color?

  • Type:
    (string & {}) | AkselColor

ref?

  • Type:
    LegacyRef<HTMLDivElement>
  • Description:

    Allows getting a ref to the component instance. Once the component unmounts, React will set ref.current to null (or call the ref with null if you passed a callback ref). React Docs

Tokens

For å bruke --ac-modal-backdrop må du ha med pseudo-elementet ::backdrop til slutt i selektoren.

Deprecation warning: I det nye systemet for theming og darkmode, er komponent-tokens fjernet. Mer dokumentasjon for dette kommer, midlertidig dokumentasjon finner du her.

TokenFallback
--ac-modal-bg--a-surface-default
--ac-modal-backdrop--a-surface-backdrop
--ac-modal-width-small450px
--ac-modal-width-medium700px