Miglioramento dello stile predefinito della modalità Buio con la proprietà CSS color-scheme e il meta tag corrispondente

La proprietà CSS color-scheme e il meta tag corrispondente consentono agli sviluppatori di attivare le impostazioni predefinite specifiche per il tema del foglio di stile dello user agent per le loro pagine.

La funzionalità Media delle preferenze utente di prefers-color-scheme offre agli sviluppatori il pieno controllo sull'aspetto delle loro pagine. Se non la conosci, leggi il mio articolo prefers-color-scheme: Ciao oscurità, mia vecchia amica, in cui ho documentato tutto ciò che so sulla creazione di esperienze in modalità Buio straordinarie.

Un elemento del puzzle che è stato menzionato solo brevemente nell'articolo è la proprietà CSS color-scheme e il metatag corrispondente dello stesso nome. Entrambi semplificano la vita degli sviluppatori consentendoti di attivare nella pagina i valori predefiniti specifici del tema dello stile CSS dello user agent, ad esempio i controlli dei moduli, le barre di scorrimento e i colori di sistema CSS. Allo stesso tempo, questa funzionalità impedisce ai browser di applicare autonomamente trasformazioni.

Supporto browser

prefers-color-scheme

Supporto dei browser

  • Chrome: 76.
  • Edge: 79.
  • Firefox: 67.
  • Safari: 12.1.

Origine

color-scheme

Supporto dei browser

  • Chrome: 81.
  • Edge: 81.
  • Firefox: 96.
  • Safari: 13.

Origine

Il foglio di stile dello user agent

Prima di continuare, descrivo brevemente che cos'è un foglio di stile per user agent. Nella maggior parte dei casi, puoi considerare la parola user agent (UA) come un modo elegante per dire browser. Il foglio di stile UA determina l'aspetto predefinito di una pagina. Come suggerisce il nome, un foglio di stile UA è qualcosa che dipende dalla UA in questione. Puoi dare un'occhiata al foglio di stile UA di Chrome (e Chromium) e confrontarlo con quello di Firefox o Safari (e WebKit). In genere, gli stili CSS UA sono d'accordo sulla maggior parte degli elementi. Ad esempio, rendono i link blu, il testo generico nero e il colore di sfondo bianco, ma esistono anche differenze importanti (e a volte fastidiose), ad esempio lo stile dei controlli del modulo.

Dai un'occhiata più da vicino al foglio di stile UA di WebKit e al funzionamento della modalità Buio. Esegui una ricerca completa del testo per "dark" nel foglio di stile. Il valore predefinito fornito dal foglio di stile cambia a seconda che la modalità oscura sia attiva o meno. Per esemplificare, di seguito è riportata una di queste regole CSS che utilizza la pseudoclasse :matches e le variabili interne di WebKit come -apple-system-control-background, nonché la direttiva del preprocessore interno di WebKit #if defined:

input,
input:matches([type="password"], [type="search"]) {
  -webkit-appearance: textfield;
  #if defined(HAVE_OS_DARK_MODE_SUPPORT) &&
      HAVE_OS_DARK_MODE_SUPPORT
    color: text;
    background-color: -apple-system-control-background;
  #else
    background-color: white;
  #endif
  /* snip */
}

Noterai alcuni valori non standard per le proprietà color e background-color sopra. Né text-apple-system-control-background sono colori CSS validi. Si tratta di colori semantici interni a WebKit.

È emerso che CSS ha colori di sistema semantico standardizzati. Sono specificati nel modulo Colore CSS di livello 4. Ad esempio, Canvas (da non confondere con il tag <canvas>) è destinato allo sfondo dei contenuti o dei documenti dell'applicazione, mentre CanvasText è destinato al testo nei contenuti o nei documenti dell'applicazione. I due tipi sono collegati e non devono essere usati in modo isolato.

I fogli di stile UA possono utilizzare i propri colori proprietari o i colori di sistema semantici standardizzati per determinare in che modo gli elementi HTML devono essere visualizzati per impostazione predefinita. Se il sistema operativo è impostato sulla modalità Buio o utilizza un tema scuro, CanvasText (o text) verrà impostato condizionatamente su bianco, e Canvas (o -apple-system-control-background) su nero. Il foglio di stile UA assegna quindi il seguente CSS una sola volta e copre sia la modalità Luce che Buio.

