Gebruik geavanceerde typografie met lokale lettertypen

Ontdek hoe u met de Local Font Access API toegang krijgt tot de lokaal geïnstalleerde lettertypen van de gebruiker en er gedetailleerde details over kunt verkrijgen

Webveilige lettertypen

Als u lang genoeg met webontwikkeling bezig bent, herinnert u zich wellicht de zogenaamde websafe fonts . Het is bekend dat deze lettertypen beschikbaar zijn op vrijwel alle exemplaren van de meest gebruikte besturingssystemen (namelijk Windows, macOS, de meest voorkomende Linux-distributies, Android en iOS). In het begin van de jaren 2000 leidde Microsoft zelfs een initiatief genaamd TrueType core fonts for the Web , dat deze lettertypen gratis downloadde met als doel dat "wanneer u een website bezoekt die deze specificeert, u pagina's precies ziet zoals de site-ontwerper het bedoeld heeft. " . Ja, dit omvatte sites in Comic Sans MS . Hier is een klassieke webveilige lettertypestapel (met de ultieme terugval van welk sans-serif lettertype dan ook) die er als volgt uit zou kunnen zien:

body {
  font-family: Helvetica, Arial, sans-serif;
}

Weblettertypen

De tijd dat webveilige lettertypen er echt toe deden, is al lang voorbij. Tegenwoordig hebben we weblettertypen , waarvan sommige zelfs variabele lettertypen zijn die we verder kunnen aanpassen door de waarden voor de verschillende blootgestelde assen te wijzigen. U kunt weblettertypen gebruiken door een @font-face blok aan het begin van de CSS te declareren, waarin wordt aangegeven welke lettertypebestanden moeten worden gedownload:

@font-face {
  font-family: 'FlamboyantSansSerif';
  src: url('flamboyant.woff2');
}

Hierna kunt u het aangepaste weblettertype gebruiken door de font-family op te geven, zoals normaal:

body {
  font-family: 'FlamboyantSansSerif';
}

Lokale lettertypen als vingerafdrukvector

De meeste weblettertypen komen van, nou ja, het internet. Een interessant feit is echter dat de eigenschap src in de @font-face -declaratie, naast de url() -functie, ook een local() functie accepteert. Hierdoor kunnen aangepaste lettertypen lokaal worden geladen (verrassing!). Als de gebruiker FlamboyantSansSerif op zijn besturingssysteem heeft geïnstalleerd, wordt de lokale kopie gebruikt in plaats van dat deze wordt gedownload:

@font-face {
  font-family: 'FlamboyantSansSerif';
  src: local('FlamboyantSansSerif'), url('flamboyant.woff2');
}

Deze aanpak biedt een mooi terugvalmechanisme dat mogelijk bandbreedte bespaart. Op internet kunnen we helaas geen leuke dingen hebben. Het probleem met de functie local() is dat deze kan worden misbruikt voor browservingerafdrukken. Het blijkt dat de lijst met lettertypen die een gebruiker heeft geïnstalleerd behoorlijk identificerend kan zijn. Veel bedrijven hebben hun eigen bedrijfslettertypen die op de laptops van werknemers worden geïnstalleerd. Google heeft bijvoorbeeld een bedrijfslettertype genaamd Google Sans .

De macOS Font Book-app toont een voorbeeld van het Google Sans-lettertype.
Het Google Sans-lettertype geïnstalleerd op de laptop van een Google-medewerker.

Een aanvaller kan proberen vast te stellen voor welk bedrijf iemand werkt door te testen op het bestaan ​​van een groot aantal bekende bedrijfslettertypen zoals Google Sans . De aanvaller zou proberen tekst in deze lettertypen op een canvas weer te geven en de tekens te meten. Als de tekens overeenkomen met de bekende vorm van het bedrijfslettertype, heeft de aanvaller een treffer. Als de glyphs niet overeenkomen, weet de aanvaller dat er een standaard vervangend lettertype is gebruikt, omdat het bedrijfslettertype niet is geïnstalleerd. Voor volledige details over deze en andere browserfingerprinting-aanvallen kunt u het onderzoeksartikel van Laperdix et al. lezen.

Afgezien van bedrijfslettertypen kan zelfs alleen de lijst met geïnstalleerde lettertypen identificerend zijn. De situatie met deze aanvalsvector is zo slecht geworden dat het WebKit-team onlangs besloot om "alleen [in de lijst beschikbare lettertypen] weblettertypen en lettertypen op te nemen die bij het besturingssysteem worden geleverd, maar niet lokaal door de gebruiker geïnstalleerde lettertypen" . (En hier ben ik dan, met een artikel over het verlenen van toegang tot lokale lettertypen.)

De API voor lokale toegang tot lettertypen

