Maler
Temabytte
NyOppdatert 27. januar 2026
Retningslinjer og tips til hvordan du kan støtte temabytte i appen din.
Eksempler
Bruk av mørkt tema
For åpne sider under Nav.no skal det kordineres med Nav.no-teamet om løsninger skal kunne støtte noen annet en lyst tema. Til dags dato (28.01.26) er det ikke opprettet en strategi for dette.
Hvis appen er en underside eller del av et større system, må temabytte være konsistent på tvers av hele systemet.
Potensielle fallgruver
Før du støtter bruk av mørkt fargetema bør du ta en gjennomgang av løsningen din
- Bruker løsningen noen “widgets”, f.eks tredjeparts-innhold som tilbakemelding-popups etc. Hvordan støtter disse mørkt tema?
- Tar løsningen i bruk noen
iframes? Om så, hvordan løses temabytte på tvers. - Bruker løsningen mye illustrasjoner, bilder eller annen media? Må disse oppdateres til å endres på tvers av tema?
Automatisk tema (prefers-color-scheme)
Forhåndsvalgt tema bør følge brukerens systeminnstilling, men må kunne overstyres. Dette kan hentes ut med window.matchMedia("(prefers-color-scheme: dark)").matches.
Nextjs
For next så vil pakker som next-themes være den enkleste metoden for å håndtere temabytte.
NextThemeProvider.tsx
import { ThemeProvider as NextThemeProvider } from "next-themes";
function ThemeProvider({ children }: { children: React.ReactNode }) { return ( <NextThemeProvider attribute="class" > {children} </NextThemeProvider> );}SPA
SPAThemeProvider.tsx
import { createContext, useContext, useEffect, useState } from "react"
type Theme = "dark" | "light" | "system"
type ThemeProviderProps = { children: React.ReactNode defaultTheme?: Theme storageKey?: string}
type ThemeProviderState = { theme: Theme setTheme: (theme: Theme) => void}
const initialState: ThemeProviderState = { theme: "system", setTheme: () => null,}
const ThemeProviderContext = createContext<ThemeProviderState>(initialState)
export function ThemeProvider({ children, defaultTheme = "system", storageKey = "spa-theme", ...props}: ThemeProviderProps) { const [theme, setTheme] = useState<Theme>( () => (localStorage.getItem(storageKey) as Theme) || defaultTheme )
useEffect(() => { const root = window.document.documentElement
root.classList.remove("light", "dark")
if (theme === "system") { const systemTheme = window.matchMedia("(prefers-color-scheme: dark)") .matches ? "dark" : "light"
root.classList.add(systemTheme) return }
root.classList.add(theme) }, [theme])
const value = { theme, setTheme: (theme: Theme) => { localStorage.setItem(storageKey, theme) setTheme(theme) }, }
return ( <ThemeProviderContext.Provider {...props} value={value}> {children} </ThemeProviderContext.Provider> )}
export const useTheme = () => { const context = useContext(ThemeProviderContext)
if (context === undefined) throw new Error("useTheme must be used within a ThemeProvider")
return context}App.tsx
import { ThemeProvider } from "@/components/theme-provider" function App() { return ( <ThemeProvider defaultTheme="light" storageKey="spa-theme"> {children} </ThemeProvider> )} export default App