Does VH work with 100vh?

Fix 100vh på iOS: Undgå springende layouts

18/02/2024

Rating: 3.98 (7283 votes)

Oplever du, at din hjemmeside eller webapplikation opfører sig uforudsigeligt på iOS-enheder, især når det kommer til højdejusteringer? Du er ikke alene. Mange webudviklere kæmper med den berygtede 100vh-fejl på iPhones og iPads, en irriterende adfærd, hvor visningsportens højde ikke beregnes korrekt. Dette kan føre til skjulte fodpaneler, uønskede scrollbarer eller et "springende" layout, når brugeren interagerer med browserens adresselinje. I denne dybdegående guide vil vi udforske, hvorfor denne fejl opstår, og præsentere de mest effektive løsninger, der sikrer, at dit indhold vises perfekt på tværs af alle iOS-enheder, uden at gå på kompromis med brugeroplevelsen. Vi dækker alt fra smarte CSS-hacks til robuste JavaScript-baserede strategier, så du kan vælge den løsning, der passer bedst til dit projekt.

Hvad er 100vh-problemet på iOS?

Problemet med 100vh på iOS-enheder, herunder iPhones og iPads, stammer fra den måde, browsere som Safari håndterer visningsportens højde på, især når brugergrænsefladeelementer som adresselinjen og den nederste navigationsbjælke dynamisk skjules og vises. Ifølge CSS-specifikationen skal 100vh repræsentere 100% af visningsportens højde. På en desktop-browser er dette typisk ligetil. Men på mobile enheder, specielt iOS, kan den "synlige" visningsport ændre sig, når brugeren scroller. Når adresselinjen trækkes op og ud af syne, eller den nederste bjælke forsvinder, udvides den tilgængelige plads for websiden. Dette får 100vh-værdien til at genberegnes, hvilket resulterer i en pludselig ændring af elementers dimensioner. Forestil dig et element, der er designet til at fylde hele skærmen – når browserbjælkerne forsvinder, vokser dette element pludselig, hvilket skaber en ubehagelig "springende" effekt.

Dette problem er særligt udtalt, når man forsøger at skabe et "fuldskærms"-layout, hvor et element skal fylde præcis 100% af den tilgængelige skærmhøjde. Et klassisk eksempel er en side med en fast header, et indholdsområde og en fast footer. Hvis fodpanelet er placeret ved bunden af 100vh, kan det blive skjult bag Safari's nederste navigationsbjælke, hvilket forringer brugeroplevelsen markant. Selvom Apple har forsøgt at afhjælpe dette i nyere iOS-versioner, eksisterer problemet stadig i forskellige former og kræver ofte specifikke rettelser for at sikre en konsistent og problemfri visning på tværs af alle iOS-versioner og -modeller. Gamle iOS 7-brugere oplevede endda en mere alvorlig fejl, hvor 100vh enheder ville vise et "meget højt tomt gab", selvom dette stort set er løst i nyere versioner, er det stadig en påmindelse om kompleksiteten ved mobile visningsporte.

How to fix 100vh in iOS?
PostCSS plugin to fix iOS’s bug with 100vh. It works in Chrome (just -webkit-fill-available causes problems in Chrome in some cases), iOS/iPad/MacOS Safari and all other browsers. Pure CSS solution, no JS required. /* Footer will be hidden on iOS Safari because of bottom panel */ height: 100vh; height: 100vh;

Løsninger med PostCSS-pluginnet (Anbefalet CSS-baseret løsning)

En af de mest elegante og effektive måder at afhjælpe 100vh-buggen på iOS er ved at bruge et PostCSS-plugin kaldet postcss-100vh-fix. Denne løsning er særligt attraktiv, fordi den er baseret på ren CSS og ikke kræver JavaScript på klientsiden, hvilket potentielt kan forbedre ydelsen og forenkle din kodebase. Pluginnet udnytter en smart CSS-regel til at målrette specifikt mod iOS/iPad/macOS Safari og andre browsere, der udviser denne adfærd, samtidig med at den undgår at påvirke browsere som Chrome, hvor den samme hack kan forårsage problemer.

Princippet bag løsningen er at bruge CSS-egenskaben -webkit-fill-available, som er en WebKit-specifik værdi, der instruerer elementet om at fylde den fuldt tilgængelige plads i visningsporten, og som tager højde for browserens dynamiske UI-elementer.

Her er et eksempel på den CSS, pluginnet genererer (eller som du selv kan anvende):

