Hopp til innhold

Font

en skrifttype i en fil som siden laster ned

Hva det er

Hver bokstav du leser på en nettside, er tegnet etter en font: filen som rommer de tegnede bokstavene i ett design, i én vekt og én stil, sammen med tabellene som forteller programvare hvilken tegning som står for hvilket tegn, og hvor tett tegnene skal stå. Når et nettsted leverer filen selv, kalles den en webfont, CSS-spesifikasjonene kaller den et font face, og i dagligtale sier mange skrifttype om både fonten og designet.

Typografer holder designet og filene fra hverandre. Ubuntu er en skrifttype, mens Ubuntu Light og Ubuntu Bold Italic er snitt av den, hvert i sin egen fil. CSS holder det samme skillet. En fontfamilie samler snitt under ett navn, og hver @font-face-regel beskriver ett enkelt snitt: familien det hører til, hvor det skal hentes fra, vekten og stilen det dekker, hvilke tegn det kan vise, og hva som skal stå på skjermen mens det lastes.

@font-face {
    font-family: "Reading Serif";
    src:
        local("Reading Serif Regular"),
        local("ReadingSerif-Regular"),
        url("/fonts/reading-serif-400.woff2") format("woff2");
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

body {
    font-family: "Reading Serif", Georgia, serif;
}

Egenskapen font-family på et element er en liste som leses fra venstre mot høyre. Spesifikasjonen velger en familie og et snitt for hvert tegn i en tekstbit og tar det første snittet som passer til ønsket vekt og stil og har en glyf for akkurat det tegnet. Én linje kan derfor bli satt med to fonter når den første mangler en bokstav, og det generiske navnet til slutt i listen, serif, sans-serif, monospace eller system-ui, sørger for at en installert font alltid tar resten.

På weben er filen nesten alltid WOFF2: de samme OpenType- eller TrueType-konturene og -tabellene, pakket om for overføring og komprimert med Brotli. Inne i filen kobler cmap-tabellen hver tegnkode til en glyf, og andre tabeller bærer tallene en layoutmotor trenger, som ascent, descent og line gap, og hvor en understreking ligger og hvor tykk den er. Disse tallene avgjør linjehøyde og avstand like mye som bokstavformene avgjør utseendet.

Hvorfor det er viktig

Hver vekt og hver stil er en egen nedlasting. Et design som bruker normal, kursiv og fet skrift, legger tre filer mellom leseren og teksten som er satt med dem, og hver av dem legger byte til det første besøket. Deskriptoren unicode-range lar en familie deles opp etter skriftsystem, og spesifikasjonen forbyr en nettleser å laste ned en del for tegn utenfor området til delen, så en side henter bare de delene teksten dens faktisk bruker.

Tekst i en webfont kan ikke tegnes før filen er kommet fram, så nettleseren trenger en regel for ventetiden. Deskriptoren font-display setter den. Med block anbefaler spesifikasjonen en blokkeringsperiode på 3 sekunder, der teksten er satt, men tegnes usynlig. Med swap er blokkeringsperioden 100 ms eller mindre, reservefonten vises nesten med en gang, og webfonten tar over når den kommer. Med fallback er byttevinduet kort, med 3 sekunder anbefalt, og etter det beholder siden reservefonten. Med auto bestemmer nettleseren selv, og mange behandler det som block.

Hvor filen ligger, betyr også noe. Fontforespørsler bruker CORS, så en font fra et annet opphav (origin) lastes bare når den serveren tillater det, og hver forespørsel til et annet selskaps server forteller det selskapet hvilken adresse leseren har og hvilket nettsted vedkommende er på. Å levere fonter fra nettstedets egen vert fjerner både den ekstra forbindelsen og observatøren.

En font er programvare under en lisens. SIL Open Font License tillater at fontene brukes, studeres, endres og distribueres videre så lenge de ikke selges alene, og forbyr en endret versjon å bruke et reservert fontnavn uten tillatelse. En font som er kjøpt til trykk, kan ha andre vilkår på weben, så les lisensen før filen havner på en server.

Dekning er det siste spørsmålet. En font tegner bare tegnene cmap-tabellen dens lister opp. Det meste av det kyrilliske alfabetet ligger i området U+0400–045F, men den ukrainske bokstaven ґ ligger på U+0490–0491, så et delsett eller et område skrevet for russisk tekst overlater den til den reservefonten som står for tur.

Slik ser det ut i praksis

Nettstedets kolofon lister opp det som når fram til nettleseren hos en leser, som fem ting, og tre av dem er webfonter. Ubuntu, av Dalton Maag for Canonical, er under Ubuntu Font Licence. Ubuntu Mono, den samme familiens snitt med fast bredde, setter koden. Shantell Sans, basert på kunstneren Shantell Martins håndskrift med tusj, er under SIL Open Font License og skriver margnotatene. Alle tre kommer fra nettstedets egen maskin, og siden sier hvorfor: en webfont fra noen andres CDN er en tredjepart som ser deg lese. Ubuntu Mono og Shantell Sans lastes bare på sidene som har kode eller et margnotat.

Å dele én skrifttype opp etter skriftsystem er temaet for notatet om understrekingene i Safari. Nettstedet leverer Ubuntu i seks deler, tre vekter latinsk og tre kyrillisk, og hver del oppgir tegnene den dekker, så engelske og danske sider henter tre latinske filer og ingen kyrilliske, og ukrainske sider det motsatte. Alle seks delte ett familienavn, og i Safari svekker et snitt med et ikke-latinsk tegnområde skip-ink, mellomrommet en understreking lar stå rundt en underlengde, for hvert tegn i familien, også latinsk tekst. Å slette de tre kyrilliske deklarasjonene under kjøring tok de målte mellomrommene fra 1,8/1,0/1,0px til 4,5/11,0/5,0px. Rettelsen ga de kyrilliske snittene et eget familienavn og satte det i fontstakken etter Ubuntu: tre omdøpte deklarasjoner og én oppføring i stakken, med Chrome uberørt og ukrainsk fortsatt satt i Ubuntu med identiske bredder. Det samme notatet viser hvor mye en fonts egne tall varierer: Ubuntu oppgir en understrekingstykkelse på 0,056em for Light, 0,020em for Medium og 0,120em for Bold.

Landingssiden foran selskapets egen git-forge hadde vært en håndvedlikeholdt kopi av designet til hovednettstedet, og hver forskjell som ble funnet mellom de to, var et uhell og ikke en beslutning. To av de fem gjaldt fonter: en fontdeklarasjon som slo sammen to vekter til én på enhver maskin der familien var installert, og en vekt som ble brukt uten at det fulgte noen font med for den. Alle fem var usynlige på et skjermbilde. Kopien ble slettet, og landingssiden bygges nå av hovednettstedets egne maler.

Hvor det går galt

  • Teksten er usynlig mens filen lastes. Under block, og ofte under auto, viser en treg forbindelse en ferdig satt side uten ord i opptil hele blokkeringsperioden. Bruk swap for brødtekst, og forhåndslast de én eller to filene den første skjermen trenger. En forhåndslasting av en font trenger attributtet crossorigin også for en fil fra samme opphav, fordi den må matche CORS-forespørselen den står i stedet for.
  • Siden hopper når fonten kommer. En reservefont med andre bredder og linjehøyder bryter linjene på andre steder, og byttet brekker dem om. Spesifikasjonen råder til reservefonter med mål som ligger tett opptil webfontens. Der ingen gjør det, gir et local()-snitt for reservefonten med ascent-override, descent-override og line-gap-override den vertikale mål som stemmer, så byttet endrer bokstavformer og ikke oppsett.
  • Fet og kursiv som ingen har tegnet. Når en familie mangler et snitt for fet skrift, kan nettleseren gjøre det normale snittet tykkere, og den kan skråstille det når det ikke finnes noe kursivt snitt. Strekene flyter ut, og bokstaver som skulle stått rett, lener seg. Lever hvert snitt designet bruker, eller sett font-synthesis til none, slik at et manglende snitt viser seg i gjennomgangen som rett tekst i normal vekt i stedet for en etterligning.
  • local() tar et snitt, ikke en familie. Navnet inne i local() matcher ett enkelt snitt på det fulle navnet eller på PostScript-navnet. Skriver du familienavnet der for hver vekt, kan det matche ett og samme installerte snitt for alle sammen, så fet skrift vises som normal på nettopp de maskinene som har familien installert. Navngi hvert snitt på begge måter, eller utelat local().
  • En manglende glyf blander skrifttyper. Et snitt som mangler et tegn, gir det videre til neste familie, så ett ord kan vise to design. Et delsett som er skåret for stramt, gjør det samme for et helt skriftsystem. Sjekk dekningen mot teksten nettstedet faktisk publiserer, på hvert språk det publiserer på.

Les mer

  • CSS Fonts Module Level 4 — @font-face, algoritmen som velger snitt, unicode-range, font-display og styringen av syntetisk fet og kursiv.
  • WOFF File Format 2.0 — hvordan OpenType- og TrueType-fonter pakkes og komprimeres for weben.
  • OpenType cmap table — tabellen som avgjør hvilke tegn en font kan tegne.
  • SIL Open Font License — selve lisensteksten, med vilkårene for kopier, endrede versjoner og reserverte navn.
  • WebKit bug 255159 — feilrapporten om skip-ink for understrekinger i Safari, som notatet på nettstedet bygger på.

Ordliste