Overlay der Fenstersteuerelemente in der Titelleiste der PWA anpassen

Verwenden Sie den Bereich der Titelleiste neben den Fenstersteuerelementen, damit Ihre PWA eher wie eine App wirkt.

Wenn Sie sich an meinen Artikel Eine App wie eine App gestalten erinnern, erinnern Sie sich vielleicht daran, wie ich erwähnt habe, dass Sie die Titelleiste Ihrer App angepasst haben, um eine App-ähnliche User Experience zu schaffen. Hier ist ein Beispiel, wie dies mit der macOS Podcasts App aussehen könnte.

Titelleiste der macOS Podcasts App mit Schaltflächen zur Mediensteuerung und Metadaten zum aktuell wiedergegebenen Podcast.
Durch eine benutzerdefinierte Titelleiste wirkt deine PWA eher wie eine plattformspezifische App.

Jetzt mag es verlockend sein, zu beanstanden, dass Podcasts eine plattformspezifische macOS-App ist, die nicht in einem Browser ausgeführt wird und daher tun kann, was sie möchte, ohne sich an die Regeln des Browsers halten zu müssen. Richtig, aber die gute Nachricht ist, dass Sie mit der Funktion „Overlay für Fenstersteuerelemente“, um die es in diesem Artikel geht, in Kürze ähnliche Benutzeroberflächen für Ihre PWA erstellen können.

Overlay-Komponenten für Fenstersteuerelemente

Das Overlay für Fenstersteuerelemente besteht aus vier Unterfunktionen:

  1. Der Wert "window-controls-overlay" für das Feld "display_override" im Manifest der Web-App.
  2. Die CSS-Umgebungsvariablen titlebar-area-x, titlebar-area-y, titlebar-area-width und titlebar-area-height.
  3. Die Standardisierung der zuvor proprietären CSS-Eigenschaft -webkit-app-region als app-region-Eigenschaft, um ziehbare Regionen in Webinhalten zu definieren.
  4. Ein Mechanismus zum Abfragen und Umgehen des Bereichs der Fenstersteuerung über das Mitglied windowControlsOverlay von window.navigator.

Was ist ein Overlay für Fenstersteuerelemente?

Der Titelleistenbereich bezieht sich auf den Raum links oder rechts neben den Fenstersteuerelementen (d. h. die Schaltflächen zum Minimieren, Maximieren, Schließen usw.) und enthält häufig den Titel der Anwendung. Mit Fenstersteuerelementen-Overlay können progressive Web-Apps (PWAs) eine App-ähnliche Wirkung haben, indem die vorhandene Titelleiste mit voller Breite durch ein kleines Overlay mit den Fenstersteuerelementen ersetzt wird. Auf diese Weise können Entwickler benutzerdefinierte Inhalte im bisherigen browsergesteuerten Bereich der Titelleiste platzieren.

Aktueller Status

Step Status
1. Erklärende Erklärung erstellen Abschließen
2. Ersten Entwurf der Spezifikation erstellen Abschließen
3. Feedback einholen und Design iterieren In Bearbeitung
4. Ursprungstest Abschließen
5. Launch Abgeschlossen (in Chromium 104)

So verwenden Sie das Overlay für Fenstersteuerelemente

window-controls-overlay wird dem Web-App-Manifest hinzugefügt

Bei einer progressiven Web-App kann das Overlay für Fenstersteuerelemente aktiviert werden, indem "window-controls-overlay" im Web-App-Manifest als primäres "display_override"-Mitglied hinzugefügt wird:

{
  "display_override": ["window-controls-overlay"]
}

Das Overlay für Fenstersteuerelemente ist nur sichtbar, wenn alle der folgenden Bedingungen erfüllt sind:

  1. Die App wird nicht im Browser geöffnet, sondern in einem separaten PWA-Fenster.
  2. Das Manifest enthält "display_override": ["window-controls-overlay"]. Andere Werte sind anschließend zulässig.
  3. Die PWA wird auf einem Computerbetriebssystem ausgeführt.
  4. Der aktuelle Ursprung stimmt mit dem Ursprung überein, für den die PWA installiert wurde.

Dies führt zu einem leeren Titelleistenbereich mit den regulären Fenstersteuerelementen auf der linken oder rechten Seite, je nach Betriebssystem.

Ein App-Fenster mit einer leeren Titelleiste und den Fenstersteuerelementen auf der linken Seite.
Eine leere Titelleiste für benutzerdefinierte Inhalte.