body { height: 100vh; /* Standard højde, der kan forårsage problemer på iOS / } / Undgå at Chrome ser Safari-hacket / @supports (-webkit-touch-callout: none) { body { / Hacket til Safari / height: -webkit-fill-available; } }

Denne kode sikrer, at body-elementet (eller ethvert andet element, du anvender det på) korrekt fylder den tilgængelige højde på iOS-enheder, selv når Safari's adresselinje og navigationsbjælke skjules eller vises. @supports (-webkit-touch-callout: none) er en smart måde at målrette specifikt mod WebKit-baserede browsere på iOS, da -webkit-touch-callout-egenskaben er unik for dem. Dette forhindrer uønskede bivirkninger i andre browsere, der måske fortolker -webkit-fill-available anderledes.

Fordele ved PostCSS-løsningen:

  • Ren CSS: Ingen JavaScript er påkrævet på klientsiden, hvilket kan forbedre indlæsningstiden og ydelsen.
  • Bred kompatibilitet: Virker i iOS/iPad/macOS Safari og de fleste andre browsere (med undtagelse af visse Chrome-tilfælde, som den undgår).
  • Enkel implementering: Når PostCSS er opsat, er det blot et spørgsmål om at tilføje pluginnet til din konfiguration.
  • Understøtter min-height og max-height: Pluginnet kan også anvendes på disse egenskaber.

Begrænsninger:

  • Partielle højder: Denne løsning fungerer ikke direkte for partielle højder som height: 90vh eller height: calc(100vh - 60px). For disse scenarier kræves mere avancerede løsninger, ofte involverende JavaScript.
  • Chrome til Android: Løsningen adresserer ikke en lignende fejl i Chrome til Android, hvor 100vh også kan opføre sig uforudsigeligt.

Sådan installeres og bruges pluginnet:

  1. Installer pluginnet:
    npm install --save-dev postcss postcss-100vh-fix
  2. Kontroller din PostCSS-konfiguration: Se efter postcss.config.js i projektets rod, en "postcss"-sektion i package.json, eller PostCSS-opsætning i din bundler-konfiguration (f.eks. Webpack, Parcel).
  3. Tilføj pluginnet: Hvis du allerede bruger PostCSS, skal du blot tilføje require('postcss-100vh-fix') til din plugins-liste. Hvis ikke, skal du opsætte PostCSS i henhold til den officielle dokumentation og derefter tilføje pluginnet.

Eksempel på postcss.config.js:

module.exports = { plugins: [ require('postcss-100vh-fix'), require('autoprefixer') // Eller andre plugins du bruger ] }

Denne PostCSS-løsning er et fremragende udgangspunkt for mange projekter, der primært har brug for at løse den grundlæggende 100vh-adfærd på iOS uden at introducere JavaScript-kompleksitet.

Avancerede løsninger med JavaScript og CSS-variabler

Mens PostCSS-pluginnet er effektivt for simple height: 100vh scenarier, er der situationer, hvor du har brug for mere finjusteret kontrol, især hvis du arbejder med partielle højder (f.eks. height: calc(100vh - 60px)) eller ønsker en mere robust løsning på tværs af alle mobile browsere, herunder Chrome til Android. I disse tilfælde er en JavaScript-baseret tilgang, der arbejder sammen med CSS-variabler, ofte den mest fleksible og pålidelige løsning.

Idéen er at dynamisk beregne den "sande" visningsporthøjde ved hjælp af JavaScript's window.innerHeight og derefter injicere denne værdi som en CSS-variabel. Denne variabel kan derefter bruges i din stylesheet til at definere højden af dine elementer. Dette giver dig mulighed for at tage højde for browserens dynamiske UI-elementer i realtid.

How to apply 100vh on iPhone?
The fix is very simple. For the elements where you need to apply 100vh, just match the element height with the device height using media queries that targets the older versions of iPhone and iPad resolution.

Trin-for-trin implementering:

  1. Definer en CSS-variabel i din stylesheet:
    :root { --real100vh: 100vh; / Standard fallback, hvis JS fejler / }

    Denne variabel fungerer som en placeholder for den korrigerede højde. Standardværdien 100vh sikrer en fallback for browsere, hvor JavaScript enten ikke kører, eller hvor korrektionen ikke er nødvendig.

  2. Brug JavaScript til at sætte variablen: Du skal køre denne JavaScript-kode ved sidens indlæsning (f.eks. DOMContentLoaded eller jQuery's ready-event) og igen ved vinduets størrelsesændring (resize-event) for at sikre, at højden altid er opdateret.
    function setReal100vh() { let value = "100vh"; // Standardværdi // Anvend JS for at sætte skærmhøjden, hvis vinduesstørrelsen er iPad eller mindre if (window.innerWidth && window.innerWidth <= 1024) { value = ${window.innerHeight}px; } document.documentElement.style.setProperty("--real100vh", value); } // Kør funktionen ved indlæsning og størrelsesændring window.addEventListener('load', setReal100vh); window.addEventListener('resize', setReal100vh); // For nogle tilfælde kan det også være nødvendigt at køre den ved DOMContentLoaded document.addEventListener('DOMContentLoaded', setReal100vh);

    Denne kode tjekker for enhedens bredde for at anvende korrektionen primært på mobile enheder (under 1024px bredde, som dækker de fleste tablets og telefoner). window.innerHeight returnerer den aktuelle højde af visningsporten i pixels, hvilket inkluderer den plads, der er "taget" af browserens UI-elementer.

  3. Brug den nye CSS-variabel i din stylesheet:

    Nu kan du anvende --real100vh overalt, hvor du tidligere ville have brugt 100vh.

    .min-fuldskærms-sektion { height: var(--real100vh); / Tilføj en overgang for en blødere effekt ved scroll / transition: height 0.4s ease-in-out; } .indhold-med-fast-header { height: calc(var(--real100vh) - 100px); / Eksempel med calc() */ }

    At tilføje en transition på højden kan gøre overgangen, når browserbjælkerne skjules/vises, langt mindre "jumpy" og mere behagelig for brugeren.

    How to fix 100vh in iOS?
    PostCSS plugin to fix iOS’s bug with 100vh. It works in Chrome (just -webkit-fill-available causes problems in Chrome in some cases), iOS/iPad/MacOS Safari and all other browsers. Pure CSS solution, no JS required. /* Footer will be hidden on iOS Safari because of bottom panel */ height: 100vh; height: 100vh;

