Meta Theme Color und Trickery

Avatar of Manuel Matuzovic
Manuel Matuzovic am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Ab Version 15 unterstützt Safari das theme-color <meta>-Tag sowohl unter macOS als auch unter iOS. Das sind aufregende Neuigkeiten, denn nun unterstützt der erste Desktop-Browser dieses <meta>-Tag und es unterstützt auch das media-Attribut und das prefers-color-scheme Media Feature.

Ich habe dem theme-color Meta-Tag nie viel Beachtung geschenkt, aber jetzt ist es ein guter Zeitpunkt, seine Funktionen und Einschränkungen kennenzulernen und einige interessante Anwendungsfälle zu entdecken.

Heads up! Safari hat die Unterstützung für das theme-color Meta-Tag in Safari Technology Preview (127) entfernt. Das war nur vorübergehend, ab Version 128 wird es wieder unterstützt.

Funktionen und Einschränkungen

So habe ich das theme-color Meta-Tag in den letzten Jahren verwendet: nur ein guter alter Hex-Code für das content-Attribut.

<meta name="theme-color" content="#319197">

Nach Tests, die ich Anfang des Jahres gemacht habe, funktioniert dies in Chrome, Brave und Samsung Internet unter Android, installierten PWAs in Chrome und jetzt auch in Safari Technology Preview.

Die Hex-Farbenunterstützung ist in allen unterstützten Browsern hervorragend.

CSS-Farbunterstützung

Eine der ersten Fragen, die mir in den Sinn kamen, war: "Können wir auch Farbschlüsselwörter, hsl(), rgb() verwenden?" Laut der HTML-Spezifikation kann der Wert des Attributs jede CSS-Farbe sein. Ich habe diesen theme-color Test-CodePen erstellt, um das zu überprüfen.

<meta name="theme-color" content="hsl(24.3, 97.4%, 54.3%)">
Blank webpage with orange header.
Die theme-color Meta-Tags unterstützen CSS-Farben in jeder Form: Schlüsselwörter, rgb(), hsl() oder Hex-Code.
Blank webpage with a hot pink header. There are controls to the right of the webpage for browser testing.
Blick auf Chrome 90 auf einem Android Galaxy S20

Alle unterstützten Browser unterstützen auch hsl() und rgb(). Das ist großartig, weil es uns ermöglicht, einige ziemlich coole Dinge mit JavaScript zu tun. Wir werden später darüber sprechen, aber zuerst sehen wir uns einige Einschränkungen an.

Transparenz

HEX-Codes, rbg(), hsl() und Schlüsselwörter werden gut und konsistent unterstützt, aber Farben, die Transparenz enthalten: nicht so sehr. Eigentlich werden sie in den meisten Browsern unterstützt, aber die Ergebnisse sind nicht sehr konsistent und manchmal unerwartet.

transparent ist eine CSS-Farbe und wenn sie im theme-color Meta-Tag verwendet wird, machen die meisten Browser das Erwartete. Alle normalen mobilen Browser ändern keine Farbe und zeigen die Standard-Tab-Leiste an, aber Safari unter macOS und die Chrome Canary PWA unter macOS machen die Tab-Leiste schwarz. Die PWA unter Android greift auf theme-color zurück, das in manifest.json definiert ist, worüber wir gleich sprechen werden.

Examples of the same white webpage with either white or dark headers with the browser vendor labeled above each one.
Browser mit einem transparenten theme-color Meta-Tag

Alle Browser interpretieren hsla() und rgba(), aber sie setzen den Alpha-Wert auf 1. Die einzige Ausnahme ist Safari unter macOS; es interpretiert die Transparenz, aber es scheint, dass die transparente Farbe eine schwarze Basislinie hat. Dies hat zur Folge, dass die hellorange Farbe wie dunkles Orange aussieht.

Same browser comparison but all with orange headers, except Safari which is a darker brown.
hsla() angewendet auf das theme-color Meta-Tag

Neue Farbfunktionen

Safari 15 ist der erste Browser, der die Farbfunktionen lab(), lch() und hwb() unterstützt. Diese Funktionen funktionieren, wenn Sie sie in CSS verwenden, aber nicht, wenn Sie sie im theme-color Meta-Tag verwenden.