Het begin van dit artikel heeft u wellicht in een negatieve stemming gebracht. Kunnen we echt geen leuke dingen hebben? Maak je geen zorgen. We denken dat we het kunnen, en misschien is alles niet hopeloos . Maar laat me eerst een vraag beantwoorden die u zich misschien stelt.

Waarom hebben we de Local Font Access API nodig als er weblettertypen zijn?

Ontwerp- en grafische tools van professionele kwaliteit zijn van oudsher moeilijk te leveren op internet. Eén struikelblok was het onvermogen om toegang te krijgen tot en gebruik te maken van de volledige verscheidenheid aan professioneel ontworpen lettertypen met hints die ontwerpers lokaal hebben geïnstalleerd. Weblettertypen maken sommige gebruiksscenario's voor publicatie mogelijk, maar bieden geen programmatische toegang tot de vectorglyph-vormen en lettertypetabellen die door rasterizers worden gebruikt om de glyph-contouren weer te geven. Er is ook geen manier om toegang te krijgen tot de binaire gegevens van een weblettertype.

  • Ontwerptools hebben toegang nodig tot lettertypebytes om hun eigen OpenType-lay-outimplementatie uit te voeren en maken het mogelijk dat ontwerptools op lagere niveaus kunnen inhaken, voor acties zoals het uitvoeren van vectorfilters of transformaties op de glyph-vormen.
  • Ontwikkelaars hebben mogelijk verouderde lettertypestapels voor hun toepassingen die ze op internet brengen. Om deze stapels te kunnen gebruiken, hebben ze meestal directe toegang tot lettertypegegevens nodig, iets wat weblettertypen niet bieden.
  • Voor sommige lettertypen is mogelijk geen licentie beschikbaar voor levering via internet. Linotype heeft bijvoorbeeld een licentie voor sommige lettertypen die alleen desktopgebruik omvat.

De Local Font Access API is een poging om deze uitdagingen op te lossen. Het bestaat uit twee delen:

  • Een API voor het opsommen van lettertypen , waarmee gebruikers toegang kunnen verlenen tot de volledige set beschikbare systeemlettertypen.
  • Vanuit elk opsommingsresultaat is er de mogelijkheid om low-level (byte-georiënteerde) SFNT-containertoegang aan te vragen die de volledige lettertypegegevens bevat.

Browser-ondersteuning

Browserondersteuning

  • Chroom: 103.
  • Rand: 103.
  • Firefox: niet ondersteund.
  • Safari: niet ondersteund.

Bron

Hoe u de Local Font Access API gebruikt

Functiedetectie

Om te controleren of de Local Font Access API wordt ondersteund, gebruikt u:

if ('queryLocalFonts' in window) {
  // The Local Font Access API is supported
}

Opsomming van lokale lettertypen

Om een ​​lijst met lokaal geïnstalleerde lettertypen te verkrijgen, moet u window.queryLocalFonts() aanroepen. De eerste keer wordt hierdoor een toestemmingsprompt geactiveerd, die de gebruiker kan goedkeuren of weigeren. Als de gebruiker goedkeurt dat de lokale lettertypen worden opgevraagd, retourneert de browser een array met lettertypegegevens die u kunt herhalen. Elk lettertype wordt weergegeven als een FontData object met de family (bijvoorbeeld "Comic Sans MS" ), fullName (bijvoorbeeld "Comic Sans MS" ), postscriptName (bijvoorbeeld "ComicSansMS" ) en style (bijvoorbeeld , "Regular" ).

// Query for all available fonts and log metadata.
try {
  const availableFonts = await window.queryLocalFonts();
  for (const fontData of availableFonts) {
    console.log(fontData.postscriptName);
    console.log(fontData.fullName);
    console.log(fontData.family);
    console.log(fontData.style);
  }
} catch (err) {
  console.error(err.name, err.message);
}

Als u alleen geïnteresseerd bent in een subset van lettertypen, kunt u deze ook filteren op basis van de PostScript-namen door een postscriptNames parameter toe te voegen.

const availableFonts = await window.queryLocalFonts({
  postscriptNames: ['Verdana', 'Verdana-Bold', 'Verdana-Italic'],
});

Toegang tot SFNT-gegevens

Volledige SFNT- toegang is beschikbaar via de blob() -methode van het FontData object. SFNT is een lettertypebestandsindeling die andere lettertypen kan bevatten, zoals PostScript-, TrueType-, OpenType-, Web Open Font Format (WOFF)-lettertypen en andere.

