Viewport
den del af en side et vindue faktisk viser
Hvad det er
En viewport er det rektangel, en browser lægger et dokument ud i og tegner det
ind i: på en skærm området inden for vinduets egne værktøjslinjer, på papir
sideområdet på hvert ark. CSS måler hele tiden mod det. Den indledende
indeholdende blok, altså den boks, rodelementet lægges ud i, får dets størrelse,
en medieforespørgsel på width eller height spørger til det, og enhederne
vw og vh er hundrededele af det. På en telefon har ordet brug for et forled,
og specifikationerne har flere at vælge imellem: layout, visuel, lille, stor og
dynamisk.
På en computer er viewporten og vinduet næsten det samme. På en telefon skilles
de. Fordi så mange dokumenter er lavet til skrivebordsvinduer, lægger
mobilbrowsere en side uden instruktioner ud i en fast bredde, der efterligner et
skrivebordsvindue, ifølge CSS Viewport-specifikationen typisk 980 til 1.024
CSS-pixel, og skalerer derefter resultatet ned, så det passer til glasset. En
side melder sig ud med ét element i sit hoved, og elementet tager imod width,
height, tre skalagrænser, user-scalable og interactive-widget:
<meta name="viewport" content="width=device-width, initial-scale=1" />
Zoom deler viewporten i to. Layout-viewporten er den, CSS lægger siden ud efter,
og knibezoom rører den ikke, så linjeskiftene bliver, hvor de er. Den visuelle
viewport er den del af siden, der er på glasset netop nu: den bliver mindre, når
læseren zoomer ind, og glider med, når læseren panorerer. Som standard skrumper
et skærmtastatur kun den visuelle viewport. Med
interactive-widget=resizes-content beder siden browseren om at ændre layoutet
med, og med overlays-content om at lade begge være.
Telefoner har desuden browserbjælker, der glider væk. Adresselinjen tager plads,
når siden indlæses, og trækker sig tilbage, når læseren ruller, så den synlige
højde ændrer sig under en side, der står stille. CSS Values 4 giver tre
størrelser til det. Den store viewport antager, at alle bjælker, der kan trækkes
tilbage, er trukket tilbage, den lille antager, at de alle vises, og den
dynamiske følger, hvad der faktisk er tilfældet. Enhederne bærer de samme
forstavelser, lvh, svh og dvh, med tilsvarende bredder, og de almindelige
vh og vw er defineret ud fra den store viewport. En brugerflade, der lægger
sig over indholdet uden at flytte det, typisk skærmtastaturet, ændrer ingen af
de længder.
Hvorfor det betyder noget
Responsivt design hviler på viewporten. Hvert brudpunkt i et stylesheet er et
spørgsmål om dens bredde, så en side uden meta-elementet bliver lagt ud i
skrivebordsbredde på en telefon og skrumpet, til teksten er ulæselig, uanset
hvor omhyggeligt medieforespørgslerne er skrevet.
Højden er den svære akse. Bredden ligger fast, så længe telefonen ikke drejes. Højden ændrer sig, når bjælken glider, når tastaturet åbner, og når telefonen vendes, så alt, der er dimensioneret efter skærmens højde, må sige, hvilken højde det mener. Den lille viewport passer altid og efterlader en stribe ubrugt plads, når bjælkerne trækker sig tilbage. Den store fylder skærmen og lægger indhold bag bjælkerne, mens de vises. Den dynamiske er præcis, og specifikationen advarer selv om, at den kan ændre indholdets størrelse, mens læseren ruller, så alt nedenunder flytter sig.
Skærme har også hjørner. En telefon med runde hjørner eller et udskåret
kamerahul er ikke et rektangel, og med standardværdien auto forbliver hele
siden synlig på den. Tilføjer siden viewport-fit=cover, beder den om, at
viewporten bliver det rektangel, der kan tegnes uden om hele den fysiske skærm,
og påtager sig selv at holde teksten fri af udskæringen med variablerne
env(safe-area-inset-*). De skal være nul på en rektangulær skærm, så én regel
for polstringen dækker begge slags.
Fast positionering hænger også på viewporten. En fast boks placeres efter
layout-viewporten, som CSS Positioned Layout giver den dynamiske viewports
størrelse, så cookiebjælker, modale baggrunde og fuldskærmsmenuer står stille,
mens siden ruller. Hver af dem går ud fra, at ingen forfader har overtaget
rollen, og transform, will-change og contain kan netop gøre det.
Udskrift er den viewport, et stylesheet skrevet til skærm aldrig møder. På papir
måler viewport-enhederne sideområdet, en forespørgsel på width spørger til
sideboksen, og et fast element gentages på hver side.
Sådan ser det ud i praksis
Siderne på dette websted erklærer width=device-width, initial-scale=1, viewport-fit=cover, så de lægges ud i telefonens bredde og går helt ud til
kanten, også under en udskæring. Stylesheetet betaler for den sidste del:
sidepolstringen er max(1rem, env(safe-area-inset-left)) og den tilsvarende
regel for højre side, så teksten holder en rem fra kanten og kun rykker længere
ind, hvor der sidder en udskæring. På lave skærme i liggende format hæves gulvet
til max(2rem, 7vw, env(safe-area-inset-left)), fordi indrykningerne er nul på
en telefon uden udskæring, og én rem sad for tæt på kanten.
Fuldskærmssektioner henter deres højde fra en fælles variabel sat til 100dvh
med 100vh som reserve, og kommentaren ved siden af siger hvorfor: 100vh kan
være højere end det synlige, mens adresselinjen er fremme, og det havde ladet
den næste sektion stikke op under topsektionen. To elementer går med vilje uden
om variablen. Mærket i sidehovedet er dimensioneret i statisk vh, fordi et
mærke bundet til den dynamiske viewport ville skifte størrelse, når browserens
bjælker gled væk, og flytte rundt på topsektionen midt i en rulning. Den faste
baggrund på berøringsskærme er 100lvh høj, så den aldrig skifter størrelse,
når adresselinjen kommer og går, og den ligger på sit eget kompositionslag,
fordi berøringsbrowsere rev den op i lyse og mørke bånd under inertirulning.
Hver serviceblok på forsiden er mindst 100dvh høj, hvilket giver én blok pr.
skærm, så længe indholdet er lavere end skærmen. Ved 852 gange 393 pixel fylder
en bloks indhold 412, og blokkene stødte lige op ad hinanden. Polstring inden
for de 100dvh, via box-sizing: border-box, koster intet på en høj skærm og
åbner kun et mellemrum, når indholdet løber over.
Testene følger medieforespørgslerne. Sitets browserdrevne kvalitetsport udvidede sine tjek til en fælles tabel med toogtyve vinduesformer, hentet fra hver eneste medieforespørgsel i stylesheetet, og det trak layouttjekket alene fra 95 sekunder op til 405.
Udskrift afslørede forskellen mellem motorerne.
Udskriftsstylesheetet
beskriver, at én motor regner viewport-enheder ud fra sideboksen og en anden ud
fra vinduet, så en side udskrevet fra et bredt vindue mistede en tredjedel af
hver linje i den anden. Sidehovedets eget stylesheet beskriver
medieforespørgslernes side af samme kløft: udskriften beholdt vinduets
orientering, højde og bredde, så ark udskrevet fra et bredt og et smalt vindue
fik sidehoveder, der afveg 47 pixel fra hinanden, indtil screen and forrest i
forespørgslen begrænsede reglen til vinduer.
Fælden med den indeholdende blok er også dokumenteret. Arbejdet med reduceret bevægelse viste, at fem forskellige egenskaber hver især gør et element til den indeholdende blok for alt, der placeres i forhold til viewporten, og at det i stilhed havde krympet et lag, man klikker på for at lukke, til en brøkdel af skærmen.
Hvor det går galt
Telefonen viser en lillebitte skrivebordsside. Uden
viewport-meta-elementet lægger browseren siden ud i en skrivebordsbredde og
skalerer den ned, og medieforespørgslerne ser den bredde. Tilføj
width=device-width, initial-scale=1, og lad zoom være slået til:
user-scalable=no fjerner læserens egen måde at forstørre lille tekst på.
En fuldskærmssektion går ud over skærmens bund. 100vh er den store
viewport, så mens adresselinjen er fremme, ligger bunden af sektionen bag den,
sammen med enhver knap, der står dér. Brug svh til et element, der altid skal
passe, og dvh kun dér, hvor en størrelsesændring midt i en rulning er
acceptabel.
Et fuldskærmslag skrumper til en boks inde på siden. En forfader med
transform, med en will-change, der nævner den, eller med containment bliver
den indeholdende blok for position: fixed, og laget tager forfaderens
størrelse. Læg den slags lag uden for ethvert transformeret element.
En udskrevet side mister slutningen af hver linje. Viewport-enheder og
forespørgsler på vinduets mål siver ind i udskriften, og en motor, der regner
dem ud fra vinduet, lægger arket ud til en skærm. Hold viewport-enheder ude af
alt, der skal udskrives, og sæt screen and foran forespørgsler, der er ment
for vinduer.
Læs mere
- CSS Viewport Module Level 1 —
viewport-
meta-elementet og de tre adfærdsformer forinteractive-widget. - CSS Values and Units Level 4: viewport-percentage lengths — den lille, den store og den dynamiske viewportstørrelse og alle de enheder, der bygger på dem.
- CSS Positioned Layout Level 3 — fast positionering, de egenskaber, der fanger den, og hvad den gør på papir.
- CSS Environment Variables Level 1 — safe-area-indrykningerne og reglen, der gør dem til nul på en rektangulær skærm.
- Media Queries Level 4 —
width,heightogorientation, målt på viewporten på skærm og på sideboksen ved udskrift.