Alle drei Deklarationen funktionieren in Safari 15 einwandfrei

body {
  background-color: hwb(27 10% 28%);
  background-color: lch(67.5345% 42.5 258.2);
  background-color: lab(62.2345% -34.9638 47.7721);
}

Wenn Sie eine der neuen Farbfunktionen im theme-color Meta-Tag verwenden, interpretiert Safari diese nicht und greift auf seinen eigenen Algorithmus zur Farbauswahl zurück. Es ist wahrscheinlich, dass Safari die Hintergrundfarbe Ihres <body> für die theme-color verwendet, was bedeutet, dass Sie möglicherweise das erwartete Ergebnis erhalten, ohne die theme-color explizit zu definieren.

<meta name="theme-color" content="lab(29.2345% 39.3825 20.0664)">
Green webpage with green header.

Bitte beachten Sie, dass Safari 15 zum Zeitpunkt der Erstellung der einzige Browser ist, der diese neuen Farbfunktionen unterstützt.

currentColor

Wenn CSS-Farben unterstützt werden, sollte currentColor auch funktionieren, oder? Nein, leider nicht in irgendeinem Browser. Es ist wahrscheinlich ein ungewöhnlicher Anwendungsfall, aber ich würde erwarten, dass wir die theme-color auf die aktuelle Farbe des <body>- oder <html>-Elements setzen können.

<style>
  body {
    color: blue;
  }
</style>

<meta name="theme-color" content="currentColor">

Ich habe ein Ticket im WebKit-Bugtracker gefunden mit dem Titel "<meta name="theme-color" content="..."> sollte auch CSS currentcolor unterstützen." Die Unterstützung könnte sich in Zukunft ändern, wenn jemand das Ticket aufgreift.

Verbotene Farben

Als ich CSS-Farbschlüsselwörter testete, verwendete ich die Farbe red, und es funktionierte nicht. Zuerst dachte ich, dass Schlüsselwörter nicht unterstützt werden, aber blue, hotpink und green funktionierten einwandfrei. Wie sich herausstellt, gibt es einen engen Farbbereich, den Safari nicht unterstützt, Farben, die die Verwendung der Benutzeroberfläche beeinträchtigen würden. red funktioniert nicht, weil es optisch zu nahe an der Hintergrundfarbe des Schließknopfes in der Tab-Leiste liegt. Diese Einschränkung ist spezifisch für Safari, in allen anderen unterstützten Browsern scheint jede Farbe einwandfrei zu funktionieren.

Wbite webpage with a color picker set to red. The header of the browser is white.
Wenn Sie die theme-color auf red setzen, verwendet Safari jede Farbe, die es für angemessen hält.

Benutzerdefinierte Eigenschaften

Ich weiß nicht genug über die Interna von Browsern und benutzerdefinierten Eigenschaften und ob es überhaupt möglich ist, auf benutzerdefinierte Eigenschaften im <head> zuzugreifen, aber ich habe es trotzdem versucht. Leider hat es in keinem Browser funktioniert.

<style>
  :root {
    --theme: blue;
  }
</style>

<meta name="theme-color" content="var(--theme)">

Das ist ziemlich alles, was ich über die grundlegende Unterstützung des theme-color Meta-Tags wissen wollte. Als Nächstes sehen wir uns an, wie man den Dunkelmodus für die Tab-Leiste implementiert und wie nicht.

Dunkelmodus

Safari 15 ist der erste Desktop-Browser, der das media-Attribut und die prefers-color-scheme Media Feature auf theme-color Meta-Tags unterstützt. Ab Version 93 unterstützt Chrome dies ebenfalls, aber nur für installierte Progressive Web Apps.

Laut der Web-App-Manifest-Seite auf web.dev wählen Browser, wenn Sie mehrere theme-color Meta-Tags definieren, das erste Tag aus, das übereinstimmt.

<meta name="theme-color" content="#872e4e" media="(prefers-color-scheme: dark)">

