# Font

## 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.

```css
@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](/nb/credits/) 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](/nb/notes/safari-underline-font-subset/). 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](/nb/portfolio/deployed-the-companys-own-git-forge-121/) 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](https://www.w3.org/TR/css-fonts-4/) — `@font-face`,
  algoritmen som velger snitt, `unicode-range`, `font-display` og styringen av
  syntetisk fet og kursiv.
- [WOFF File Format 2.0](https://www.w3.org/TR/WOFF2/) — hvordan OpenType- og
  TrueType-fonter pakkes og komprimeres for weben.
- [OpenType cmap table](https://learn.microsoft.com/en-us/typography/opentype/spec/cmap)
  — tabellen som avgjør hvilke tegn en font kan tegne.
- [SIL Open Font License](https://openfontlicense.org/open-font-license-official-text/)
  — selve lisensteksten, med vilkårene for kopier, endrede versjoner og reserverte
  navn.
- [WebKit bug 255159](https://bugs.webkit.org/show_bug.cgi?id=255159) — feilrapporten
  om skip-ink for understrekinger i Safari, som notatet på nettstedet bygger på.

<https://engineer.company/nb/glossary/font/>