Fordele ved JavaScript/CSS-variabel-tilgangen:

  • Høj præcision: Giver den mest præcise kontrol over visningsportens højde.
  • Understøtter calc(): Kan bruges inde i calc()-funktioner, hvilket er afgørende for layouts med faste headers/footere.
  • Fleksibilitet: Gør det muligt at overskrive højden ved specifikke breakpoints i CSS, hvis det er nødvendigt.
  • Bredere dækning: Kan afhjælpe problemer på tværs af flere mobile browsere, inklusiv Chrome til Android, som PostCSS-pluginnet ikke dækker.

Overvejelser:

  • Ydelse: Kræver JavaScript og lytter til resize-events, hvilket kan have en minimal indvirkning på ydelsen, men for de fleste moderne enheder er dette ubetydeligt.
  • Initial load: Sørg for, at JavaScript'en kører tidligt nok i indlæsningsprocessen for at undgå et kort "flash" af ukorrigeret layout.

For endnu mere omfattende JavaScript-baserede løsninger, der håndterer en bred vifte af visningsportsproblemer, kan du undersøge biblioteker som postcss-viewport-height-correction (på trods af navnet er det en JavaScript-baseret løsning) eller lignende "viewport buggyfill" scripts, der er designet til at give en mere robust og automatisk korrektion.

Hvorfor er dette vigtigt for brugeroplevelsen?

At løse 100vh-problemet på iOS er ikke bare en teknisk detalje; det er afgørende for en god brugeroplevelse. Forestil dig at besøge en hjemmeside på din iPhone, hvor indholdet pludselig hopper op og ned, eller hvor vigtige knapper og informationer forsvinder bag browserens navigationsbjælker. Dette skaber øjeblikkeligt frustration og kan få brugere til at forlade dit websted.

En "springende" layoutoplevelse, forårsaget af at 100vh genberegnes, når adresselinjen skjules, er et klassisk eksempel på dårlig brugervenlighed. Det forstyrrer læseflowet og skaber en følelse af ustabilitet. Ligeledes er det frustrerende, hvis en "fixed" footer, der indeholder vigtige navigationselementer eller en call-to-action, bliver skjult bag Safaris nederste bjælke. Brugeren skal da aktivt scrolle op eller ned for at få adgang til det skjulte indhold, hvilket tilføjer unødvendige trin og forringer intuitiviteten.

Ved at implementere en korrekt løsning for 100vh sikrer du, at dit design forbliver intakt og forudsigeligt uanset browserens UI-tilstand. Dette giver en mere professionel og poleret følelse, øger brugertilfredsheden og opfordrer til længere interaktion med dit indhold. En flydende og stabil brugeroplevelse er nøglen til at fastholde besøgende og opnå dine webmål.

Tabel: Sammenligning af løsninger