Inhalte in die Titelleiste verschieben

Da die Titelleiste jetzt Platz bietet, können Sie etwas dorthin verschieben. Für diesen Artikel habe ich eine Wikimedia Featured Content erstellt. Eine nützliche Funktion für diese App ist z. B. die Suche nach Wörtern in den Artikeltiteln. Der HTML-Code für die Suchfunktion sieht wie folgt aus:

<div class="search">
  <img src="logo.svg" alt="Wikimedia logo." width="32" height="32" />
  <label>
    <input type="search" />
    Search for words in articles
  </label>
</div>

Um dieses div nach oben in die Titelleiste zu verschieben, wird CSS-Code benötigt:

.search {
  /* Make sure the `div` stays there, even when scrolling. */
  position: fixed;
  /**
   * Gradient, because why not. Endless opportunities.
   * The gradient ends in `#36c`, which happens to be the app's
   * `<meta name="theme-color" content="#36c">`.
   */
  background-image: linear-gradient(90deg, #36c, #131313, 33%, #36c);
  /* Use the environment variable for the left anchoring with a fallback. */
  left: env(titlebar-area-x, 0);
  /* Use the environment variable for the top anchoring with a fallback. */
  top: env(titlebar-area-y, 0);
  /* Use the environment variable for setting the width with a fallback. */
  width: env(titlebar-area-width, 100%);
  /* Use the environment variable for setting the height with a fallback. */
  height: env(titlebar-area-height, 33px);
}

Im Screenshot unten sehen Sie die Wirkung dieses Codes. Die Titelleiste ist vollständig responsiv. Wenn Sie die Größe des PWA-Fensters ändern, reagiert die Titelleiste so, als würde sie aus normalem HTML-Inhalt bestehen, was eigentlich der Fall ist.

Ein App-Fenster mit einer Suchleiste in der Titelleiste.
Die neue Titelleiste ist aktiv und responsiv.

Festlegen, welche Teile der Titelleiste ziehbar sind

Der Screenshot oben lässt vermuten, dass Sie fertig sind. Sie sind jedoch noch nicht ganz fertig. Das PWA-Fenster kann nicht mehr gezogen werden (abgesehen von einem sehr kleinen Bereich), da die Schaltflächen der Fenstersteuerung keine Ziehbereiche sind und der Rest der Titelleiste aus dem Such-Widget besteht. Sie können dieses Problem mithilfe der CSS-Eigenschaft app-region mit dem Wert drag beheben. Im konkreten Fall können Sie alles außer dem input-Element ziehbar machen.

/* The entire search `div` is draggable… */
.search {
  -webkit-app-region: drag;
  app-region: drag;
}

/* …except for the `input`. */
input {
  -webkit-app-region: no-drag;
  app-region: no-drag;
}

Mit diesem CSS-Code kann der Nutzer das App-Fenster wie gewohnt durch Ziehen von div, img oder label ziehen. Nur das input-Element ist interaktiv, sodass die Suchanfrage eingegeben werden kann.

Funktionserkennung

Wenn das Vorhandensein von windowControlsOverlay getestet wird, kann die Unterstützung für das Overlay für Fenstersteuerelemente erkannt werden:

if ('windowControlsOverlay' in navigator) {
  // Window Controls Overlay is supported.
}

Bereich für Fenstersteuerung mit windowControlsOverlay abfragen

Bisher hat der Code ein Problem: Auf einigen Plattformen befinden sich die Fenstersteuerelemente auf der rechten Seite, auf anderen auf der linken. Außerdem ändert sich die Position des Chrome-Menüs mit den drei Punkten je nach Plattform. Das bedeutet, dass das Hintergrundbild des linearen Farbverlaufs dynamisch so angepasst werden muss, dass es über #131313maroon oder maroon#131313maroon ausgeführt wird, damit es sich in die Hintergrundfarbe maroon der Titelleiste einfügt, die durch <meta name="theme-color" content="maroon"> bestimmt wird. Dazu fragen Sie die getTitlebarAreaRect() API für das Attribut navigator.windowControlsOverlay ab.

if ('windowControlsOverlay' in navigator) {
  const { x } = navigator.windowControlsOverlay.getTitlebarAreaRect();
  // Window controls are on the right (like on Windows).
  // Chrome menu is left of the window controls.
  // [ windowControlsOverlay___________________ […] [_] [■] [X] ]
  if (x === 0) {
    div.classList.add('search-controls-right');
  }
  // Window controls are on the left (like on macOS).
  // Chrome menu is right of the window controls overlay.
  // [ [X] [_] [■] ___________________windowControlsOverlay [⋮] ]
  else {
    div.classList.add('search-controls-left');
  }
} else {
  // When running in a non-supporting browser tab.
  div.classList.add('search-controls-right');
}

Anstatt das Hintergrundbild direkt in den CSS-Regeln der .search-Klasse zu verwenden (wie zuvor), verwendet der geänderte Code jetzt zwei Klassen, die mit dem obigen Code dynamisch festgelegt werden.

/* For macOS: */
.search-controls-left {
  background-image: linear-gradient(90deg, #36c, 45%, #131313, 90%, #36c);
}

/* For Windows: */
.search-controls-right {
  background-image: linear-gradient(90deg, #36c, #131313, 33%, #36c);
}

Bestimmen, ob das Overlay für Fenstersteuerelemente sichtbar ist

Das Overlay der Fenstersteuerelemente ist nicht immer im Bereich der Titelleiste sichtbar. In Browsern, die die Overlay-Funktion für Fenstersteuerelemente nicht unterstützen, ist sie normalerweise nicht vorhanden. Sie ist aber auch nicht vorhanden, wenn die betreffende PWA in einem Tab ausgeführt wird. Um diese Situation zu erkennen, können Sie das Attribut visible von windowControlsOverlay abfragen:

if (navigator.windowControlsOverlay.visible) {
  // The window controls overlay is visible in the title bar area.
}

Alternativ können Sie auch die Medienabfrage display-mode in JavaScript und/oder CSS verwenden:

// Create the query list.
const mediaQueryList = window.matchMedia('(display-mode: window-controls-overlay)');

// Define a callback function for the event listener.
function handleDisplayModeChange(mql) {
  // React on display mode changes.
}

// Run the display mode change handler once.
handleDisplayChange(mediaQueryList);

// Add the callback function as a listener to the query list.
mediaQueryList.addEventListener('change', handleDisplayModeChange);
@media (display-mode: window-controls-overlay) { 
  /* React on display mode changes. */ 
}

Benachrichtigung über Geometrieänderungen

Die Abfrage des Overlay-Bereichs der Fenstersteuerelemente mit getTitlebarAreaRect() kann für einmalige Aktionen ausreichen, z. B. für die Einstellung des richtigen Hintergrundbilds je nachdem, wo sich die Fenstersteuerelemente befinden. In anderen Fällen ist jedoch eine genauere Steuerung erforderlich. Ein möglicher Anwendungsfall könnte beispielsweise sein, das Overlay der Fenstersteuerung basierend auf dem verfügbaren Platz anzupassen und direkt dort einen Scherz hinzuzufügen, wenn genügend Platz vorhanden ist.

Overlay-Bereich der Fenstersteuerelemente in einem schmalen Fenster mit gekürztem Text.
Steuerelemente für die Titelleiste, die an ein schmales Fenster angepasst wurden.

Sie können sich über Änderungen der Geometrie informieren lassen, indem Sie navigator.windowControlsOverlay.ongeometrychange abonnieren oder einen Event-Listener für das Ereignis geometrychange einrichten. Dieses Ereignis wird nur ausgelöst, wenn das Overlay der Fenstersteuerelemente sichtbar ist, d. h., wenn navigator.windowControlsOverlay.visible den Wert true hat.

const debounce = (func, wait) => {
  let timeout;
  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout);
      func(...args);
    };
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
  };
};