/**
  Not actual UA stylesheet code.
  For illustrative purposes only.
*/
body {
  color: CanvasText;
  background-color: Canvas
}

La proprietà CSS color-scheme

La specifica del modulo di regolazione del colore CSS di livello 1 introduce un modello e controlli per la regolazione automatica del colore da parte dell'agente utente con l'obiettivo di gestire le preferenze dell'utente, come la modalità scura, la regolazione del contrasto o specifiche combinazioni di colori desiderate.

La proprietà color-scheme definita al suo interno consente a un elemento di indicare con quali combinazioni di colori è possibile visualizzarlo. Questi valori vengono negoziati con le preferenze dell'utente, dando luogo a una combinazione di colori scelta che influisce su elementi dell'interfaccia utente (UI), come i colori predefiniti dei controlli dei moduli e delle barre di scorrimento, nonché sui valori utilizzati dei colori di sistema CSS. Attualmente sono supportati i seguenti valori:

  • normal Indica che l'elemento non è consapevole delle combinazioni di colori, quindi l'elemento deve essere visualizzato con la combinazione di colori predefinita del browser.

  • [ light | dark ]+ Indica che l'elemento è consapevole e può gestire le combinazioni di colori elencate ed esprime una preferenza ordinata tra di loro.

In questo elenco, light rappresenta una combinazione di colori chiara, con colori di sfondo chiari e colori di primo piano scuri, mentre dark rappresenta il contrario, con colori di sfondo scuri e colori di primo piano chiari.

Per tutti gli elementi, il rendering con una combinazione di colori dovrebbe far corrispondere i colori utilizzati in tutte le UI fornite dal browser affinché l'elemento corrisponda all'intento della combinazione di colori. Alcuni esempi sono le barre di scorrimento, le sottolineature per il controllo ortografico, i controlli del modulo e così via.

Nell'elemento :root, il rendering con una combinazione di colori deve inoltre influire sul colore della superficie della tela (ovvero sul colore di sfondo globale), sul valore iniziale della proprietà color e sui valori utilizzati dei colori di sistema, nonché sulle barre di scorrimento della visualizzazione.

/*
  The page supports both dark and light color schemes,
  and the page author prefers dark.
*/
:root {
  color-scheme: dark light;
}

Il meta tag color-scheme

Il rispetto della proprietà CSS color-scheme richiede innanzitutto il download del CSS (se viene fatto riferimento tramite <link rel="stylesheet">) e la sua analisi. Per aiutare gli user agent a visualizzare immediatamente lo sfondo della pagina con la combinazione di colori desiderata, puoi fornire un valore color-scheme anche in un elemento <meta name="color-scheme">.

<!--
  The page supports both dark and light color schemes,
  and the page author prefers dark.
-->
<meta name="color-scheme" content="dark light">

Combinazione di color-scheme e prefers-color-scheme

