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>
è creato per l'interazione dell'utente. L'evento click
viene attivato tramite tastiera,
mouse, tocco, voce e altro ancora, con regole intelligenti sulle
tempistiche. 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, ognuno dei quali è mostrato nell'incorporamento precedente del codepen. 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 applicare 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 {}
Aumento
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 correttamente per il pulsante predefinito, che si comporta come un pulsante Invia. 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 faticosa. 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.
Passa il mouse e imposta lo stato attivo insieme
Mi piace raggruppare :hover
e :focus
con l'pseudo selettore
funzionale :is()
. In questo modo le mie interfacce prendono sempre
in considerazione gli stili della 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 di tastiere e tecnologie per la disabilità. A questo scopo, anima il contorno allontanandolo dal pulsante di 5 px, 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;
}
Garanzia di trasmissione del contrasto di colore
Esistono almeno quattro diverse combinazioni di colori, per il colore chiaro e scuro, che devono tenere conto del contrasto di colore: pulsante, pulsante di invio, pulsante di ripristino e pulsante disattivato. VisBug viene utilizzato qui per esaminare e mostrare tutti i punteggi contemporaneamente:
Le icone vengono nascoste a persone 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 adattiva per le proprietà personalizzate
La strategia delle proprietà personalizzate utilizzata in questa sfida della GUI è molto simile a quella utilizzata nella creazione di una combinazione di colori. Per un sistema di colori chiari e scuri adattivi, viene definita e denominata una proprietà personalizzata per ogni tema. Successivamente, viene utilizzata una singola proprietà personalizzata che contiene 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 il fatto che i temi chiaro e scuro siano chiari e dichiarativi. La dipendenza indiretta 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.
Prepararsi alla 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 usato 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 il bianco o il nero, ma le versioni con scurimenti o schiariture
di --_accent
che utilizzano
hsl()
e
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()
schema, tranne per i pulsanti del tema chiaro, che sono impostati su bianco in modo che la loro superficie li faccia sembrare 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 pulsante ben definito
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 intorno al testo nel pulsante viene eseguita utilizzando l'unità ch
, una lunghezza relativa alla dimensione 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 sul pulsante
Queste proprietà stabiliscono una proprietà di dimensione per la transizione all'interazione e il colore di evidenziazione segue il sistema di colori adattivi. Parleremo di come questi interagiscono più avanti in questo post, ma alla fine verranno 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 viene posizionato sopra il pulsante, migliorando la leggibilità e aggiungendo un buon livello di perfezionamento della 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 la lettura è positiva, ma anche i consumatori di questi pulsanti personalizzati possono utilizzare gli oggetti di scena semplici e 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
Per i pulsanti e gli input, i caratteri devono essere impostati su inherit
in modo da corrispondere
al resto dei caratteri della pagina, altrimenti verranno impostati dal browser. Questo vale anche
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, lo è lo
pseudo-elemento ::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 utilizzano 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 vengono applicate 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 riguarda l'evidenziazione al passaggio del mouse, inizialmente
di dimensione pari a 0, ma verrà definita in un secondo momento e sarà sottoposta a transizione in modo che
sembri crescere a partire 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
che si adatti 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 del pulsante 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 la spaziatura dei pulsanti, ho utilizzato gap
per impedire ai fratelli di toccare e proprietà logiche per la spaziatura interna, quindi la spaziatura dei pulsanti funziona 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 prossima sezione è dedicata principalmente agli utenti touch sui dispositivi mobili. 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 notato che non si tratta dell'esperienza utente con i pulsanti nelle app integrate, quindi lo 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 dall'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 lo spazio tra il contorno attivo e il 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. È impostato il colore del tratto e una drop-shadow
in modo che corrisponda a 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;
}
Personalizzazione dei pulsanti di invio
Volevo che i pulsanti avessero un aspetto leggermente promosso e l'ho fatto impostando il colore del testo dei pulsanti come colore di contrasto:
:where(
[type="submit"],
form button:not([type],[disabled])
) {
--_text: var(--_accent);
}
Personalizza i pulsanti di reimpostazione
Volevo che i pulsanti di ripristino avessero alcuni segnali di avviso integrati per avvisare gli utenti del loro comportamento potenzialmente distruttivo. 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 in corrispondenza con la 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 set di colori e mi sono assicurato che venissero superati, modificando il valore di leggerezza HSL fino a quando il punteggio è passato 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 immissione 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 relative al tema scuro
Ho dato ai pulsanti di azione principali uno sfondo più scuro per un testo con un maggiore contrasto, dando 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 dato che è 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 questa operazione sia stata rapida 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
.
La spaziatura interna e altri elementi dello spazio sono relativi a questa dimensione e vengono scalati 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 niente da visualizzare qui.
Risorse
- Codice sorgente su GitHub