Erweiterte Typografie mit lokalen Schriftarten verwenden

Hier erfahren Sie, wie Sie mit der Local Font Access API auf die lokal installierten Schriftarten des Nutzers zugreifen und grundlegende Details zu ihnen abrufen können.

Websichere Schriftarten

Wenn Sie schon lange genug mit der Webentwicklung beschäftigt sind, erinnern Sie sich vielleicht an die sogenannten websicheren Schriftarten. Diese Schriftarten sind bekanntermaßen in fast allen Instanzen der am häufigsten verwendeten Betriebssysteme verfügbar (Windows, macOS, den gängigsten Linux-Distributionen sowie Android und iOS). Anfang der 2000er-Jahre startete Microsoft sogar eine Initiative namens TrueType Core Fonts for the Web, bei der diese Schriftarten kostenlos zum Download zur Verfügung gestellt wurden. Ziel war es, „auf einer Website, auf der sie angegeben werden, die Seiten genau so zu sehen, wie der Website-Designer vorgesehen hat“. Ja, dazu gehören auch Websites, die in Comic Sans MS festgelegt wurden. Hier ist ein klassischer websicherer Font Stack (mit dem letzten Fallback auf die jeweilige Schriftart in sans-serif), die so aussehen könnte:

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

Web-Schriftarten

Die Zeiten, in denen websichere Schriftarten wirklich wichtig waren, sind längst vorbei. Heute gibt es Webschriftarten, von denen einige sogar variable Schriftarten sind. Diese können Sie weiter optimieren, indem Sie die Werte für die verschiedenen sichtbaren Achsen ändern. Sie können Webschriftarten verwenden, indem Sie einen @font-face-Block am Anfang des CSS-Codes deklarieren, in dem die herunterzuladenden Schriftartdateien angegeben sind:

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

Anschließend können Sie die benutzerdefinierte Webschriftart verwenden. Dazu geben Sie wie gewohnt font-family an:

body {
  font-family: 'FlamboyantSansSerif';
}

Lokale Schriftarten als Fingerabdruckvektor

Die meisten Schriftarten stammen aus dem Web. Interessanterweise kann das Attribut src in der @font-face-Deklaration, abgesehen von der Funktion url(), auch eine local()-Funktion akzeptieren. Dadurch können benutzerdefinierte Schriftarten lokal geladen werden (Überraschung!). Wenn der Nutzer FlamboyantSansSerif auf seinem Betriebssystem installiert hat, wird die lokale Kopie verwendet, anstatt sie herunterzuladen:

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

Dieser Ansatz bietet einen schönen Fallback-Mechanismus, der möglicherweise Bandbreite spart. Im Internet können wir leider keine schönen Dinge haben. Das Problem bei der Funktion local() besteht darin, dass sie für Browser-Fingerprinting missbraucht werden kann. Die Liste der vom Nutzer installierten Schriftarten kann ziemlich identifizierbar sein. Viele Unternehmen haben eigene Unternehmensschriftarten, die auf den Laptops der Mitarbeiter installiert sind. Google hat beispielsweise eine Unternehmensschriftart namens Google Sans.

Die macOS Font Book App mit einer Vorschau der Schriftart „Google Sans“.
Die Schriftart „Google Sans“ auf dem Laptop eines Google-Mitarbeiters.

Ein Angreifer kann versuchen, herauszufinden, für welches Unternehmen jemand arbeitet. Dazu testet er eine große Anzahl bekannter Unternehmensschriftarten wie Google Sans. Der Angreifer versuchte, den in diesen Schriftarten festgelegten Text auf einem Canvas zu rendern und die Glyphen zu messen. Entsprechen die Glyphen der bekannten Form der Unternehmensschrift, hat der Angreifer einen Treffer. Wenn die Glyphen nicht übereinstimmen, weiß der Angreifer, dass eine Standardersatzschrift verwendet wurde, da die Unternehmensschrift noch nicht installiert war. Weitere Informationen zu diesem und anderen Browser-Fingerprinting-Angriffen finden Sie im Umfragedokument von Laperdix et al.

