How to get the inner height of a viewport in JavaScript?

vh-enhed: Løsninger til mobile browsere

26/08/2024

Rating: 4.73 (11295 votes)

Det er et velkendt problem for webudviklere: når du bruger CSS-enheden `vh` (viewport height) til at definere højden på elementer, især på mobile enheder, kan den dynamiske browser-adresselinje skabe uventede visuelle fejl. Adresselinjen, der forsvinder og dukker op igen, når brugeren scroller, kan få elementer sat til `100vh` til at se enten for høje eller for lave ud, hvilket resulterer i afskåret indhold eller unødvendig plads. Dette er især frustrerende, når man forsøger at få et design til at passe perfekt til skærmen.

How to adjust viewport size if browser address bar is visible?
Instead of using vh units try CSS rule height: 100dvh this is dynamic viewport height and the size will be automatically adjusted in response to the mobile browsers UI state i.e. if the browser address bar is visible or not. As of January 2025, it is supported by 90.57% of users worldwide, according to caniuse.com. you saved me!

Forestil dig at have en fuldskærmsheader, der ser perfekt ud i din desktop-browser eller i browserens udviklingsværktøjer på en simuleret mobil enhed. Men når du tester på en rigtig telefon, opdager du, at den nederste del af din header er afskåret, eller at der er et ekstra tomrum under den. Problemet ligger i, hvordan mobile browsere som Chrome beregner `100vh`. Når adresselinjen er synlig, reduceres den tilgængelige viewport-højde, men `100vh` kan stadig referere til den *maksimale* højde, altså den højde der er tilgængelig, når adresselinjen er skjult.

Dette kan føre til, at et element, der er sat til `100vh`, fylder mere end den faktiske skærmplads, når adresselinjen er synlig. Lad os dykke ned i, hvordan vi kan løse dette problem og sikre en ensartet og professionel brugeroplevelse på tværs af alle enheder.

Indholdsfortegnelse

Forståelsen af Viewport-Enheder på Mobiler

For at løse dette problem er det vigtigt at forstå forskellen mellem de forskellige viewport-enheder, især på mobile browsere. Der findes tre primære viewport-enheder:

  • `vh` (viewport height): 1% af viewportens højde.
  • `svh` (small viewport height): 1% af den *mindste* viewport højde (når adresselinjen er synlig).
  • `lvh` (large viewport height): 1% af den *største* viewport højde (når adresselinjen er skjult).
  • `dvh` (dynamic viewport height): 1% af den *aktuelle* viewport højde, som ændrer sig dynamisk, når brugeren interagerer med browserens UI-elementer som adresselinjen.

Problemet opstår ofte, fordi `100vh` på mange mobile browsere refererer til `100lvh`, altså den maksimale højde. Når adresselinjen vises, mindskes den faktiske tilgængelige højde, men elementet forbliver "højt", hvilket resulterer i den observerede afskæring eller overskydende plads.

De Klassiske Løsninger (og deres begrænsninger)

Før de nyere `svh`, `lvh` og `dvh` enheder blev bredt understøttet, forsøgte udviklere at omgå problemet med JavaScript eller komplekse CSS-hacks. Disse metoder kan være effektive, men ofte også mere komplicerede at implementere og vedligeholde.

JavaScript-baseret Løsning

En almindelig tilgang var at bruge JavaScript til at måle den faktiske viewport-højde og derefter sætte elementets højde manuelt. Dette kunne se nogenlunde således ud:

window.addEventListener('resize', () => { let vh = window.innerHeight * 0.01; document.documentElement.style.setProperty('--vh', `${vh}px`); }); // Initial setup let vh = window.innerHeight * 0.01; document.documentElement.style.setProperty('--vh', `${vh}px`);

Derefter ville man i CSS bruge `--vh`-variablen:

.element { height: calc(var(--vh) * 100); }