if ('windowControlsOverlay' in navigator) {
  navigator.windowControlsOverlay.ongeometrychange = debounce((e) => {
    span.hidden = e.titlebarAreaRect.width < 800;
  }, 250);
}

Anstatt ongeometrychange eine Funktion zuzuweisen, können Sie auch windowControlsOverlay einen Event-Listener hinzufügen. Informationen zum Unterschied zwischen den beiden finden Sie auf MDN.

navigator.windowControlsOverlay.addEventListener(
  'geometrychange',
  debounce((e) => {
    span.hidden = e.titlebarAreaRect.width < 800;
  }, 250),
);

Kompatibilität beim Ausführen in einem Tab und in nicht unterstützten Browsern

Es gibt zwei mögliche Fälle, die berücksichtigt werden sollten:

  • Der Fall, dass eine App in einem Browser ausgeführt wird, der Window Controls Overlay unterstützt, aber die App in einem Browsertab verwendet wird.
  • Der Fall, dass eine App in einem Browser ausgeführt wird, der das Overlay für Fenstersteuerelemente nicht unterstützt.

In beiden Fällen wird der HTML-Code, der für das Overlay der Fenstersteuerelemente erstellt wurde, standardmäßig inline wie normaler HTML-Inhalt angezeigt und die Fallback-Werte der env()-Variablen werden für die Positionierung übernommen. Bei Browsern, die dies unterstützen, können Sie auch festlegen, dass der HTML-Code, der für das Overlay der Fenstersteuerelemente vorgesehen ist, nicht angezeigt wird. Dazu müssen Sie die visible-Eigenschaft des Overlays prüfen und false melden, damit der HTML-Inhalt ausgeblendet wird.