Abgesehen von Unternehmensschriftarten kann bereits nur die Liste der installierten Schriftarten identifiziert werden. Die Situation mit diesem Angriffsvektor ist so schlimm geworden, dass sich das WebKit-Team kürzlich entschieden hat, "nur [in der Liste der verfügbaren Schriftarten] Webschriftarten und Schriftarten aufzunehmen, die im Betriebssystem enthalten sind, aber keine lokal vom Nutzer installierten Schriftarten. Und hier bin ich mit einem Artikel darüber, wie man Zugriff auf lokale Schriftarten gewährt.

Local Font Access API

Der Anfang dieses Artikels hat Sie möglicherweise negativ empfunden. Können wir wirklich keine Schönen haben? Kein Problem. Wir glauben das, und vielleicht ist nicht alles hoffnungslos. Aber zuerst möchte ich eine Frage beantworten, die Sie sich vielleicht stellen.

Warum brauchen wir die Local Font Access API, wenn es Webschriftarten gibt?

In der Vergangenheit war es schwierig, im Web professionelle Design- und Grafiktools bereitzustellen. Ein Stolperstein war die Unmöglichkeit, auf die gesamte Vielfalt an professionell erstellten Schriftarten mit Hinweisen zuzugreifen, die Designer lokal installiert haben. Webschriftarten ermöglichen zwar einige Anwendungsfälle für die Veröffentlichung, ermöglichen jedoch keinen programmatischen Zugriff auf die Vektorsymbolformen und Schrifttabellen, die von Rastern zum Rendern der Glyphenumrisse verwendet werden. Ebenso ist es nicht möglich, auf die Binärdaten einer Webschriftart zuzugreifen.

  • Designtools benötigen Zugriff auf Schriftbyte, um eine eigene OpenType-Layoutimplementierung durchzuführen und Designtools auf niedrigeren Ebenen einzubinden, z. B. für Vektorfilter oder Transformationen der Glyphenformen.
  • Möglicherweise haben Entwickler ältere Font Stacks für ihre Anwendungen, die sie ins Web stellen. Um diese Stacks verwenden zu können, benötigen sie in der Regel direkten Zugriff auf Schriftartdaten, was Webschriftarten nicht bieten.
  • Einige Schriftarten sind möglicherweise nicht für die Übermittlung über das Web lizenziert. So hat Linotype beispielsweise eine Lizenz für einige Schriftarten, die nur die Desktopnutzung umfassen.

Mit der Local Font Access API möchten wir diese Probleme lösen. Sie besteht aus zwei Teilen:

  • Eine Font Enumeration API, mit der Nutzer Zugriff auf alle verfügbaren Systemschriftarten gewähren können.
  • Die Möglichkeit, von jedem Aufzählungsergebnis einen (byte-orientierten) SFNT-Containerzugriff auf unterer Ebene anzufordern, der die vollständigen Schriftartdaten enthält.

Unterstützte Browser

Unterstützte Browser

  • 103
  • 103
  • x
  • x

Quelle

Local Font Access API verwenden

Funktionserkennung

So prüfen Sie, ob die Local Font Access API unterstützt wird:

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

Lokale Schriftarten auflisten

Um eine Liste der lokal installierten Schriftarten zu erhalten, müssen Sie window.queryLocalFonts() aufrufen. Dadurch wird beim ersten Mal eine Berechtigungsaufforderung ausgelöst, die der Nutzer genehmigen oder ablehnen kann. Wenn der Nutzer die Abfrage seiner lokalen Schriftarten genehmigt, gibt der Browser ein Array mit Schriftartendaten zurück, die Sie durchlaufen können. Jede Schriftart wird als FontData-Objekt mit den Eigenschaften family (z. B. "Comic Sans MS"), fullName (z. B. "Comic Sans MS"), postscriptName (z. B. "ComicSansMS") und style (z. B. "Regular") dargestellt.

// 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);
}

Wenn Sie nur an einem Teil der Schriftarten interessiert sind, können Sie diese auch anhand der PostScript-Namen filtern. Fügen Sie dazu einen postscriptNames-Parameter hinzu.

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

Auf SFNT-Daten zugreifen

Der vollständige SFNT-Zugriff ist über die blob()-Methode des FontData-Objekts verfügbar. SFNT ist ein Schriftart-Dateiformat, das auch andere Schriftarten wie PostScript, TrueType, OpenType, WOFF-Schriftarten (Web Open Font Format) und andere enthalten kann.

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 der Demo unten kannst du die Local Font Access API in Aktion sehen. Sehen Sie sich auch den Quellcode an. In der Demo ist ein benutzerdefiniertes Element namens <font-select> zu sehen, mit dem eine lokale Schriftartauswahl implementiert wird.