Selvom denne løsning virker, har den ulemper. Den kræver JavaScript for at fungere, hvilket kan forsinke den visuelle rendering og potentielt forårsage et "flash" af forkert layout, før scriptet kører. Desuden kan resize-events være hyppige og kræve optimering.

CSS `calc()` med `100%`

En anden metode involverede at bruge `height: 100%` på elementet og dets forældre, men dette virker kun, hvis forældrene også har en defineret højde, der dynamisk tilpasser sig, hvilket ofte ikke er tilfældet eller er meget svært at opnå uden JavaScript.

De Moderne CSS Løsninger: `svh`, `lvh`, og `dvh`

Heldigvis har CSS udviklet sig for at imødekomme disse udfordringer direkte. De nye viewport-enheder giver os præcis den kontrol, vi har brug for.

`svh` (Small Viewport Height)

Hvis du ønsker, at dit element altid skal passe inden for den *mindste* tilgængelige højde (altså når adresselinjen er synlig), skal du bruge `svh`. Et element sat til `100svh` vil altid passe perfekt, selv når adresselinjen er synlig.

.fuld-skærmselement { height: 100svh; }

Fordel: Sikrer, at intet indhold bliver afskåret, uanset om adresselinjen er synlig eller ej.

Ulempe: Kan resultere i et synligt mellemrum, når adresselinjen forsvinder, da elementet ikke udvider sig.

`lvh` (Large Viewport Height)

Hvis du derimod ønsker, at dit element skal fylde den *maksimale* tilgængelige højde (når adresselinjen er skjult), skal du bruge `lvh`. Et element sat til `100lvh` vil kun fylde hele skærmen, når adresselinjen er skjult.

.fuld-skærmselement { height: 100lvh; }

Fordel: Giver den "fuldskærms" oplevelse, når der er mest plads.

Ulempe: Indhold kan blive afskåret, når adresselinjen er synlig.

How to set a viewport height?
As per this official article on Chrome web, the proper way to set the height to fill the visible viewport is with height: 100%, either on the element or on a position: fixed element. As the document describes, this ensures compatibility with mobile Safari and is independent of how large the URL bar is. Thank you very much.

`dvh` (Dynamic Viewport Height)

Dette er ofte den mest ønskelige løsning, da den dynamisk justerer sig. `dvh` repræsenterer den *aktuelle* viewport-højde. Når adresselinjen vises eller skjules, vil et element sat til `100dvh` automatisk justere sin højde derefter.

.fuld-skærmselement { height: 100dvh; }

Fordel: Giver en sømløs oplevelse, hvor elementet altid passer perfekt til den tilgængelige plads, uden afskæring eller unødvendige mellemrum.

Ulempe: Kræver, at browseren understøtter `dvh`. Understøttelsen er dog god i moderne browsere.

Hvornår skal man bruge hvad?

Valget af enhed afhænger af dit specifikke designbehov:

  • Brug `100svh`, hvis det er absolut kritisk, at intet indhold nogensinde bliver afskåret, selvom det betyder et potentielt synligt mellemrum på visse tidspunkter. Dette er ofte det sikreste valg for hovedindhold, der skal være fuldt synligt.
  • Brug `100lvh`, hvis du ønsker en dramatisk fuldskærmsoplevelse, og du er villig til at acceptere, at lidt indhold kan være skjult, når adresselinjen er synlig. Dette kan bruges til baggrundsbilleder eller sektioner, hvor den visuelle effekt er vigtigere end absolut synlighed af alt indhold.
  • Brug `100dvh`, hvis du ønsker den mest problemfrie og dynamiske løsning, der altid tilpasser sig den aktuelle viewport-højde. Dette er generelt den foretrukne metode til at opnå det, brugerne forventer af en "100vh" højde på mobile enheder.

Browserkompatibilitet

Det er altid en god idé at tjekke browserkompatibiliteten for de nyere enheder. Her er en oversigt:

Browser`svh``lvh``dvh`
Chrome (Desktop)JaJaJa
Chrome (Android)JaJaJa
Safari (Desktop)JaJaJa
Safari (iOS)JaJaJa
Firefox (Desktop)JaJaJa
Firefox (Android)JaJaJa
Edge (Desktop)JaJaJa

Som det ses, er understøttelsen for `svh`, `lvh`, og `dvh` generelt rigtig god i moderne browsere. For ældre browsere, der ikke understøtter disse, kan man overveje en fallback-mekanisme, typisk ved at bruge `vh` eller `px` som standard og eventuelt JavaScript, hvis det er strengt nødvendigt.

Eksempel: Fuldskærmsheader med `dvh`

Lad os tage det oprindelige eksempel og anvende `100dvh` for at løse problemet.

HTML (uændret)

<!DOCTYPE html> <html lang="da" dir="ltr"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Test</title> <link rel="stylesheet" href="style.css"> </head> <body> <header>Lorem ipsum</header> <main> <p>Lorem ipsum</p> </main> </body> </html>

CSS (med `dvh`)

body { margin: 0; font-family: sans-serif; } header { height: 100dvh; /* Bruges dvh for dynamisk højde */ background-color: lightblue; display: flex; justify-content: center; align-items: center; font-size: 2em; border-bottom: 2px solid black; /* For at vise afskæring, hvis det var 100vh */ } main { padding: 20px; }

Med denne ændring vil `

` elementet automatisk justere sin højde, så den passer til den tilgængelige viewport, uanset om browserens adresselinje er synlig eller ej. Dette giver en meget bedre brugeroplevelse.

Opsummering og Bedste Praksis

Problemet med `vh`-enheden på mobile browsere og dens interaktion med den dynamiske adresselinje er en almindelig faldgrube. Mens JavaScript-løsninger har været brugt tidligere, tilbyder de moderne CSS viewport-enheder (`svh`, `lvh`, `dvh`) en renere og mere effektiv løsning.

For de fleste moderne webprojekter, hvor en perfekt tilpasning til den tilgængelige plads er ønsket, er `100dvh` det bedste valg. Det sikrer, at dit layout dynamisk tilpasser sig brugerens interaktion med browseren, hvilket resulterer i en poleret og professionel præsentation.

Husk altid at teste dine designs på rigtige mobile enheder, da emuleringer i udviklingsværktøjer ikke altid fanger alle nuancer af browseradfærd.

Ofte Stillede Spørgsmål

Hvad er den største forskel mellem `vh` og `dvh`?

Den primære forskel er, hvordan de håndterer browserens UI-elementer som adresselinjen. `vh` refererer ofte til den maksimale viewport-højde, mens `dvh` refererer til den aktuelle, dynamiske viewport-højde. Dette betyder, at `100dvh` automatisk justerer sig, når UI-elementer vises eller skjules, mens `100vh` kan forblive statisk og potentielt forårsage afskæring.

Hvilken enhed skal jeg bruge for at undgå afskåret indhold?

Hvis dit primære mål er at undgå, at noget indhold bliver afskåret, er `100svh` (small viewport height) det sikreste valg, da det altid baserer sig på den mindste tilgængelige højde.

Er der nogen browsere, der ikke understøtter `dvh`?

Understøttelsen for `dvh`, `svh` og `lvh` er generelt meget god i de nyeste versioner af alle større browsere, inklusive Chrome, Firefox, Safari og Edge på både desktop og mobil. For meget gamle browsere kan der være behov for fallbacks.

Kan jeg bruge `calc()` med `dvh`?

Ja, ligesom med `vh`, kan du også bruge `calc()` med `dvh`. For eksempel: `height: calc(100dvh - 50px);` for at skabe et element, der er 100% af den dynamiske viewport-højde minus 50 pixels.

Hvis du vil læse andre artikler, der ligner vh-enhed: Løsninger til mobile browsere, kan du besøge kategorien Teknologi.

Go up