Ich war gespannt darauf, herauszufinden, was in Browsern passiert, die das media-Attribut nicht unterstützen. Ich habe eine Demo-Seite zum Testen des Dunkelmodus erstellt, die die obigen Meta-Tags enthält und es Ihnen auch ermöglicht, die Website als PWA zu installieren. Die webmanifest.json enthält eine weitere Farbbestimmung für die theme-color.

{
  "name": "My PWA",
  "icons": [
    {
      "src": "https://via.placeholder.com/144/00ff00",
      "sizes": "144x144",
      "type": "image/png"
    }
  ],
  "start_url": "/theme-color-darkmode.html",
  "display": "standalone",
  "background_color": "hsl(24.3, 97.4%, 54.3%)",
  "theme_color": "hsl(24.3, 97.4%, 54.3%)"
}

So zeigen unterstützte Browser die Tab-Leiste im Lichtmodus an. Es spielt keine Rolle, ob ein Browser das media-Attribut unterstützt oder nicht, er wird den ersten Meta-Tag unabhängig davon interpretieren.

So sieht die Tab-Leiste auf derselben Seite im Dunkelmodus aus. Diese Ergebnisse sind interessanter, da sie leicht variieren. Die Canary PWA und Safari unterstützen und zeigen die dunkle Farbe an. Alle mobilen Browser verwenden ihr Standard-Styling für die dunkle Tab-Leiste, mit Ausnahme von Samsung Internet, das das helle Styling verwendet, da es das prefers-color-scheme Media Feature nicht unterstützt. (TIL: Das sollte sich in naher Zukunft ändern.)

Ich habe einen letzten Test gemacht. Ich wollte sehen, was passiert, wenn ich nur eine Theme-Farbe für den Dunkelmodus definiere, aber die Seite im Lichtmodus aufrufe.

<meta name="theme-color" content="#872e4e" media="(prefers-color-scheme: dark)">

Diese Ergebnisse haben mich am meisten überrascht, da ich erwartet hatte, dass alle mobilen Browser das media-Attribut ignorieren und trotzdem die dunkle Farbe im Meta-Tag verwenden würden. Aber der normale Chrome Canary ignoriert die gesamte Meta-Tag, auch wenn er das media-Attribut nicht unterstützt. Wie erwartet, greifen beide Canary PWAs auf die in der Manifestdatei definierte Farbe zurück.

Das andere Interessante ist, dass Safari eine theme-color anzeigt, obwohl ich keine für den Lichtmodus definiert habe. Das liegt daran, dass Safari selbst eine Farbe auswählt, wenn Sie keine theme-color angeben. In diesem Fall verwendet es die Hintergrundfarbe der Seite, aber es könnte auch die Hintergrundfarbe des <header>-Elements verwenden, zum Beispiel.

Wenn Sie eine Theme-Farbe für Licht- und Dunkelmodus definieren möchten, ist es am besten, beide Farben zu definieren und den ersten Meta-Tag als Fallback für Browser zu verwenden, die das Media-Feature nicht unterstützen.

<meta name="theme-color" content="#319197" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#872e4e" media="(prefers-color-scheme: dark)">

Safari hat bewiesen, dass theme-color auch auf Desktop-Browsern hervorragend funktioniert. Ich bin sicher, dass Designer und Entwickler viele kreative Wege finden werden, dieses Meta-Tag zu nutzen, besonders da der Wert über JavaScript geändert werden kann. Ich habe einige interessante Demos zur Inspiration gesammelt und erstellt.

Demos und Anwendungsfälle

Theming

poolsuite.net bietet verschiedene Themes für die Website und ändert die theme-color entsprechend.

Max Böck ändert ebenfalls die theme-color auf seiner Website, wenn Sie das Theme wechseln.

Seiten-Theming

Die meisten Websites bieten keine benutzerdefinierten Themes, aber Sie können Ihren Seiten trotzdem das gewisse Etwas verleihen. Dave verwendet verschiedene Schlüsselfarben in seinen Blog-Posts für Links und Icons und jetzt auch in der Tab-Leiste.

Verläufe