Datenschutz

Die Berechtigung "local-fonts" bietet eine Oberfläche mit hoher Fingerabdruckerkennung. Browser können jedoch alles zurückgeben, was sie möchten. Bei Browsern mit Schwerpunkt auf Anonymität kann beispielsweise nur eine Reihe von Standardschriftarten in den Browser integriert werden. Außerdem müssen Browser Tabellendaten nicht genau so bereitstellen, wie sie auf der Festplatte angezeigt werden.

Die Local Font Access API ist nach Möglichkeit so konzipiert, dass sie nur genau die Informationen zur Verfügung stellt, die für die genannten Anwendungsfälle erforderlich sind. System-APIs können eine Liste der installierten Schriftarten nicht in zufälliger oder sortierter Reihenfolge, sondern in der Reihenfolge ihrer Installation erstellen. Die Rückgabe genau der Liste installierter Schriftarten, die von einer solchen System-API bereitgestellt wird, kann zusätzliche Daten zur Verfügung stellen, die für das Fingerprinting verwendet werden können. Durch die Beibehaltung dieser Reihenfolge können Anwendungsfälle, die aktiviert werden sollen, nicht unterstützt werden. Daher müssen die zurückgegebenen Daten für diese API sortiert werden, bevor sie zurückgegeben werden.

Sicherheit und Berechtigungen

Das Chrome-Team hat die Local Font Access API gemäß den unter Zugriff auf leistungsstarke Webplattformfunktionen steuern definierten Grundprinzipien wie Nutzersteuerung, Transparenz und Ergonomie entworfen und implementiert.

Nutzersteuerung

Der Zugriff auf die Schriftarten eines Nutzers unterliegt vollständig seiner Kontrolle und wird nur gewährt, wenn die Berechtigung "local-fonts", wie in der Berechtigungs-Registry aufgeführt, gewährt wurde.

Transparenz

Im Tabellenblatt mit Websiteinformationen wird angezeigt, ob einer Website Zugriff auf die lokalen Schriftarten des Nutzers gewährt wurde.

Berechtigungspersistenz

Die Berechtigung "local-fonts" bleibt zwischen dem Neuladen der Seite bestehen. Er kann über das Tabellenblatt Websiteinformationen widerrufen werden.

Feedback

Das Chrome-Team möchte gern mehr über Ihre Erfahrungen mit der Local Font Access API erfahren.

Informationen zum API-Design

Gibt es etwas an der API, das nicht so funktioniert, wie Sie erwartet haben? Oder fehlen Methoden oder Eigenschaften, um Ihre Idee zu implementieren? Haben Sie eine Frage oder einen Kommentar zum Sicherheitsmodell? Sie können ein Spezifikationsproblem im entsprechenden GitHub-Repository melden oder Ihre Gedanken zu einem vorhandenen Problem hinzufügen.

Problem mit der Implementierung melden

Haben Sie einen Fehler bei der Implementierung in Chrome gefunden? Oder unterscheidet sich die Implementierung von der Spezifikation? Melden Sie einen Fehler unter new.crbug.com. Geben Sie so viele Details wie möglich und eine einfache Anleitung zum Reproduzieren an. Geben Sie Blink>Storage>FontAccess in das Feld Komponenten ein. Glitch eignet sich perfekt, um schnelle und einfache Reproduzierungen zu teilen.

Unterstützung für die API zeigen

Möchten Sie die Local Font Access API verwenden? Ihre öffentliche Unterstützung hilft dem Chrome-Team, Funktionen zu priorisieren, und zeigt anderen Browseranbietern, wie wichtig es ist, sie zu unterstützen.

Senden Sie einen Tweet mit dem Hashtag #LocalFontAccess an @ChromiumDev und teilen Sie uns mit, wo und wie Sie das Tool verwenden.

Danksagungen

Die Spezifikation für die Local Font Access API wurde von Emil A. Eklund, Alex Russell, Joshua Bell und Olivier Yiptong. Dieser Artikel wurde von Joe Medley, Dominik Röttsches und Olivier Yiptong gelesen. Hero-Image von Brett Jordan auf Unsplash