Poiché sia il meta tag sia la proprietà CSS (se applicata all'elemento :root) generano lo stesso comportamento, consiglio sempre di specificare la combinazione di colori tramite il meta tag, in modo che il browser possa adottare più rapidamente la combinazione preferita.

Sebbene per le pagine di riferimento assolute non siano necessarie ulteriori regole CSS, in generale dovresti sempre combinare color-scheme e prefers-color-scheme. Ad esempio, il colore CSS proprietario di WebKit -webkit-link, utilizzato da WebKit e Chrome per il blu dei link classico rgb(0,0,238), ha un rapporto di contrasto insufficiente di 2,23:1 su uno sfondo nero e non soddisfa sia i requisiti WCAG AA che quelli WCAG AAA.

Ho aperto dei bug per Chrome, WebKit e Firefox nonché un problema meta nello standard HTML per risolvere il problema.

Interazione con prefers-color-scheme

L'interazione della proprietà CSS color-scheme e del meta tag corrispondente con la funzionalità multimediale delle preferenze utente di prefers-color-scheme può inizialmente sembrare confusa. In effetti, giocano molto bene insieme. La cosa più importante da capire è che color-scheme determina esclusivamente l'aspetto predefinito, mentre prefers-color-scheme determina l'aspetto stilizzato. Per maggiore chiarezza, supponiamo che la seguente pagina:

<head>
  <meta name="color-scheme" content="dark light">
  <style>
    fieldset {
      background-color: gainsboro;
    }
    @media (prefers-color-scheme: dark) {
      fieldset {
        background-color: darkslategray;
      }
    }
  </style>
</head>
<body>
  <p>
    Lorem ipsum dolor sit amet, legere ancillae ne vis.
  </p>
  <form>
    <fieldset>
      <legend>Lorem ipsum</legend>
      <button type="button">Lorem ipsum</button>
    </fieldset>
  </form>
</body>

Il codice CSS in linea nella pagina imposta background-color dell'elemento <fieldset> su gainsboro nel caso generale e su darkslategray se l'utente preferisce una combinazione di colori dark in base alla funzionalità dei contenuti multimediali delle preferenze utente prefers-color-scheme.

Tramite l'elemento <meta name="color-scheme" content="dark light">, la pagina comunica al browser che supporta un tema scuro e uno chiaro, con una preferenza per il tema scuro.

A seconda che il sistema operativo sia impostato sulla modalità Buio o Luce, l'intera pagina viene visualizzata in modalità Luce su Buio o viceversa, in base allo stile foglio dell'agente utente. Non è necessario alcun CSS aggiuntivo fornito dagli sviluppatori per modificare il testo del paragrafo o il colore di sfondo della pagina.

Nota come cambia background-color dell'elemento <fieldset> in base all'attivazione o meno della modalità buio, seguendo le regole dello stile in linea fornito dallo sviluppatore nella pagina. Può essere gainsboro o darkslategray.

Una pagina in modalità Luce.
Modalità Luce: stili specificati dallo sviluppatore e dallo user agent. Il testo è nero e lo sfondo è bianco, come indicato nel foglio di stile dello user agent. Il valore background-color dell'elemento <fieldset> è gainsboro in base allo stile in linea dello sviluppatore.
Una pagina in modalità Buio.
Modalità Buio: stili specificati dallo sviluppatore e dallo user agent. Il testo è bianco e lo sfondo è nero in base allo stile della pagina dell'agente utente. Il valore background-color dell'elemento <fieldset> è darkslategray in base allo stile in linea dello sviluppatore.

L'aspetto dell'elemento <button> è controllato dal foglio di stile dell'agente utente. Il color è impostato sul colore di sistema ButtonText, mentre background-color e i quattro border-color sono impostati sul colore di sistema ButtonFace.

Una pagina in modalità Luce che utilizza la proprietà ButtonFace.
Modalità Luce: background-color e i vari border-color sono impostati sul colore di sistema ButtonFace.

Ora osserva come cambia border-color dell'elemento <button>. Il valore calcolato per border-top-color e border-bottom-color passa da rgba(0, 0, 0, 0.847) (nero) a rgba(255, 255, 255, 0.847) (bianco), poiché lo user agent aggiorna ButtonFace dinamicamente in base alla combinazione di colori. Lo stesso vale per color dell'elemento <button> impostato sul colore di sistema corrispondente ButtonText.

Mostra che i valori di colore calcolati corrispondono a ButtonFace.
Modalità Luce: i valori calcolati di border-top-color e border-bottom-color, entrambi impostati su ButtonFace nel foglio di stile dell'user agent, ora sono rgba(0, 0, 0, 0.847).
Mostra che i valori del colore calcolati corrispondono ancora a ButtonFace in modalità Buio.
Modalità Buio: i valori calcolati di border-top-color e border-bottom-color, entrambi impostati su ButtonFace nello stile foglio dell'user agent, ora sono rgba(255, 255, 255, 0.847).

Demo

Puoi vedere gli effetti di color-scheme applicati a un numero elevato di elementi HTML in una demo su Glitch. La demo mostra deliberatamente la violazione WCAG AA e WCAG AAA con i colori dei link menzionati nell'avviso precedente.

La demo in modalità Luce.
La demo è passata a color-scheme: light.
La demo in modalità Buio.
La demo è passata a color-scheme: dark. Nota la violazione WCAG AA e WCAG AAA con i colori dei link.

Ringraziamenti

La proprietà CSS color-scheme e il metatag corrispondente sono stati implementati da Rune Lillesveen. Rune è anche co-editor della specifica del Modulo di regolazione del colore CSS di livello 1. Immagine hero di Philippe Leone su Unsplash.