Eine PWA, die in einem Browsertab ausgeführt wird und im Textkörper das Overlay für Fenstersteuerelemente angezeigt wird.
Steuerelemente für die Titelleiste können in älteren Browsern ganz einfach im Text angezeigt werden.

Zur Erinnerung: Browser, die keine Unterstützung bieten, berücksichtigen die Manifesteigenschaft "display_override" der Web-App entweder gar nicht oder erkennen "window-controls-overlay" nicht und verwenden daher den nächstmöglichen Wert gemäß der Fallback-Kette, z. B. "standalone".

Eine PWA, die im eigenständigen Modus ausgeführt wird, wobei das Overlay für Fenstersteuerelemente im Text angezeigt wird.
Steuerelemente für die Titelleiste können in älteren Browsern ganz einfach im Text angezeigt werden.

Hinweise zur Benutzeroberfläche

Es mag verlockend sein, jedoch wird davon abgeraten, ein klassisches Dropdown-Menü im Overlay-Bereich der Fenstersteuerelemente zu erstellen. Dies würde gegen die Designrichtlinien für macOS verstoßen, einer Plattform, auf der Nutzer Menüleisten (sowohl vom System bereitgestellte als auch benutzerdefinierte) oben auf dem Bildschirm erwarten.

Wenn Ihre App im Vollbildmodus angezeigt wird, überlegen Sie sorgfältig, ob das Overlay für Fenstersteuerelemente sinnvoll ist. Unter Umständen möchten Sie Ihr Layout neu anordnen, wenn das onfullscreenchange-Ereignis ausgelöst wird.

Demo

Ich habe eine Demo erstellt, die Sie in verschiedenen unterstützenden und nicht unterstützten Browsern sowie im installierten und nicht installierten Status ausprobieren können. Wenn Sie das Overlay für Fenstersteuerelemente verwenden möchten, müssen Sie die App installieren. Unten sehen Sie zwei Screenshots. Der Quellcode für die App ist auf Glitch verfügbar.

Die Demo-App „Empfohlene Inhalte“ von Wikimedia mit Fenstersteuerungs-Overlay.
Die Demo-App kann getestet werden.

Die Suchfunktion im Overlay für Fenstersteuerelemente ist voll funktionsfähig:

Die Demo-App „Empfohlene Inhalte“ von Wikimedia mit Fenstersteuerelementen-Overlay und aktiver Suche nach dem Begriff „cleopa...“, wobei ein Artikel mit dem entsprechenden Begriff hervorgehoben wird.
Eine Suchfunktion, die das Overlay für Fenstersteuerelemente verwendet.

Sicherheitsaspekte

Das Chromium-Team hat die Window Controls Overlay API gemäß den unter Zugriff auf leistungsstarke Webplattformfunktionen steuern definierten Grundprinzipien wie Nutzersteuerung, Transparenz und Ergonomie entwickelt und implementiert.

Spoofing

