Una panoramica di base su come creare componenti <button>
adattabili al colore, reattivi e accessibili.
In questo post voglio condividere la mia opinione su come creare un elemento <button>
adattabile al colore, adattabile e accessibile.
Prova la demo e visualizza la fonte
Se preferisci i video, ecco una versione di questo post su YouTube:
Panoramica
L'elemento
<button>
è progettato per l'interazione con l'utente. L'evento click
si attiva da tastiera, mouse, tocco, comandi vocali e altro ancora, con regole intelligenti relative ai relativi tempi. Inoltre, in ogni browser sono disponibili alcuni stili predefiniti, che puoi utilizzare direttamente senza alcuna personalizzazione. Utilizza color-scheme
per attivare anche i pulsanti chiari e scuri forniti dal browser.
Esistono anche diversi tipi di pulsanti, ciascuno mostrato nell'embed di Codepen precedente. Un <button>
senza un tipo si adatterà all'inserimento in un <form>
, cambiando al tipo di invio.
<!-- buttons -->
<button></button>
<button type="submit"></button>
<button type="button"></button>
<button type="reset"></button>
<!-- button state -->
<button disabled></button>
<!-- input buttons -->
<input type="button" />
<input type="file">
Nel contest della GUI di questo mese, ogni pulsante avrà stili che aiuteranno a differenziarne visivamente lo scopo. I pulsanti di reimpostazione saranno di colore di avviso perché sono distruttivi, mentre i pulsanti di invio avranno un testo di colore blu per essere leggermente più in evidenza rispetto ai pulsanti normali.
I pulsanti hanno anche pseudo classi
che il CSS può utilizzare per gli stili. Queste classi forniscono hook CSS per personalizzare il pulsante: :hover
per quando il mouse passa sopra il pulsante, :active
per quando si preme il mouse o la tastiera e :focus
o :focus-visible
per l'assistenza nello stile delle tecnologie per la disabilità.
button:hover {}
button:active {}
button:focus {}
button:focus-visible {}
Segni e linee
Oltre ai tipi di pulsanti forniti dalla specifica HTML, ho aggiunto un pulsante con un'icona e un pulsante con una classe personalizzata btn-custom
.
<button>Default</button>
<input type="button" value="<input>"/>
<button>
<svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
<path d="..." />
</svg>
Icon
</button>
<button type="submit">Submit</button>
<button type="button">Type Button</button>
<button type="reset">Reset</button>
<button disabled>Disabled</button>
<button class="btn-custom">Custom</button>
<input type="file">
Poi, per i test, ogni pulsante viene inserito all'interno di un modulo. In questo modo posso assicurarmi che gli stili vengano aggiornati in modo appropriato per il pulsante predefinito, che si comporta come un pulsante di invio. Inoltre, cambio la strategia di icone, passando da SVG in linea a SVG mascherato, per assicurarmi che entrambe funzionino allo stesso modo.
<form>
<button>Default</button>
<input type="button" value="<input>"/>
<button>Icon <span data-icon="cloud"></span></button>
<button type="submit">Submit</button>
<button type="button">Type Button</button>
<button type="reset">Reset</button>
<button disabled>Disabled</button>
<button class="btn-custom btn-large" type="button">Large Custom</button>
<input type="file">
</form>
A questo punto la matrice delle combinazioni è piuttosto scoraggiante. Tra tipi di pulsanti, pseudoclassi e presenza o meno in un modulo, esistono più di 20 combinazioni di pulsanti. È un bene che il CSS possa aiutarci a esprimerli chiaramente.
Accessibilità
Gli elementi pulsante sono naturalmente accessibili, ma esistono alcuni miglioramenti comuni.
Passare il mouse sopra e attivare lo stato attivo contemporaneamente
Mi piace raggruppare :hover
e :focus
con l'pseudo selettore
funzionale :is()
. In questo modo, le mie interfacce prendono sempre in considerazione gli stili di tastiera e delle tecnologie per la disabilità.
button:is(:hover, :focus) {
…
}
Anello di messa a fuoco interattivo
Mi piace animare l'anello di messa a fuoco per gli utenti che utilizzano tastiera e tecnologie per la disabilità. Lo scopo viene raggiunto animando il contorno allontanandolo dal pulsante di 5 pixel, ma solo quando il pulsante non è attivo. In questo modo viene creato un effetto che fa sì che l'anello di messa a fuoco si rimpicciolisca alle dimensioni del pulsante quando viene premuto.
:where(button, input):where(:not(:active)):focus-visible {
outline-offset: 5px;
}
Garantire il superamento del contrasto di colore
Esistono almeno quattro diverse combinazioni di colori tra chiaro e scuro che devono essere prese in considerazione per il contrasto di colore: pulsante, pulsante di invio, pulsante di reimpostazione e pulsante disattivato. VisBug viene utilizzato qui per esaminare e mostrare tutti i punteggi contemporaneamente:
Nascondere le icone agli utenti che non possono vederle
Quando crei un pulsante con icona, l'icona deve fornire supporto visivo al testo del pulsante. Ciò significa anche che l'icona non è utile per chi ha perso la vista. Fortunatamente, il browser offre un modo per nascondere gli elementi alla tecnologia degli screen reader, in modo che le persone con problemi di vista non vengano disturbate dalle immagini decorative dei pulsanti:
<button>
<svg … aria-hidden="true">...</svg>
Icon Button
</button>
Stili
In questa sezione, stabilisco innanzitutto un sistema di proprietà personalizzate per gestire gli stili adattabili del pulsante. Con queste proprietà personalizzate posso iniziare a selezionare gli elementi e personalizzarne l'aspetto.
Una strategia di proprietà personalizzata adattiva
La strategia di proprietà personalizzate utilizzata in questa sfida della GUI è molto simile a quella impiegata per creare una combinazione di colori. Per un sistema di colori chiari e scuri adattivi, viene definita e denominata una proprietà personalizzata per ogni tema. Poi viene utilizzata una singola proprietà personalizzata per contenere il valore corrente del tema e viene assegnata a una proprietà CSS. In un secondo momento, la singola proprietà personalizzata può essere aggiornata con un valore diverso, quindi aggiornando lo stile del pulsante.
button {
--_bg-light: white;
--_bg-dark: black;
--_bg: var(--_bg-light);
background-color: var(--_bg);
}
@media (prefers-color-scheme: dark) {
button {
--_bg: var(--_bg-dark);
}
}
Mi piace che i temi chiaro e scuro siano dichiarativi e chiari. La mediazione e l'astrazione vengono trasferite alla proprietà personalizzata --_bg
, che ora è l'unica proprietà "reattiva"; --_bg-light
e --_bg-dark
sono statici. È inoltre chiaro che il tema chiaro è quello predefinito e quello scuro viene applicato solo in modo condizionale.
Preparazione per la coerenza del design
Il selettore condiviso
Il seguente selettore viene utilizzato per scegliere come target tutti i vari tipi di pulsanti e può sembrare un po' complicato all'inizio. Viene utilizzato :where()
, pertanto la personalizzazione del pulsante non richiede alcuna specificità. I pulsanti sono spesso adattati per scenari alternativi e il selettore :where()
garantisce che l'attività sia facile. All'interno di :where()
, è selezionato ogni tipo di pulsante, incluso ::file-selector-button
, che non può essere utilizzato all'interno di :is()
o :where()
.
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
…
}
Tutte le proprietà personalizzate avranno come ambito questo selettore. È ora di esaminare tutte le proprietà personalizzate. In questo pulsante vengono utilizzate diverse proprietà personalizzate. Descriverò ogni gruppo man mano che procediamo, poi condividerò i contesti di scarsa illuminazione e movimento ridotto alla fine della sezione.
Colore di sfondo del pulsante
I pulsanti di invio e le icone sono un ottimo posto per aggiungere un tocco di colore:
--_accent-light: hsl(210 100% 40%);
--_accent-dark: hsl(210 50% 70%);
--_accent: var(--_accent-light);
Colore testo del pulsante
I colori del testo dei pulsanti non sono bianchi o neri, ma sono versioni scurite o schiarite di --_accent
utilizzando
hsl()
e
mantenendo la tonalità 210
:
--_text-light: hsl(210 10% 30%);
--_text-dark: hsl(210 5% 95%);
--_text: var(--_text-light);
Colore sfondo pulsante
Gli sfondi dei pulsanti seguono lo stesso hsl()
pattern, tranne che per i pulsanti del tema chiaro, che sono impostati su bianco in modo che la loro superficie li faccia apparire vicini all'utente o davanti ad altre superfici:
--_bg-light: hsl(0 0% 100%);
--_bg-dark: hsl(210 9% 31%);
--_bg: var(--_bg-light);
Sfondo del riquadro del pulsante
Questo colore di sfondo serve a mostrare una superficie dietro altre, utile per lo sfondo dell'input del file:
--_input-well-light: hsl(210 16% 87%);
--_input-well-dark: hsl(204 10% 10%);
--_input-well: var(--_input-well-light);
Spaziatura interna dei pulsanti
La spaziatura attorno al testo nel pulsante viene eseguita utilizzando l'unità
ch
, una lunghezza relativa alle dimensioni del carattere. Questo diventa fondamentale quando i pulsanti grandi possono semplicemente aumentare le scale font-size
e dei pulsanti proporzionalmente:
--_padding-inline: 1.75ch;
--_padding-block: .75ch;
Bordo del pulsante
Il raggio del bordo del pulsante viene memorizzato in una proprietà personalizzata in modo che l'input del file possa essere associato agli altri pulsanti. I colori dei bordi rispettano il sistema di colori adattivi stabilito:
--_border-radius: .5ch;
--_border-light: hsl(210 14% 89%);
--_border-dark: var(--_bg-dark);
--_border: var(--_border-light);
Effetto di evidenziazione al passaggio del mouse del pulsante
Queste proprietà stabiliscono una proprietà di dimensione per la transizione all'interazione e il colore di evidenziazione segue il sistema di colori adattivi. Spiegheremo come interagiscono più avanti in questo post, ma in definitiva vengono utilizzati per un effetto box-shadow
:
--_highlight-size: 0;
--_highlight-light: hsl(210 10% 71% / 25%);
--_highlight-dark: hsl(210 10% 5% / 25%);
--_highlight: var(--_highlight-light);
Ombreggiatura testo pulsante
Ogni pulsante ha uno stile di ombra del testo delicato. In questo modo, il testo si posiziona sopra il pulsante, migliorandone la leggibilità e aggiungendo un tocco di raffinatezza alla presentazione.
--_ink-shadow-light: 0 1px 0 var(--_border-light);
--_ink-shadow-dark: 0 1px 0 hsl(210 11% 15%);
--_ink-shadow: var(--_ink-shadow-light);
Icona del pulsante
Le icone hanno le dimensioni di due caratteri grazie all'unità di lunghezza relativa ch
, che consente di ridimensionare l'icona in proporzione al testo del pulsante. Il colore dell'icona si basa su --_accent-color
per un colore adatto al tema e adattivo.
--_icon-size: 2ch;
--_icon-color: var(--_accent);
Ombra pulsante
Affinché le ombre si adattino correttamente alla luce e al buio, devono cambiare sia il colore sia l'opacità. Le ombre del tema chiaro sono ideali se sono sottili e tinte in base al colore della superficie su cui vengono sovrapposte. Le ombre del tema scuro devono essere più scure e più sature in modo da poter sovrapporre i colori di superficie più scuri.
--_shadow-color-light: 220 3% 15%;
--_shadow-color-dark: 220 40% 2%;
--_shadow-color: var(--_shadow-color-light);
--_shadow-strength-light: 1%;
--_shadow-strength-dark: 25%;
--_shadow-strength: var(--_shadow-strength-light);
Con colori e intensità adattivi posso assemblare due profondità di ombre:
--_shadow-1: 0 1px 2px -1px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 9%));
--_shadow-2:
0 3px 5px -2px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 3%)),
0 7px 14px -5px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 5%));
Inoltre, per dare ai pulsanti un aspetto leggermente 3D, un'ombra interna 1px
crea l'illusione:
--_shadow-depth-light: 0 1px var(--_border-light);
--_shadow-depth-dark: 0 1px var(--_bg-dark);
--_shadow-depth: var(--_shadow-depth-light);
Transizioni dei pulsanti
Seguendo il pattern per i colori adattabili, creo due proprietà statiche per contenere le opzioni del sistema di design:
--_transition-motion-reduce: ;
--_transition-motion-ok:
box-shadow 145ms ease,
outline-offset 145ms ease
;
--_transition: var(--_transition-motion-reduce);
Tutte le proprietà nel selettore
:where( button, input[type="button"], input[type="submit"], input[type="reset"], input[type="file"] ), :where(input[type="file"])::file-selector-button { --_accent-light: hsl(210 100% 40%); --_accent-dark: hsl(210 50% 70%); --_accent: var(--_accent-light);--_text-light: hsl(210 10% 30%); --_text-dark: hsl(210 5% 95%); --_text: var(--_text-light);
--_bg-light: hsl(0 0% 100%); --_bg-dark: hsl(210 9% 31%); --_bg: var(--_bg-light);
--_input-well-light: hsl(210 16% 87%); --_input-well-dark: hsl(204 10% 10%); --_input-well: var(--_input-well-light);
--_padding-inline: 1.75ch; --_padding-block: .75ch;
--_border-radius: .5ch; --_border-light: hsl(210 14% 89%); --_border-dark: var(--_bg-dark); --_border: var(--_border-light);
--_highlight-size: 0; --_highlight-light: hsl(210 10% 71% / 25%); --_highlight-dark: hsl(210 10% 5% / 25%); --_highlight: var(--_highlight-light);
--_ink-shadow-light: 0 1px 0 hsl(210 14% 89%); --_ink-shadow-dark: 0 1px 0 hsl(210 11% 15%); --_ink-shadow: var(--_ink-shadow-light);
--_icon-size: 2ch; --_icon-color-light: var(--_accent-light); --_icon-color-dark: var(--_accent-dark); --_icon-color: var(--accent, var(--_icon-color-light));
--_shadow-color-light: 220 3% 15%; --_shadow-color-dark: 220 40% 2%; --_shadow-color: var(--_shadow-color-light); --_shadow-strength-light: 1%; --_shadow-strength-dark: 25%; --_shadow-strength: var(--_shadow-strength-light); --_shadow-1: 0 1px 2px -1px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 9%)); --_shadow-2: 0 3px 5px -2px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 3%)), 0 7px 14px -5px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 5%)) ;
--_shadow-depth-light: hsl(210 14% 89%); --_shadow-depth-dark: var(--_bg-dark); --_shadow-depth: var(--_shadow-depth-light);
--_transition-motion-reduce: ; --_transition-motion-ok: box-shadow 145ms ease, outline-offset 145ms ease ; --_transition: var(--_transition-motion-reduce); }
Adattamenti al tema scuro
Il valore del pattern degli elementi statici -light
e -dark
diventa chiaro quando vengono impostati gli elementi del tema scuro:
@media (prefers-color-scheme: dark) {
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
--_bg: var(--_bg-dark);
--_text: var(--_text-dark);
--_border: var(--_border-dark);
--_accent: var(--_accent-dark);
--_highlight: var(--_highlight-dark);
--_input-well: var(--_input-well-dark);
--_ink-shadow: var(--_ink-shadow-dark);
--_shadow-depth: var(--_shadow-depth-dark);
--_shadow-color: var(--_shadow-color-dark);
--_shadow-strength: var(--_shadow-strength-dark);
}
}
Non solo è facile da leggere, ma gli utenti di questi pulsanti personalizzati possono utilizzare gli elementi di base con la certezza che si adatteranno in modo appropriato alle preferenze degli utenti.
Adattamenti con movimento ridotto
Se il movimento è accettabile per questo utente che visita il sito, assegna --_transition
a
var(--_transition-motion-ok)
:
@media (prefers-reduced-motion: no-preference) {
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
--_transition: var(--_transition-motion-ok);
}
}
Alcuni stili condivisi
I caratteri dei pulsanti e degli input devono essere impostati su inherit
in modo che corrispondano ai caratteri del resto della pagina. In caso contrario, verranno formattati dal browser. Lo stesso vale per letter-spacing
. Se imposti line-height
su 1.5
, la dimensione della cassetta delle lettere viene impostata in modo da lasciare un po' di spazio sopra e sotto il testo:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
/* …CSS variables */
font: inherit;
letter-spacing: inherit;
line-height: 1.5;
border-radius: var(--_border-radius);
}
Aggiungere stili ai pulsanti
Regolazione del selettore
Il selettore input[type="file"]
non è la parte del pulsante dell'input, ma lo è l'elemento pseudo ::file-selector-button
, quindi ho rimosso input[type="file"]
dall'elenco:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
}
Regolazioni del cursore e del tocco
Per prima cosa, applico lo stile pointer
al cursore, in modo che il pulsante indichi agli utenti che usano il mouse che è interattivo. Poi aggiungo touch-action: manipulation
per fare in modo che i clic non debbano attendere e osservare un potenziale doppio clic, rendendo i pulsanti più veloci:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
cursor: pointer;
touch-action: manipulation;
}
Colori e bordi
A questo punto personalizzo le dimensioni dei caratteri, lo sfondo, il testo e i colori dei bordi utilizzando alcune delle proprietà personalizzate adattabili stabilite in precedenza:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
font-size: var(--_size, 1rem);
font-weight: 700;
background: var(--_bg);
color: var(--_text);
border: 2px solid var(--_border);
}
Ombre
Ai pulsanti sono state applicate alcune ottime tecniche. Il pulsante text-shadow
si adatta a temi chiari e scuri, creando un'estetica piacevole e discreta del testo del pulsante che si inserisce perfettamente sullo sfondo. Per box-shadow
vengono assegnate tre ombre. La prima, --_shadow-2
, è un'ombra riquadro normale.
La seconda ombra è un trucco visivo che fa sembrare il pulsante leggermente smussato verso l'alto. L'ultima ombra è per l'evidenziazione al passaggio del mouse, inizialmente con una dimensione pari a 0, ma in seguito verrà assegnata una dimensione e verrà applicata una transizione in modo che sembri crescere dal pulsante.
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
box-shadow:
var(--_shadow-2),
var(--_shadow-depth),
0 0 0 var(--_highlight-size) var(--_highlight)
;
text-shadow: var(--_ink-shadow);
}
Layout
Ho assegnato al pulsante un layout flexbox,
in particolare un layout inline-flex
adatto ai suoi contenuti. Poi centro il testo e allineo verticalmente e orizzontalmente gli elementi secondari al centro. In questo modo, le icone e gli altri elementi dei pulsanti saranno allineati correttamente.
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
display: inline-flex;
justify-content: center;
align-items: center;
text-align: center;
}
Spaziatura
Per lo spazio tra i pulsanti, ho utilizzato gap
per impedire il contatto tra elementi fratelli e le proprietà
logiche per i margini, in modo che lo spazio tra i pulsanti funzioni per tutti i layout di testo.
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
gap: 1ch;
padding-block: var(--_padding-block);
padding-inline: var(--_padding-inline);
}
UX tocco e mouse
La sezione successiva è rivolta principalmente agli utenti che utilizzano dispositivi mobili con tocco. La prima proprietà, user-select
, è per tutti gli utenti e impedisce l'evidenziazione del testo del pulsante. Questo è principalmente visibile sui dispositivi touch quando un pulsante viene toccato e tenuto premuto e il sistema operativo evidenzia il testo del pulsante.
In genere, ho riscontrato che questa non è l'esperienza utente con i pulsanti nelle app integrate, quindi la disattivo impostando user-select
su nessuno. I colori di evidenziazione dei pulsanti
(-webkit-tap-highlight-color
)
e i menu contestuali del sistema operativo
(-webkit-touch-callout
)
sono altre funzionalità dei pulsanti molto incentrate sul web che non sono in linea con le aspettative degli utenti in merito ai pulsanti in generale, quindi li rimuoverò.
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
user-select: none;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
}
Transizioni
La variabile --_transition
adattiva viene assegnata alla proprietà
transition:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
transition: var(--_transition);
}
Quando l'utente passa il mouse sopra il pulsante, senza premerlo, regola le dimensioni dell'evidenziazione dell'ombra per dare un'estetica accattivante allo stato attivo che sembra crescere all'interno del pulsante:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
):where(:not(:active):hover) {
--_highlight-size: .5rem;
}
Quando il pulsante è attivo, aumenta l'offset del contorno attivo dal pulsante, dandogli anche un aspetto piacevole che sembra crescere dall'interno del pulsante:
:where(button, input):where(:not(:active)):focus-visible {
outline-offset: 5px;
}
Icone
Per gestire le icone, il selettore ha un selettore :where()
aggiunto per gli elementi figli SVG diretti o gli elementi con l'attributo personalizzato data-icon
. Le dimensioni dell'icona vengono impostate con la proprietà personalizzata utilizzando le proprietà logiche in linea e a blocchi. Il colore del tratto è impostato, nonché un drop-shadow
in modo che corrisponda al text-shadow
. flex-shrink
è impostato su 0
, quindi l'icona non viene mai schiacciata. Infine, selezioni le icone con linee e associo questi stili con i tratti iniziali e finali delle linee fill: none
e round
:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
) > :where(svg, [data-icon]) {
block-size: var(--_icon-size);
inline-size: var(--_icon-size);
stroke: var(--_icon-color);
filter: drop-shadow(var(--_ink-shadow));
flex-shrink: 0;
fill: none;
stroke-linecap: round;
stroke-linejoin: round;
}
Personalizzare i pulsanti di invio
Volevo che i pulsanti di invio avessero un aspetto leggermente in evidenza e ho ottenuto questo risultato impostando il colore del testo dei pulsanti come colore di accento:
:where(
[type="submit"],
form button:not([type],[disabled])
) {
--_text: var(--_accent);
}
Personalizzare i pulsanti di reimpostazione
Volevo che i pulsanti di reimpostazione avessero alcuni segnali di avviso integrati per avvisare gli utenti del loro comportamento potenzialmente dannoso. Ho anche scelto di applicare uno stile al pulsante del tema chiaro con più accenti rossi rispetto al tema scuro. La personalizzazione viene eseguita modificando il colore di base chiaro o scuro appropriato e il pulsante aggiornerà lo stile:
:where([type="reset"]) {
--_border-light: hsl(0 100% 83%);
--_highlight-light: hsl(0 100% 89% / 20%);
--_text-light: hsl(0 80% 50%);
--_text-dark: hsl(0 100% 89%);
}
Ho anche pensato che sarebbe stato bello che il colore del contorno dell'elemento in primo piano fosse abbinato all'accento rosso. Il colore del testo passa da un rosso scuro a un rosso chiaro. Faccio in modo che il colore del contorno sia corrispondente alla parola chiave currentColor
:
:where([type="reset"]):focus-visible {
outline-color: currentColor;
}
Personalizzare i pulsanti disattivati
È molto comune che i pulsanti disattivati abbiano un cattivo contrasto di colore durante il tentativo di attenuare il pulsante disattivato in modo che appaia meno attivo. Ho testato ogni insieme di colori e mi sono assicurato che tutti superassero il test, modificando il valore di luminosità HSL finché il punteggio non è stato superato in DevTools o VisBug.
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
)[disabled] {
--_bg: none;
--_text-light: hsl(210 7% 40%);
--_text-dark: hsl(210 11% 71%);
cursor: not-allowed;
box-shadow: var(--_shadow-1);
}
Personalizzazione dei pulsanti di inserimento dei file
Il pulsante di inserimento del file è un contenitore per uno span e un pulsante. CSS è in grado di impostare un po' di stile al contenitore dell'input, nonché al pulsante nidificato, ma non allo span. Al contenitore viene assegnato max-inline-size
in modo che non aumenti di dimensioni più del necessario, mentre inline-size: 100%
si ridurrà per adattarsi a contenitori più piccoli. Il colore di sfondo è impostato su un colore adattivo più scuro rispetto ad altre superfici, quindi è visibile dietro il pulsante di selezione dei file.
:where(input[type="file"]) {
inline-size: 100%;
max-inline-size: max-content;
background-color: var(--_input-well);
}
Il pulsante di selezione del file e i pulsanti di tipo di input sono specificamente indicatiappearance: none
per rimuovere gli stili forniti dal browser che non sono stati sostituiti dagli altri stili dei pulsanti.
:where(input[type="button"]),
:where(input[type="file"])::file-selector-button {
appearance: none;
}
Infine, viene aggiunto un margine al inline-end
del pulsante per allontanare il testo dello spazio dal pulsante, creando uno spazio.
:where(input[type="file"])::file-selector-button {
margin-inline-end: var(--_padding-inline);
}
Eccezioni speciali per il tema scuro
Ho dato ai pulsanti di azione principali uno sfondo più scuro per un testo con un maggiore contrasto, conferendo loro un aspetto leggermente più in evidenza.
@media (prefers-color-scheme: dark) {
:where(
[type="submit"],
[type="reset"],
[disabled],
form button:not([type="button"])
) {
--_bg: var(--_input-well);
}
}
Creazione di varianti
Per divertimento e perché è pratico, ho scelto di mostrare come creare alcune varianti. Una variante è molto vivace, simile all'aspetto spesso dei pulsanti principali. Un'altra variante è di grandi dimensioni. L'ultima variante ha un'icona con riempimento sfumato.
Pulsante vivace
Per ottenere questo stile di pulsante, ho sovrascritto le proprietà di base direttamente con colori blu. Sebbene sia stato un processo rapido e semplice, rimuove gli elementi adattabili e ha lo stesso aspetto sia con il tema chiaro sia con quello scuro.
.btn-custom {
--_bg: linear-gradient(hsl(228 94% 67%), hsl(228 81% 59%));
--_border: hsl(228 89% 63%);
--_text: hsl(228 89% 100%);
--_ink-shadow: 0 1px 0 hsl(228 57% 50%);
--_highlight: hsl(228 94% 67% / 20%);
}
Pulsante grande
Questo stile di pulsante viene ottenuto modificando la proprietà personalizzata --_size
.
I margini e altri elementi dello spazio sono relativi a questa dimensione e vengono ridimensionati proporzionalmente in base alla nuova dimensione.
.btn-large {
--_size: 1.5rem;
}
Pulsante icona
Questo effetto icona non ha nulla a che fare con i nostri stili di pulsanti, ma mostra come ottenerlo con poche proprietà CSS e quanto bene il pulsante gestisce le icone che non sono SVG in linea.
[data-icon="cloud"] {
--icon-cloud: url("https://api.iconify.design/mdi:apple-icloud.svg") center / contain no-repeat;
-webkit-mask: var(--icon-cloud);
mask: var(--icon-cloud);
background: linear-gradient(to bottom, var(--_accent-dark), var(--_accent-light));
}
Conclusione
Ora che sai come ho fatto, come faresti? 🙂
Diversifichiamo i nostri approcci e impariamo tutti i modi per creare sul web.
Crea una demo, twittami i link e io la aggiungerò alla sezione dei remix della community di seguito.
Remix della community
Ancora nessun elemento da visualizzare.
Risorse
- Codice sorgente su GitHub