Una panoramica di base su come creare componenti <button>
adattabili al colore, adattabili e accessibili.
In questo post voglio condividere le mie idee 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 YouTube di questo post:
Panoramica
L'elemento <button>
è stato creato per l'interazione dell'utente. Il suo evento click
viene attivato tramite tastiera,
mouse, tocco, voce e altro, con regole intelligenti sulla tempistica. Include anche alcuni stili predefiniti in ciascun browser, quindi puoi utilizzarli 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'incorporamento precedente di Codepen. Un <button>
senza tipo si adatterà a essere all'interno di un <form>
, cambiando il 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">
In GUI Challenge di questo mese, ogni pulsante riceverà stili che ti aiuteranno a distinguere visivamente l'intenzione. I pulsanti di reimpostazione avranno colori di avviso poiché sono distruttivi, mentre i pulsanti Invia assumeranno un testo intenso blu in modo che appaiano leggermente più in evidenza rispetto ai normali pulsanti.
I pulsanti contengono anche pseudo classi
che il CSS può utilizzare per lo stile. Queste classi forniscono hook CSS per personalizzare l'aspetto del pulsante: :hover
quando il mouse è posizionato sopra il pulsante, :active
per la pressione di un mouse o della tastiera e :focus
o :focus-visible
per facilitare lo stile delle tecnologie per la disabilità.
button:hover {}
button:active {}
button:focus {}
button:focus-visible {}
Markup
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">
Quindi, 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. Per assicurarmi che entrambe funzionino allo stesso modo, modifico anche la strategia per le icone, passando da SVG in linea a SVG mascherato.
<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>
La matrice di combinazioni è piuttosto schiacciante in questo momento. Tra tipi di pulsanti, pseudo-classi e l'interno o l'esterno di un modulo, ci sono oltre 20 combinazioni di pulsanti. è una cosa positiva che il CSS può aiutarci a illustrare chiaramente.
Accessibilità
Gli elementi pulsante sono naturalmente accessibili, ma ci sono alcuni miglioramenti comuni.
Passa il mouse e metti a fuoco insieme
Mi piace raggruppare :hover
e :focus
insieme allo pseudo-selettore funzionale :is()
. Così le interfacce tengono sempre conto
degli stili di tastiera e tecnologie per la disabilità.
button:is(:hover, :focus) {
…
}
Anello di messa a fuoco interattiva
Mi piace animare l'anello di messa a fuoco per gli utenti che usano tastiera e tecnologie per la disabilità. Per risolvere questo problema, rimuovono i contorni dal pulsante di 5 px, ma solo quando il pulsante non è attivo. Questo crea un effetto che, quando premuto, riporta l'anello di messa a fuoco alle dimensioni del pulsante.
:where(button, input):where(:not(:active)):focus-visible {
outline-offset: 5px;
}
Garanzia di un contrasto cromatico passeggero
Esistono almeno quattro diverse combinazioni di colori, chiaro e scuro, che devono essere valutate con il contrasto di colore: pulsante, pulsante Invia, pulsante di ripristino e pulsante disattivato. VisBug viene utilizzato qui per controllare e mostrare tutti i punteggi contemporaneamente:
Le icone verranno nascoste a chi non può vederle
Quando lo crei, l'icona deve fornire un supporto visivo al testo del pulsante. Significa anche che l'icona non è utile per chi soffre di perdita della vista. Fortunatamente il browser consente di nascondere gli elementi alla tecnologia di screen reader, in modo che le persone con problemi di vista non siano disturbati 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 adattivi del pulsante. Con queste proprietà posso iniziare a selezionare elementi e personalizzarne l'aspetto.
Una strategia di proprietà personalizzata adattiva
La strategia di proprietà personalizzata utilizzata in questa verifica GUI è molto simile a quella utilizzata per la creazione di una combinazione di colori. Per un sistema di colori chiaro e scuro adattivo, viene definita e denominata di conseguenza una proprietà personalizzata per ogni tema. Quindi viene utilizzata una singola proprietà personalizzata per contenere il valore corrente del tema e viene assegnata a una proprietà CSS. In seguito, la singola proprietà personalizzata può essere aggiornata a un valore diverso e poi 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);
}
}
Quello che mi piace è che i temi chiaro e scuro sono chiari e dichiarativi. L'indirezione e l'astrazione vengono trasferite nella proprietà personalizzata --_bg
, che ora è l'unica proprietà "reattiva"; --_bg-light
e --_bg-dark
sono
statiche. È anche chiaro che il tema chiaro è il tema predefinito e che il tema scuro viene applicato solo in modo condizionale.
Prepararsi per la coerenza del design
Il selettore condiviso
Il seguente selettore viene utilizzato per scegliere come target tutti i vari tipi di pulsanti e all'inizio è un po' complesso. Poiché viene utilizzato :where()
, la personalizzazione del pulsante non richiede specificità. I pulsanti sono spesso adattati a scenari alternativi e il selettore :where()
assicura che l'attività sia semplice. 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 {
…
}
L'ambito di tutte le proprietà personalizzate verrà limitato all'interno di questo selettore. È il momento di esaminare tutte le proprietà personalizzate. Questo pulsante utilizza un bel po' di proprietà personalizzate. Descriveremo i singoli gruppi man mano che procediamo, quindi parlerò dei contesti oscuri e ridotti di movimento alla fine.
Colore intenso pulsante
I pulsanti e le icone Invia sono un ottimo posto per dare 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, sono versioni scure o schiacciate 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 pattern hsl()
ad eccezione dei pulsanti del tema chiaro, che sono impostati sul bianco in modo che la loro superficie li faccia apparire vicino
all'utente o davanti ad altre superfici:
--_bg-light: hsl(0 0% 100%);
--_bg-dark: hsl(210 9% 31%);
--_bg: var(--_bg-light);
Pulsante sfondo
Questo colore di sfondo consente di far apparire una superficie dietro altre superfici, utile per lo sfondo del file di input:
--_input-well-light: hsl(210 16% 87%);
--_input-well-dark: hsl(204 10% 10%);
--_input-well: var(--_input-well-light);
Spaziatura interna pulsante
La spaziatura intorno al testo nel pulsante viene eseguita utilizzando l'unità ch
, una lunghezza relativa alle dimensioni del carattere. Questo aspetto diventa fondamentale quando pulsanti di grandi dimensioni
possono semplicemente aumentare proporzionalmente font-size
e scalare i pulsanti
in modo proporzionale:
--_padding-inline: 1.75ch;
--_padding-block: .75ch;
Bordo pulsante
Il raggio del bordo del pulsante è memorizzato in una proprietà personalizzata in modo che l'input del file possa corrispondere agli altri pulsanti. I colori dei bordi seguono il sistema di colori adattivo stabilito:
--_border-radius: .5ch;
--_border-light: hsl(210 14% 89%);
--_border-dark: var(--_bg-dark);
--_border: var(--_border-light);
Effetto di evidenziazione del pulsante al passaggio del mouse
Queste proprietà stabiliscono una proprietà delle dimensioni per la transizione al momento dell'interazione e il colore di evidenziazione segue il sistema di colori adattivi. Vedremo come interagiscono questi elementi più avanti in questo post, ma alla fine 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);
Ombra del testo del pulsante
Ogni pulsante ha un sottile stile di ombra del testo. Così il testo si posiziona sopra il pulsante, migliorando la leggibilità e aggiungendo un tocco di eleganza 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 la dimensione di due caratteri grazie alla nuova unità di lunghezza relativa (ch
), che consentirà di ridimensionare l'icona proporzionalmente al testo del pulsante. Il colore dell'icona si appoggia a --_accent-color
per scegliere un colore adattivo all'interno del tema.
--_icon-size: 2ch;
--_icon-color: var(--_accent);
Ombra pulsante
Affinché le ombre si adattino correttamente alla luce e allo scuro, devono modificare sia il colore che l'opacità. Le ombre con il tema chiaro sono migliori quando sono discrete e con un gradiente in linea con il colore della superficie su cui si sovrappongono. Le ombre del tema scuro devono essere più scure e saturate per sovrapporsi ai colori della 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 i colori adattivi e i punti di forza posso combinare 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 tridimensionale, un'ombra della casella 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 adattivi, creo due proprietà statiche per contenere le opzioni del sistema di progettazione:
--_transition-motion-reduce: ;
--_transition-motion-ok:
box-shadow 145ms ease,
outline-offset 145ms ease
;
--_transition: var(--_transition-motion-reduce);
Tutte le proprietà insieme 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 del tema scuro
Il valore del pattern degli oggetti di scena statici -light
e -dark
diventa chiaro quando
vengono impostati gli oggetti di 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 va bene, ma i consumatori di questi pulsanti personalizzati possono usare gli strumenti semplici con la sicurezza di adattarsi in modo appropriato alle preferenze dell'utente.
Adattamenti dei movimenti ridotti
Se il movimento è OK per l'utente che effettua la visita, 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 al resto dei caratteri della pagina, altrimenti verranno definiti dallo stile del browser. Questo vale anche per letter-spacing
. Se imposti line-height
su 1.5
, le dimensioni della casella
lettera vengono impostate per dare spazio al testo sopra e sotto:
: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);
}
Stili dei pulsanti
Regolazione del selettore
Il selettore input[type="file"]
non è la parte del pulsante dell'input, ma 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 cursore e tocco
Per prima cosa, definisco lo stile del cursore pointer
, che consente al pulsante di indicare agli utenti del mouse che è interattivo. Aggiungo touch-action: manipulation
per evitare che i clic 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
Poi personalizzo la dimensione del carattere, lo sfondo, il testo e i colori dei bordi, utilizzando alcune delle proprietà personalizzate adattive 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 tecniche eccezionali. text-shadow
si adatta al chiaro e al buio, creando un piacevole aspetto del testo del pulsante ben posizionato sopra lo sfondo. Per box-shadow
, vengono assegnate tre ombre. La prima, --_shadow-2
, è una normale ombra del riquadro.
La seconda ombra è un trucco per gli occhi che fa sembrare il pulsante un po' smussato. L'ultima ombra è per l'evidenziazione al passaggio del mouse, che inizialmente avrà una dimensione pari a 0, ma le verrà data una dimensione in seguito e verrà eseguita la transizione in modo che
sembri ingrandita rispetto al 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 adatta ai contenuti. Quindi centra il testo e allineo gli elementi secondari al centro verticalmente e orizzontalmente. In questo modo, le icone e altri elementi
dei pulsanti verranno 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 evitare che i fratelli e le sorelle possano toccare e usare le proprietà logiche per la spaziatura interna, in modo che la spaziatura dei 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);
}
Esperienza utente con tocco e mouse
La prossima sezione riguarda soprattutto gli utenti touch su dispositivi mobili. La prima proprietà, user-select
, è per tutti gli utenti e impedisce al testo di evidenziare il testo del pulsante. È per lo più visibile sui dispositivi touch quando si tocca e si tiene premuto un pulsante 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 la disattivo impostando user-select
su Nessuno. Colori di evidenziazione dei tocchi
(-webkit-tap-highlight-color
)
e menu contestuali del sistema operativo
(-webkit-touch-callout
)
sono altre funzionalità dei pulsanti incentrate sul web che non sono in linea con le aspettative
generali degli utenti dei pulsanti, quindi rimuovo anche queste funzionalità.
: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 adattiva --_transition
è 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);
}
Al passaggio del mouse, mentre l'utente non sta premendo attivamente, regola le dimensioni di evidenziazione dell'ombra per ottenere un buon aspetto che appaia all'interno del pulsante:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
):where(:not(:active):hover) {
--_highlight-size: .5rem;
}
Dopo aver impostato lo stato attivo, aumenta lo spostamento dei contorni di messa a fuoco dal pulsante, dandogli anche un aspetto interessante che sembra crescere dall'interno del pulsante:
:where(button, input):where(:not(:active)):focus-visible {
outline-offset: 5px;
}
Icone
Per gestire le icone, nel selettore è stato aggiunto un selettore :where()
per gli elementi secondari SVG diretti o gli elementi con l'attributo personalizzato data-icon
. Le dimensioni dell'icona vengono impostate
con la proprietà personalizzata usando proprietà logiche incorporate e di blocco. Il colore del tratto
è impostato, così come
drop-shadow
per corrispondere a text-shadow
. flex-shrink
è impostato su 0
, pertanto l'icona non viene mai schiacciata. Infine, seleziono le icone a righe e assegno gli stili qui con i limiti di riga e i unioni delle righe 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 inviassero un aspetto leggermente promosso e l'ho fatto rendendo il colore del testo dei pulsanti il colore intenso:
:where(
[type="submit"],
form button:not([type],[disabled])
) {
--_text: var(--_accent);
}
Personalizza i pulsanti di ripristino
Volevo che i pulsanti di reset avessero alcuni segnali di avviso integrati per avvisare gli utenti del loro potenziale comportamento distruttivo. Ho anche optato per il 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 dei contorni di messa a fuoco abbinasse l'accento
rosso. Il colore del testo adatta un rosso scuro a un rosso chiaro. Faccio in modo che il colore dei contorni
corrisponda a questo valore con la parola chiave
currentColor
:
:where([type="reset"]):focus-visible {
outline-color: currentColor;
}
Personalizzazione dei pulsanti disattivati
È troppo comune che i pulsanti disattivati abbiano uno scarso contrasto di colore quando si tenta di sottrarre il pulsante disattivato in modo che risulti meno attivo. Ho testato ogni set di colori e mi sono assicurato che venissero superati, modificando il valore di luminosità HSL fino al punteggio trasmesso 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 input dei file
Il pulsante di input del file è un contenitore per una sezione e un pulsante. CSS è in grado di modificare leggermente il contenitore di input e il pulsante nidificato, ma non l'intervallo. Al container viene assegnato un valore max-inline-size
in modo che non cresca più del necessario, mentre inline-size: 100%
permette di ridurre e adattare i contenitori di dimensioni inferiori. Il colore di sfondo è impostato su un colore adattivo più scuro rispetto ad altre superfici, in modo che venga visualizzato 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 del selettore file e i pulsanti per il tipo di input vengono assegnati specificatamente a appearance: none
per rimuovere tutti gli stili forniti dal browser che non sono stati sovrascritti dagli altri stili del pulsante.
:where(input[type="button"]),
:where(input[type="file"])::file-selector-button {
appearance: none;
}
Infine, viene aggiunto un margine al punto inline-end
del pulsante per allontanare il testo dal pulsante, creando un po' di spazio.
:where(input[type="file"])::file-selector-button {
margin-inline-end: var(--_padding-inline);
}
Eccezioni particolari per il tema scuro
Ho assegnato ai pulsanti di azione principali uno sfondo più scuro per un testo a contrasto più elevato, dando loro un aspetto leggermente più promosso.
@media (prefers-color-scheme: dark) {
:where(
[type="submit"],
[type="reset"],
[disabled],
form button:not([type="button"])
) {
--_bg: var(--_input-well);
}
}
Creare varianti
Per divertimento e dato che è pratico, ho scelto di mostrare come creare alcune varianti. Una variante è molto vivace, simile alla frequenza con cui appaiono i pulsanti principali. Un'altra variante è grande. L'ultima variante ha un'icona piena di gradiente.
Pulsante Vivace
Per realizzare questo stile con i pulsanti, ho sovrascritto direttamente la base con i colori blu. Questa operazione è stata facile e veloce, ma rimuove gli oggetti di scena adattivi e ha lo stesso aspetto sia nei temi chiari che in quelli scuri.
.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 si ottiene modificando la proprietà personalizzata --_size
.
La spaziatura interna e gli altri elementi dello spazio sono relativi a questa dimensione e vengono scalati proporzionalmente alla nuova dimensione.
.btn-large {
--_size: 1.5rem;
}
Pulsante icona
Questo effetto icona non ha nulla a che fare con gli stili dei pulsanti, ma mostra come ottenerlo con poche proprietà CSS e l'efficacia con cui il pulsante gestisce le icone non SVG incorporate.
[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 ci sono riuscito, come faresti? 🙂
Diversifica i nostri approcci e scopriamo tutti i modi per creare sul web.
Crea una demo, inviami un tweet con i link e lo aggiungerò alla sezione Remix della community di seguito.
Remix della community
Ancora niente da visualizzare.
Risorse
- Codice sorgente su GitHub