Wenn Websites teilweise Kontrolle über die Titelleiste haben, haben Entwickler die Möglichkeit, Inhalte in einer zuvor vertrauenswürdigen und browsergesteuerten Region zu fälschen. Derzeit enthält der eigenständige Modus in Chromium eine Titelleiste, in der beim ersten Start der Titel der Webseite links und der Ursprung der Seite auf der rechten Seite angezeigt wird. Darauf folgen die Schaltfläche „Einstellungen und mehr“ und die Fenstersteuerelemente. Nach einigen Sekunden verschwindet der ursprüngliche Text. Wenn der Browser auf eine linksläufige Sprache (RTL-Sprache) eingestellt ist, wird dieses Layout so gedreht, dass sich der Ausgangstext links befindet. Dadurch wird das Fenstersteuerungs-Overlay geöffnet, um den Ursprung zu spoofen, wenn der Abstand zwischen dem Ursprung und dem rechten Rand des Overlays nicht ausreicht. Beispielsweise kann dem Ursprung „evil.ltd“ die vertrauenswürdige Website „google.com“ angehängt werden, sodass Nutzer annehmen, dass die Quelle vertrauenswürdig ist. Dieser ursprüngliche Text soll so beibehalten werden, dass Nutzer den Ursprung der App kennen und sicherstellen können, dass er mit ihren Erwartungen übereinstimmt. Bei Browsern mit RTL-Konfiguration muss rechts vom Ursprungstext genügend Abstand vorhanden sein, um zu verhindern, dass eine schädliche Website den unsicheren Ursprung mit einer vertrauenswürdigen Quelle hinzufügt.

Fingerabdruck

Das Aktivieren der Fenstersteuerelemente in den Overlay- und ziehbaren Bereichen haben außer der Funktionserkennung keine nennenswerten Datenschutzbedenken. Aufgrund der unterschiedlichen Größen und Positionen der Fenstersteuerungsschaltflächen in den verschiedenen Betriebssystemen gibt die Methode navigator.windowControlsOverlay.getTitlebarAreaRect() jedoch ein DOMRect zurück, dessen Position und Abmessungen Informationen über das Betriebssystem ergeben, auf dem der Browser ausgeführt wird. Derzeit können Entwickler das Betriebssystem bereits aus dem User-Agent-String ermitteln. Aufgrund von Fingerprinting-Problemen wird jedoch darüber diskutiert, wie der UA-String eingefroren und Betriebssystemversionen vereinheitlicht werden kann. Innerhalb der Browser-Community wird kontinuierlich versucht, zu verstehen, wie häufig sich die Größe des Fensters mit Overlay-Anzeigen auf verschiedenen Plattformen ändert. Derzeit gehen wir davon aus, dass diese über alle Betriebssystemversionen hinweg relativ stabil sind und daher nicht für die Beobachtung von Nebenversionen von Betriebssystem geeignet sind. Dies ist zwar ein potenzielles Problem mit dem Fingerabdruck, gilt aber nur für installierte PWAs, die die Funktion für die benutzerdefinierte Titelleiste verwenden, und gilt nicht für die allgemeine Browsernutzung. Außerdem ist die navigator.windowControlsOverlay API nicht für iFrames verfügbar, die in eine PWA eingebettet sind.

Wenn Sie in einer PWA zu einem anderen Ursprung wechseln, kehrt sie zur normalen eigenständigen Titelleiste zurück, auch wenn sie die oben genannten Kriterien erfüllt und mit dem Overlay für Fenstersteuerelemente gestartet wird. Dadurch wird die schwarze Leiste einbezogen, die bei der Navigation zu einem anderen Start angezeigt wird. Nachdem Sie zum ursprünglichen Ursprung zurückgekehrt sind, wird das Overlay der Fenstersteuerelemente wieder verwendet.

Schwarze URL-Leiste für die Navigation außerhalb des Ursprungsorts
Wenn der Nutzer zu einem anderen Ursprung navigiert, wird eine schwarze Leiste angezeigt.

Feedback

Das Chromium-Team möchte mehr über Ihre Erfahrungen mit der Window Controls Overlay API erfahren.

Informationen zum API-Design

Gibt es etwas an der API, das nicht so funktioniert, wie Sie es erwartet hatten? 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 von Chromium 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 UI>Browser>WebAppInstalls 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 Window Controls Overlay API verwenden? Ihre öffentliche Unterstützung hilft dem Chromium-Team, Funktionen zu priorisieren, und zeigt anderen Browseranbietern, wie wichtig es ist, sie zu unterstützen.

Senden Sie einen Tweet mit dem Hashtag #WindowControlsOverlay an @ChromiumDev und teilen Sie uns mit, wo und wie Sie es verwenden.

Nützliche Links

Danksagungen

Das Overlay für Fenstersteuerelemente wurde von Amanda Baker vom Microsoft Edge-Team implementiert und spezifiziert. Dieser Artikel wurde von Joe Medley und Kenneth Rohde Christiansen geprüft. Hero-Image von Sigmund auf Unsplash