try {
  const availableFonts = await window.queryLocalFonts({
    postscriptNames: ['ComicSansMS'],
  });
  for (const fontData of availableFonts) {
    // `blob()` returns a Blob containing valid and complete
    // SFNT-wrapped font data.
    const sfnt = await fontData.blob();
    // Slice out only the bytes we need: the first 4 bytes are the SFNT
    // version info.
    // Spec: https://docs.microsoft.com/en-us/typography/opentype/spec/otff#organization-of-an-opentype-font
    const sfntVersion = await sfnt.slice(0, 4).text();

    let outlineFormat = 'UNKNOWN';
    switch (sfntVersion) {
      case '\x00\x01\x00\x00':
      case 'true':
      case 'typ1':
        outlineFormat = 'truetype';
        break;
      case 'OTTO':
        outlineFormat = 'cff';
        break;
    }
    console.log('Outline format:', outlineFormat);
  }
} catch (err) {
  console.error(err.name, err.message);
}

Demo

In de onderstaande demo kunt u de Local Font Access API in actie zien. Bekijk zeker ook de broncode . De demo toont een aangepast element genaamd <font-select> dat een lokale lettertypekiezer implementeert.

Privacyoverwegingen

De toestemming "local-fonts" lijkt een oppervlak te bieden dat zeer geschikt is voor vingerafdrukken. Het staat browsers echter vrij om alles terug te sturen wat ze willen. Op anonimiteit gerichte browsers kunnen er bijvoorbeeld voor kiezen om alleen een set standaardlettertypen aan te bieden die in de browser zijn ingebouwd. Op dezelfde manier hoeven browsers de tabelgegevens niet precies weer te geven zoals deze op schijf verschijnen.

Waar mogelijk is de Local Font Access API ontworpen om alleen precies de informatie vrij te geven die nodig is om de genoemde gebruiksscenario's mogelijk te maken. Systeem-API's kunnen een lijst met geïnstalleerde lettertypen produceren, niet in willekeurige of gesorteerde volgorde, maar in de volgorde waarin de lettertypen zijn geïnstalleerd. Het retourneren van exact de lijst met geïnstalleerde lettertypen die door een dergelijke systeem-API wordt gegeven, kan aanvullende gegevens blootleggen die kunnen worden gebruikt voor het maken van vingerafdrukken, en gebruiksscenario's die we willen inschakelen worden niet geholpen door deze volgorde te behouden. Als gevolg hiervan vereist deze API dat de geretourneerde gegevens worden gesorteerd voordat ze worden geretourneerd.

Beveiliging en machtigingen

Het Chrome-team heeft de Local Font Access API ontworpen en geïmplementeerd met behulp van de kernprincipes die zijn gedefinieerd in Toegangscontrole tot krachtige webplatformfuncties , waaronder gebruikerscontrole, transparantie en ergonomie.

Gebruikerscontrole

Toegang tot de lettertypen van een gebruiker valt volledig onder hun controle en zal niet worden toegestaan ​​tenzij de machtiging "local-fonts" , zoals vermeld in het machtigingsregister , wordt verleend.

Transparantie

Of een site toegang heeft gekregen tot de lokale lettertypen van de gebruiker, is zichtbaar in het site-informatieblad .

Persistentie van toestemming

De toestemming "local-fonts" blijft behouden tussen paginaherlaadbeurten. Het kan worden ingetrokken via het site-informatieblad .

Feedback

Het Chrome-team wil graag horen wat uw ervaringen zijn met de Local Font Access API.

Vertel ons over het API-ontwerp

Is er iets aan de API dat niet werkt zoals je had verwacht? Of ontbreken er methoden of eigenschappen die je nodig hebt om je idee te implementeren? Heeft u een vraag of opmerking over het beveiligingsmodel? Dien een spec issue in op de corresponderende GitHub repository , of voeg uw gedachten toe aan een bestaand issue.

Meld een probleem met de implementatie

Heeft u een bug gevonden in de implementatie van Chrome? Of wijkt de uitvoering af van de specificaties? Dien een bug in op new.crbug.com . Zorg ervoor dat u zoveel mogelijk details en eenvoudige instructies voor het reproduceren opneemt, en voer Blink>Storage>FontAccess in het vak Componenten in. Glitch werkt uitstekend voor het delen van snelle en gemakkelijke reproducties.

Toon ondersteuning voor de API

Bent u van plan de Local Font Access API te gebruiken? Uw publieke steun helpt het Chrome-team prioriteiten te stellen voor functies en laat andere browserleveranciers zien hoe belangrijk het is om deze te ondersteunen.

Stuur een tweet naar @ChromiumDev met de hashtag #LocalFontAccess en laat ons weten waar en hoe u deze gebruikt.

Dankbetuigingen

De Local Font Access API-specificatie is bewerkt door Emil A. Eklund , Alex Russell , Joshua Bell en Olivier Yiptong . Dit artikel is beoordeeld door Joe Medley , Dominik Röttsches en Olivier Yiptong . Heldenafbeelding door Brett Jordan op Unsplash .