Feature/LøsningPostCSS 100vh FixJavaScript + CSS Variabel
TypeRen CSS (build-time)JavaScript (runtime)
Behov for JSNejJa
Kompatibilitet iOS SafariGod (bruger -webkit-fill-available)Meget god (bruger window.innerHeight)
Kompatibilitet Chrome AndroidNej (begrænsning)Ja (kan håndteres)
Håndtering af calc() / partielle højderNejJa
YdelsespåvirkningMinimal (build-time)Minimal (runtime)
KompleksitetLav (når PostCSS er sat op)Moderat (kræver JS-kode)
Primær fordelSimpel, ren CSS for 100vhFleksibel, præcis, bredere dækning

Ofte Stillede Spørgsmål (OSS)

Fungerer 100vh korrekt på alle browsere og enheder?

Nej, desværre ikke. Selvom 100vh er en standard CSS-enhed designet til at repræsentere 100% af visningsportens højde, udviser iOS Safari (og til tider Chrome på Android) en inkonsekvent adfærd. Dette skyldes primært den måde, disse mobile browsere dynamisk skjuler og viser deres UI-elementer (som adresselinjen og navigationsbjælken), hvilket får den "synlige" visningsport til at ændre størrelse, og dermed genberegnes 100vh. Dette fører til de førnævnte "springende" layouts eller skjult indhold. Desktop-browsere og mange Android-browsere håndterer generelt 100vh mere forudsigeligt.

How do I make 100vh a real VH?
Now you can simply use the CSS: height: var(--real100vh); wherever you want 100vh to actually be the real 100vh on mobile, and this will simply work! It looks better if you also add a transition: height 0.4s ease-in-out; on the same element, so it doesn't snap when you scroll down on mobile.

Er JavaScript altid nødvendigt for at løse 100vh-problemet på iOS?

Ikke altid. For de mest grundlæggende tilfælde, hvor du ønsker, at et element skal fylde nøjagtigt 100vh, kan den PostCSS-baserede løsning (som bruger -webkit-fill-available) være tilstrækkelig og kræver ingen JavaScript på klientsiden. Denne "rene CSS"-løsning er ideel for simple fuldskærms-layouts. Dog, hvis dit layout involverer beregninger (f.eks. calc(100vh - 60px)) eller du har brug for en mere robust løsning, der også adresserer Chrome for Androids særheder, så er en JavaScript-baseret tilgang (som at sætte en CSS-variabel baseret på window.innerHeight) ofte den mest pålidelige og fleksible løsning.

Hvad med ældre iOS-versioner som iOS 7?

iOS 7 havde en særligt berygtet 100vh-fejl, hvor enhederne ville vise et meget stort, tomt mellemrum, når 100vh blev anvendt. Dette problem blev stort set løst i iOS 8. Selvom antallet af brugere på iOS 7 er faldende, kan det stadig være relevant for nogle projekter med et bredere publikum. De moderne løsninger, vi har diskuteret (både PostCSS-pluginnet og JavaScript-tilgangen), er generelt robuste nok til at afhjælpe problemer på ældre iOS-versioner, da de enten bruger WebKit-specifikke egenskaber, der var til stede dengang, eller dynamisk måler den faktiske vindueshøjde. Hvis du specifikt skal understøtte iOS 7, kan det være værd at teste din valgte løsning grundigt på en enhed med denne version.

Hvorfor løser postcss-100vh-fix ikke Chrome til Android-buggen?

postcss-100vh-fix er specifikt designet til at målrette og udnytte en WebKit-specifik CSS-egenskab (-webkit-fill-available) og en @supports-regel, der er unik for iOS Safari's adfærd. Chrome til Android, som er baseret på Blink-motoren (ikke WebKit), har en separat, men lignende, adfærd med 100vh, der kræver en anderledes tilgang. Typisk er JavaScript-baserede løsninger, der dynamisk måler window.innerHeight, mere effektive til at afhjælpe 100vh-problemer på tværs af både iOS og Android Chrome, da de arbejder med den faktiske, dynamiske visningsporthøjde i realtid, uafhængigt af browser-specifikke CSS-hacks.

Konklusion

100vh-problemet på iOS er en almindelig udfordring for webudviklere, men heldigvis er der effektive løsninger til rådighed. Uanset om du foretrækker en simpel CSS-baseret løsning med PostCSS for grundlæggende 100vh-behov, eller en mere avanceret JavaScript-tilgang, der giver maksimal fleksibilitet og præcision for komplekse layouts, kan du opnå en problemfri brugeroplevelse på mobile enheder. Valget af løsning afhænger af dit projekts specifikke krav til kompleksitet og understøttelse af browsere. Ved at implementere en af disse strategier kan du sikre, at dine webapplikationer fremstår professionelle, stabile og brugervenlige på tværs af alle iOS-enheder.

Hvis du vil læse andre artikler, der ligner Fix 100vh på iOS: Undgå springende layouts, kan du besøge kategorien Mobiludvikling.

Go up