Come configurare le combinazioni di colori dell'applicazione con le proprietà personalizzate CSS
Pubblicato: 2022-03-10Le variabili sono uno strumento di base che aiuta a organizzare i colori su un progetto. Per molto tempo, gli ingegneri front-end hanno utilizzato le variabili del preprocessore per configurare i colori su un progetto. Ma ora molti sviluppatori preferiscono il moderno meccanismo nativo per organizzare le variabili di colore: CSS Custom Properties. Il loro vantaggio più importante rispetto alle variabili del preprocessore è che funzionano in tempo reale, non nella fase di compilazione del progetto, e hanno il supporto per il modello a cascata che consente di utilizzare l'ereditarietà e la ridefinizione dei valori al volo.
Quando si tenta di organizzare una combinazione di colori di un'applicazione, è sempre possibile inserire tutte le proprietà personalizzate relative al colore nella sezione principale, denominarle e utilizzarle in tutti i punti necessari.
Questa è un'opzione, ma ti aiuta a risolvere i problemi di temi dell'applicazione, etichettatura bianca, aggiornamento del marchio o organizzazione di una modalità chiara o scura? Cosa succede se è necessario regolare la combinazione di colori per aumentare il contrasto? Con l'approccio attuale, dovrai aggiornare ogni valore nelle tue variabili.
In questo articolo, voglio suggerire un approccio più flessibile e resistente su come dividere le variabili di colore utilizzando proprietà personalizzate, che possono risolvere molti di questi problemi.
Imposta la tavolozza dei colori
La colorazione di qualsiasi sito Web inizia con l'impostazione di una combinazione di colori. Tale schema si basa sulla ruota dei colori. Di solito, solo pochi colori primari costituiscono la base di una tavolozza, il resto sono colori derivati: toni e mezzitoni. Molto spesso, la tavolozza è statica e non cambia mentre l'applicazione Web è in esecuzione.
Secondo la teoria dei colori, ci sono solo alcune opzioni per le combinazioni di colori:
- Schema monocromatico (un colore primario)
- Schema complementare (due colori primari)
- Schema triade (tre colori primari)
- Schema tetradico (quattro colori primari)
- Motivo adiacente (due o tre colori primari)
Per il mio esempio, genererò una combinazione di colori triade utilizzando il servizio Paletton:
Ora ho tre colori principali. Sulla base di questi, calcolerò i toni e i mezzitoni (il formato HSL in combinazione con la funzione calc
è uno strumento molto utile per questo). Modificando il valore della luminosità, posso generare diversi colori aggiuntivi per la tavolozza.
Ora se la tavolozza viene modificata, sarà necessario modificare solo il valore dei colori primari. Il resto verrà ricalcolato automaticamente.
Se preferisci i formati HEX o RGB, non importa; una tavolozza può essere formata in fase di compilazione del progetto con le funzioni corrispondenti del preprocessore (ad es. con SCSS e la funzione color-adjust
). Come ho detto prima, questo livello è per lo più statico; è estremamente raro che la tavolozza possa essere modificata in un'applicazione in esecuzione. Ecco perché possiamo calcolarlo con i preprocessori.
Nota : consiglio anche di generare sia HEX letterale che RGB per ogni colore. Ciò consentirà di giocare con il canale alfa in futuro.
Il livello della tavolozza è l'unico livello in cui il colore è codificato direttamente nei nomi delle variabili, cioè possiamo identificare univocamente il colore leggendo il nome.
Definisci temi o colori funzionali
Una volta terminata la tavolozza, il passaggio successivo è il livello dei colori funzionali . A questo livello, il valore del colore non è così importante quanto il suo scopo, la funzione che svolge e cosa colora esattamente. Ad esempio, il colore del marchio principale o dell'app, il colore del bordo, il colore del testo su uno sfondo scuro, il colore del testo su uno sfondo chiaro, il colore di sfondo del pulsante, il colore del collegamento, il colore del collegamento al passaggio del mouse, il colore del testo del suggerimento e così via .
Queste sono cose estremamente comuni per quasi tutti i siti Web o applicazioni. Possiamo dire che tali colori sono responsabili di un determinato tema cromatico dell'applicazione. Inoltre, i valori di tali variabili sono presi rigorosamente dalla tavolozza. Pertanto, possiamo facilmente cambiare i temi dell'applicazione semplicemente operando con diverse tavolozze di colori.
Di seguito, ho creato tre tipici controlli dell'interfaccia utente: un pulsante, un collegamento e un campo di input. Sono colorati utilizzando variabili funzionali che contengono valori dalla tavolozza che ho generato in precedenza. La principale variabile funzionale responsabile del tema dell'applicazione (marca condizionale) è la variabile di colore principale.
Usando i tre pulsanti in alto, puoi cambiare tema (cambia il colore del marchio per i controlli). La modifica avviene utilizzando l'API CSSOM appropriata (setProperty).
Questo approccio è conveniente non solo per i temi ma anche per la configurazione di singole pagine web. Ad esempio, sul sito Web zubry.by, ho utilizzato un foglio di stile comune e una variabile funzionale --page-color
per colorare il logo, i titoli, i controlli e la selezione del testo per tutte le pagine. E negli stili propri di ogni pagina, ho appena ridefinito questa variabile per impostare la pagina nel suo colore primario individuale.
Usa i colori dei componenti
I grandi progetti web contengono sempre scomposizione; dividiamo tutto in piccoli componenti e li riutilizziamo in molti posti. Ogni componente di solito ha il suo stile, il che significa che non importa cosa abbiamo usato per scomporre i moduli BEM o CSS o un altro approccio; è importante che ciascuna di queste parti di codice possa essere chiamata ambito locale e riutilizzata.
In generale, vedo il punto nell'usare le variabili di colore a livello di componente in due casi.
Il primo è quando i componenti che secondo la guida di stile dell'applicazione vengono ripetuti con impostazioni diverse, ad esempio pulsanti per esigenze diverse come pulsante primario (marca), pulsante secondario, terziario e così via.
Il secondo è quando componenti che hanno diversi stati con colori diversi, ad esempio stati al passaggio del mouse, attivi e messa a fuoco; stati normali e non validi per l'immissione o il campo di selezione e così via.
Un caso più raro in cui le variabili componenti possono tornare utili è la funzionalità di una "etichetta bianca". La "white label" è una funzionalità del servizio che consente all'utente di personalizzare o marcare alcune parti dell'interfaccia utente per migliorare l'esperienza di interazione con i propri clienti. Ad esempio, documenti elettronici che un utente condivide con i suoi clienti tramite un servizio o modelli di posta elettronica. In questo caso, le variabili a livello di componente aiuteranno a configurare alcuni componenti separatamente dal resto del tema colore dell'applicazione.
Nell'esempio seguente, ora ho aggiunto i controlli per la personalizzazione dei colori del pulsante principale (marca). Utilizzando le variabili di colore del livello del componente possiamo configurare i controlli dell'interfaccia utente separatamente l'uno dall'altro.
Come determinare quale livello ha una variabile?
Mi sono imbattuto nella domanda su come capire cosa si può mettere nella radice (tema o livello funzionale) e cosa lasciare a livello di un componente. Questa è un'ottima domanda a cui è difficile rispondere senza vedere la situazione con cui stai lavorando.
Sfortunatamente, lo stesso approccio della programmazione non funziona con colori e stili, se vediamo tre pezzi identici di codice, allora dobbiamo rifattorizzarlo.
Il colore può essere ripetuto da componente a componente, ma ciò non significa che sia una regola. Non può esserci alcuna relazione tra tali componenti. Ad esempio, il bordo del campo di input e lo sfondo del pulsante principale. Sì, nel mio esempio sopra è così, ma controlliamo il seguente esempio:
Il colore grigio scuro viene ripetuto: questo è il bordo del campo di input, il colore di riempimento dell'icona di chiusura e lo sfondo del pulsante secondario. Ma questi componenti non sono in alcun modo collegati tra loro. Se il colore del bordo del campo di input cambia, non cambieremo lo sfondo del pulsante secondario. In tal caso dobbiamo mantenere qui solo la variabile dalla tavolozza.
E il verde? Possiamo definirlo chiaramente come il colore principale o del marchio, molto probabilmente, se cambia il colore del pulsante principale, cambierà anche il colore del collegamento e dell'intestazione del primo livello.
E il rosso? Lo stato non valido dei campi di input, dei messaggi di errore e dei pulsanti distruttivi avrà lo stesso colore a livello dell'intera applicazione. Questo è uno schema. Ora posso definire diverse variabili funzionali comuni nella sezione radice:
Per quanto riguarda il livello dei colori dei componenti, possiamo facilmente identificare i componenti che possono essere personalizzati utilizzando proprietà personalizzate.
Il pulsante viene ripetuto con impostazioni diverse, il colore di sfondo e il testo per i diversi casi d'uso cambiano: caso primario, secondario, terziario, distruttivo o negativo.
Il campo di input ha due stati: errato e normale, in cui i colori dello sfondo e del bordo differiscono. E quindi, mettiamo queste impostazioni nelle variabili di colore a livello dei componenti corrispondenti.
Per il resto dei componenti non è necessario definire variabili di colore locali, questo risulterà ridondante.
Devi immergerti nel linguaggio dei modelli del tuo progetto, che, probabilmente, è stato sviluppato dal team di progettazione e dall'UX. Gli ingegneri devono comprendere appieno l'intero concetto di linguaggio visivo, solo allora possiamo determinare cosa è comune e dovrebbe vivere a livello funzionale e cosa dovrebbe rimanere nell'ambito della visibilità locale.
Ma non tutto è così complicato, ci sono cose ovvie. Lo sfondo generale della pagina, lo sfondo e il colore del testo principale, nella maggior parte dei casi è ciò che definisce il tema della tua applicazione. È estremamente conveniente raccogliere elementi che sono responsabili della configurazione di una modalità particolare (come la modalità scura o chiara).
Perché non mettere tutto nella sezione principale?
Ho avuto una tale esperienza. Nel progetto Lition, io e il team ci siamo trovati di fronte al fatto che dovevamo supportare IE11 per l'applicazione web, ma non per il sito web e gli atterraggi. È stato utilizzato un kit UI comune tra i progetti e abbiamo deciso di mettere tutte le variabili nella radice, questo ci permetterà di ridefinirle a qualsiasi livello.
E anche con questo approccio per l'applicazione Web e il caso IE11, abbiamo semplicemente passato il codice attraverso il seguente plug-in del post-processore e abbiamo trasformato queste variabili in valori letterali per tutti i componenti dell'interfaccia utente nel progetto. Questo trucco è possibile solo se tutte le variabili sono state definite nella sezione radice perché il post-processore non può comprendere le specifiche del modello a cascata.
Ora capisco che questo non era il modo giusto. In primo luogo, se metti i colori dei componenti nella sezione radice, rompi il principio di separazione delle preoccupazioni. Di conseguenza, puoi ritrovarti con CSS ridondanti nel foglio di stile. Ad esempio, hai la cartella dei componenti in cui ogni componente ha i propri stili. Hai anche un foglio di stile comune in cui descrivi le variabili di colore nella sezione principale. Decidi di rimuovere il componente pulsante; in questo caso è necessario ricordarsi di rimuovere anche le variabili associate al pulsante dal file degli stili comuni.
In secondo luogo, questa non è la soluzione migliore in termini di prestazioni. Sì, un cambio di colore provoca solo il processo di riverniciatura, non il reflow/layout, questo di per sé non è troppo costoso, ma quando apporti alcune modifiche al livello più alto, utilizzerai più risorse per controllare l'intero albero rispetto a quando queste i cambiamenti sono in una piccola area locale. Consiglio di leggere il benchmark delle prestazioni delle variabili CSS di Lisi Linhart per maggiori dettagli.
Nel mio attuale progetto Tispr, io e il team usiamo split e non scarichiamo tutto nella radice, ad alto livello solo una tavolozza e colori funzionali. Inoltre, non abbiamo paura di IE11, perché questo problema è risolto dal corrispondente polyfill. Basta installare il modulo npm ie11-custom-properties e importare la libreria nel bundle JS dell'applicazione:
// Use ES6 syntax import "ie11-custom-properties"; // or CommonJS require('ie11-custom-properties');
Oppure aggiungi modulo per tag script:
<script async src="./node_modules/ie11-custom-properties/ie11CustomProperties.js">
Inoltre, puoi aggiungere la libreria senza npm tramite CDN. Il lavoro di questo polyfill si basa sul fatto che IE11 ha un supporto minimo per le proprietà personalizzate, dove le proprietà possono essere definite e lette in base alla cascata. Ciò non è possibile con proprietà che iniziano con trattini doppi, ma possibilmente con un trattino singolo (il meccanismo simile ai prefissi dei fornitori). Puoi leggere di più su questo nella documentazione del repository, oltre a familiarizzare con alcuni limiti. Altri browser ignoreranno questo polyfill.
Di seguito è riportata una tavolozza dell'applicazione web Tispr nonché i controlli della funzionalità "white label" per i documenti elettronici (come contratti utente, fatture o proposte).
Perché non memorizzare le variabili di colore sul lato JavaScript?
Un'altra domanda ragionevole: perché non memorizzare la tavolozza e le variabili della funzione nel codice JavaScript? Questo può anche essere modificato dinamicamente e successivamente ridefinito i colori tramite stili in linea. Questa potrebbe essere un'opzione, ma molto probabilmente questo approccio sarebbe meno ottimale poiché è necessario avere accesso a determinati elementi e modificarne le proprietà del colore. Con le variabili CSS, cambierai solo una singola proprietà, ovvero il valore della variabile.
In JavaScript, non ci sono funzioni native o API per lavorare con i colori. Nel CSS Color Module 5, ci saranno molte opportunità per creare colori derivati o in qualche modo calcolarli. Dal punto di vista del futuro, le proprietà personalizzate CSS sono più ricche e flessibili delle variabili JS. Inoltre, con le variabili JS, non ci sarà la possibilità di utilizzare l'ereditarietà in cascata e questo è lo svantaggio principale.
Conclusione
La suddivisione dei colori in tre livelli (tavolozza, funzionale e componente) può aiutarti ad essere più adattivo ai cambiamenti e ai nuovi requisiti mentre lavori a un progetto. Credo che le proprietà personalizzate CSS siano lo strumento giusto per organizzare la divisione del colore: non importa cosa usi per lo stile: CSS puro, preprocessori o approccio CSS-in-JS.
Sono arrivato a questo approccio attraverso la mia esperienza, ma non sono solo. Sara Soueidan ha descritto nel suo articolo un approccio simile in cui ha suddiviso le variabili in livelli globali e componenti.
Vorrei anche suggerire di leggere l'articolo di Lea Verou in cui descrive possibili casi di applicazione di variabili CSS (non solo in termini di colore).