Wenn Sie Verläufe auf Ihrer Seite verwenden, können Sie Ihr Styling hervorheben, indem Sie den Verlauf über den gesamten Browser spannen lassen. Das theme-color Meta-Tag unterstützt keine Verläufe, aber Sie können die gleiche Farbe für das Meta-Tag und die Startfarbe des Verlaufs des Hintergrunds Ihrer Seite verwenden.

<meta name="theme-color" content="rgb(0, 235, 255)">

<style>
  body {
    background: linear-gradient(rgb(0, 235, 255), #08124a);
  }
</style>
Formularvalidierung

Ich habe diesen Proof of Concept eines Formulars, das die theme-color bei der Formularvalidierung ändert, gebaut. Es beginnt mit einer blauen Tab-Leiste, die rot wird, wenn die übermittelten Daten ungültig sind, oder grün, wenn sie gültig sind.

const email = document.querySelector('input')
const themeColor = document.querySelector('meta[name="theme-color"]')
const msg = document.querySelector('[aria-live]')
let color = '#FA0000'
let message = 'Error message'

document.querySelector('button').addEventListener('click', (e) => {
  e.preventDefault()

  email.reportValidity()
  email.setAttribute('aria-invalid', true)

  if (email.validity.valid) {
    color = '#00FF00'
    message = "Success message!"
    email.setAttribute('aria-invalid', false)
  }

  msg.textContent = message
  themeColor.setAttribute('content', color)
});
Disco-Modus

Ich sage nicht, dass Sie es tun sollten, aber Sie könnten Ihre Website im 💃 Disco Mode 🕺 im Kombination mit setInterval und hsl() Farben erstellen.

/*
Inspired by https://twitter.com/argyleink/status/1408184587885309952
*/

const motion = window.matchMedia("(prefers-reduced-motion: no-preference)");

// Check if users don't have a preference for reduced motion
if (motion.matches) {
  let scheme = document.querySelector('meta[name="theme-color"]')
  let hue = 0
  let color

  setInterval(() => {
    color = `hsl(${hue+=5} 50% 30%)`
    document.body.style.background = color;
    scheme.setAttribute('content', color)
  }, 50)
Scrollen

Stuart hatte eine großartige Idee, er schlug vor, die Theme-Farbe beim Scrollen zu ändern. Ich habe diesen schnellen Prototyp gebaut, wieder mit hsl()-Farben.

Bitte tun Sie dies nur, wenn es die Leistung nicht negativ beeinträchtigt.

Max hat eine Demo erstellt, in der er die theme-color basierend auf der Hintergrundfarbe des aktuellen Abschnitts im Viewport mittels Intersection Observer ändert.

const setThemeColor = (color) => {
  const meta = document.querySelector('meta[name="theme-color"]')
  if (meta) {
    meta.setAttribute('content', color)
  }
}

if ("IntersectionObserver" in window) {
  const observer = new IntersectionObserver(entries => {
      entries.forEach(entry => {
        const { isIntersecting, target } = entry
        if (isIntersecting) {
          const color = window.getComputedStyle(target).getPropertyValue("background-color");
          setThemeColor(color)
        }
      })
  }, {
    root: document.getElementById('viewport'),
    rootMargin: "1px 0px -100% 0px",
    treshold: 0.1
  })
  
  document.querySelectorAll('.section').forEach(section => {
    observer.observe(section)
  })
}
Farbe extrahieren

Eine weitere interessante Idee ist, die dominante oder durchschnittliche Farbe aus Ihren Header-Bildern automatisch zu extrahieren und sie als theme-color zu verwenden.

<script type="module">
  import fastAverageColor from "https://cdn.skypack.dev/[email protected]";
  const fac = new fastAverageColor();
    
  fac.getColorAsync(document.querySelector('img'))
    .then(color => {
      document.querySelector('meta[name="theme-color"]').setAttribute('content', color.rgba)
    })
    .catch(e => {
      console.log(e);
    });
</script> 
  
<img src="/amy-humphries-2M_sDJ_agvs-unsplash.jpg" alt="A sea star on blue sand." />

Das ist nur eine Handvoll Ideen, aber ich mag bereits, wohin die Reise geht, und ich bin sicher, dass Sie sich noch kreativere Wege einfallen lassen werden, das theme-color Meta-Tag zu nutzen.

Ressourcen