Ein grundlegender Überblick über das Erstellen von farbanpassungsfähigen, responsiv und barrierefrei zugänglichen <button>
-Komponenten.
In diesem Beitrag möchte ich dir mitteilen, wie man ein farbanpassungsfähiges, responsives und barrierefreies <button>
-Element erstellt.
Demo ansehen und Quelle ansehen
Falls du lieber ein Video hast, findest du hier eine YouTube-Version dieses Beitrags:
Überblick
Das Element <button>
ist für die Nutzerinteraktion konzipiert. Das click
-Ereignis wird unter anderem über die Tastatur, die Maus, die Touch-Geste oder die Stimme ausgelöst. Dabei werden intelligente Regeln zur Zeitsteuerung berücksichtigt. In jedem Browser sind auch einige Standardstile enthalten, sodass Sie diese direkt und ohne Anpassungen verwenden können. Verwenden Sie color-scheme
, um vom Browser bereitgestellte helle und dunkle Schaltflächen zu aktivieren.
Es gibt auch verschiedene Arten von Schaltflächen, die alle in der vorherigen Codepen-Einbettung gezeigt werden. Ein <button>
ohne Typ passt sich an eine <form>
an und wird in den Übermittlungstyp geändert.
<!-- 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">
Im Rahmen der GUI Challenge dieses Monats erhalten alle Schaltflächen einen Stil, mit dem sie ihre Absicht visuell unterscheiden können. Schaltflächen zum Zurücksetzen haben Warnfarben, da sie destruktiv sind. Für Schaltfläche zum Senden wird ein blauer Akzenttext angezeigt, sodass sie etwas stärker hervorgehoben werden als normale Schaltflächen.
![Vorschau des endgültigen Satzes aller Schaltflächentypen, der in einem Formular und nicht in einem Formular angezeigt wird, mit praktischen Ergänzungen für Symbolschaltflächen und benutzerdefinierte Schaltflächen.](https://web.dev/static/articles/building/a-button-component/image/preview-the-final-set-a-f0edd66ff9463.png?authuser=6&hl=de)
Schaltflächen haben auch Pseudoklassen, die CSS für Stile verwenden kann. Diese Klassen bieten CSS-Hooks zum Anpassen der Funktion der Schaltfläche: :hover
für das Bewegen der Maus über der Schaltfläche, :active
für das Drücken einer Maus oder Tastatur und :focus
oder :focus-visible
zur Unterstützung beim Gestalten von Hilfstechnologien.
button:hover {}
button:active {}
button:focus {}
button:focus-visible {}
![Vorschau aller Schaltflächentypen im dunklen Design.](https://web.dev/static/articles/building/a-button-component/image/preview-the-final-set-a-65448775506f6.png?authuser=6&hl=de)
Markup
Zusätzlich zu den Schaltflächentypen, die über die HTML-Spezifikation bereitgestellt werden, habe ich eine Schaltfläche mit einem Symbol und einer Schaltfläche mit der benutzerdefinierten Klasse btn-custom
hinzugefügt.
<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">
Anschließend wird jede Schaltfläche zum Testen in einem Formular platziert. Auf diese Weise kann ich dafür sorgen, dass die Stile für die Standardschaltfläche, die sich wie eine Senden-Schaltfläche verhält, korrekt aktualisiert werden. Außerdem stelle ich die Symbolstrategie von Inline-SVG auf maskierte SVG um, damit beide Elemente gleichermaßen gut funktionieren.
<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>
Die Matrix der Kombinationen ist an dieser Stelle ziemlich überwältigend. Zwischen Schaltflächentypen und Pseudoklassen gibt es mehr als 20 Schaltflächenkombinationen, je nachdem, ob sie sich in einem Formular befinden oder nicht. Es ist gut, dass CSS uns hilft, die einzelnen Punkte klar zu formulieren.
Barrierefreiheit
Schaltflächenelemente sind natürlich zugänglich, es gibt jedoch einige gängige Verbesserungen.
Hover und fokussieren
Ich gruppiere :hover
und :focus
gern mit dem funktionalen Pseudoselektor :is()
. Das trägt dazu bei, dass in meinen Benutzeroberflächen immer der Stil
von Tastatur und Hilfstechnologien berücksichtigt wird.
button:is(:hover, :focus) {
…
}
Interaktiver Fokusring
Ich liebe es, den Fokusring für Nutzende von Tastaturen und Hilfstechnologien zu animieren. Dazu werde ich den Umriss um 5 Pixel von der Schaltfläche weg animieren, aber nur, wenn die Schaltfläche nicht aktiv ist. Dadurch wird der Fokusring beim Drücken auf die Größe der Schaltfläche verkleinert.
:where(button, input):where(:not(:active)):focus-visible {
outline-offset: 5px;
}
Sicherstellen, dass Farbkontraste weitergegeben werden
Es gibt mindestens vier verschiedene Farbkombinationen in hellen und dunklen Farben, die einen Farbkontrast berücksichtigen müssen: Schaltfläche, Senden-Schaltfläche, Schaltfläche zum Zurücksetzen und deaktivierte Schaltfläche. Hier wird VisBug verwendet, um alle ihre Punktzahlen auf einmal zu überprüfen und anzuzeigen:
Verbergen von Symbolen für Personen, die sie nicht sehen können
Beim Erstellen einer Symbolschaltfläche sollte das Symbol den Schaltflächentext visuell unterstützen. Das bedeutet auch, dass das Symbol für Personen mit Sehverlust keinen Wert hat. Glücklicherweise bietet der Browser die Möglichkeit, Elemente vor Screenreader-Technologie zu verbergen, damit Menschen mit Sehverlust nicht mit dekorativen Schaltflächenbildern gestört werden:
<button>
<svg … aria-hidden="true">...</svg>
Icon Button
</button>
![Chrome-Entwicklertools mit der Baumansicht der Bedienungshilfen für die Schaltfläche. Die Baumstruktur ignoriert das Schaltflächenbild, weil „aria-hidden“ auf „true“ festgelegt ist.](https://web.dev/static/articles/building/a-button-component/image/chrome-devtools-showing-4f9517c567e4c.png?authuser=6&hl=de)
Stile
Im nächsten Abschnitt richte ich zuerst ein System mit benutzerdefinierten Eigenschaften ein, um die adaptiven Stile der Schaltfläche zu verwalten. Mit diesen benutzerdefinierten Eigenschaften kann ich Elemente auswählen und ihr Erscheinungsbild anpassen.
Adaptive Strategie für benutzerdefinierte Properties
Die in dieser GUI Challenge verwendete Strategie für benutzerdefinierte Eigenschaften ähnelt sehr der Strategie, die beim Erstellen eines Farbschemas verwendet wird. Bei einem adaptiven hellen und dunklen Farbsystem wird für jedes Design eine benutzerdefinierte Eigenschaft definiert und entsprechend benannt. Dann wird eine einzelne benutzerdefinierte Eigenschaft verwendet, die den aktuellen Wert des Designs enthält, und einer CSS-Eigenschaft zugewiesen. Später kann diese einzelne benutzerdefinierte Eigenschaft auf einen anderen Wert und dann den Stil der Schaltfläche aktualisiert werden.
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);
}
}
Was mir gefällt, ist, dass das helle und das dunkle Design aussagekräftig und klar sind. Die Indirektion und Abstraktion werden in das benutzerdefinierte Attribut --_bg
übertragen, das jetzt die einzige „reaktive“ Eigenschaft ist. --_bg-light
und --_bg-dark
sind statisch. Außerdem ist zu erkennen, dass das helle Design das Standarddesign ist und das dunkle Design nur bedingt angewendet wird.
Auf Einheitlichkeit des Designs vorbereiten
Die gemeinsam genutzte Auswahl
Der folgende Selektor wird für die Ausrichtung auf alle verschiedenen Schaltflächentypen verwendet und ist anfangs etwas überwältigend. Da dabei :where()
verwendet wird, ist das Anpassen der Schaltfläche nicht spezifisch. Schaltflächen werden häufig an alternative Szenarien angepasst. Mit der Auswahl :where()
ist diese Aufgabe einfach. In :where()
wird jeder Schaltflächentyp ausgewählt, einschließlich ::file-selector-button
, der innerhalb von :is()
oder :where()
nicht verwendet werden kann.
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
…
}
Alle benutzerdefinierten Eigenschaften werden innerhalb dieser Auswahl zugeordnet. Sehen wir uns nun alle benutzerdefinierten Eigenschaften an. In dieser Schaltfläche werden viele benutzerdefinierte Eigenschaften verwendet. Ich beschreibe die einzelnen Gruppen und stelle dann am Ende des Abschnitts den dunklen und reduzierten Bewegungskontext vor.
Akzentfarbe der Schaltfläche
Die Schaltflächen und Symbole zum Einreichen von Inhalten eignen sich hervorragend für einen farbigen Touch:
--_accent-light: hsl(210 100% 40%);
--_accent-dark: hsl(210 50% 70%);
--_accent: var(--_accent-light);
Schriftfarbe für Schaltfläche
Die Farben der Schaltflächentexte sind nicht weiß oder schwarz. Sie sind dunklere oder aufgehellte Versionen von --_accent
mit hsl()
und dem Farbton 210
:
--_text-light: hsl(210 10% 30%);
--_text-dark: hsl(210 5% 95%);
--_text: var(--_text-light);
Hintergrundfarbe der Schaltfläche
Die Hintergründe für Schaltflächen folgen demselben hsl()
-Muster, mit Ausnahme der Schaltflächen im hellen Design. Sie sind auf Weiß eingestellt, damit sie mit ihrer Oberfläche in der Nähe des Nutzers oder vor anderen Oberflächen erscheinen können:
--_bg-light: hsl(0 0% 100%);
--_bg-dark: hsl(210 9% 31%);
--_bg: var(--_bg-light);
Schaltflächenhintergrund
Mit dieser Hintergrundfarbe lässt sich eine Oberfläche hinter anderen Oberflächen erscheinen. Dies ist nützlich für den Hintergrund der Dateieingabe:
--_input-well-light: hsl(210 16% 87%);
--_input-well-dark: hsl(204 10% 10%);
--_input-well: var(--_input-well-light);
Schaltflächenabstand
Der Abstand um den Text in der Schaltfläche wird mit der Einheit ch
festgelegt, einer relativen Länge zur Schriftgröße. Dies ist wichtig, wenn große Schaltflächen font-size
einfach nach oben bewegen können und die Schaltfläche proportional skaliert wird:
--_padding-inline: 1.75ch;
--_padding-block: .75ch;
Schaltflächenrahmen
Der Radius des Schaltflächenrahmens wird in eine benutzerdefinierte Eigenschaft verschoben, damit die Dateieingabe mit den anderen Schaltflächen übereinstimmen kann. Die Rahmenfarben entsprechen dem etablierten adaptiven Farbsystem:
--_border-radius: .5ch;
--_border-light: hsl(210 14% 89%);
--_border-dark: var(--_bg-dark);
--_border: var(--_border-light);
Hervorhebungseffekt für Schaltfläche
Diese Eigenschaften definieren eine Größeneigenschaft für den Übergang bei einer Interaktion, und die Hervorhebungsfarbe folgt dem adaptiven Farbsystem. Wir besprechen später in diesem Beitrag, wie diese interagieren, aber letztendlich werden sie für einen box-shadow
-Effekt verwendet:
--_highlight-size: 0;
--_highlight-light: hsl(210 10% 71% / 25%);
--_highlight-dark: hsl(210 10% 5% / 25%);
--_highlight: var(--_highlight-light);
Textschatten für Schaltfläche
Jede Schaltfläche hat einen dezenten Textschatten. So hat der Text mehr Platz auf der Schaltfläche, was die Lesbarkeit verbessert und die Präsentation noch ansprechender macht.
--_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);
Buttersymbol
Symbole haben die Größe von zwei Zeichen, da wieder die Einheit ch
für die relative Länge verwendet wird, damit das Symbol proportional zum Schaltflächentext skaliert wird. Die Symbolfarbe stützt sich auf --_accent-color
für eine adaptive Farbe, die innerhalb des Designs liegt.
--_icon-size: 2ch;
--_icon-color: var(--_accent);
Schaltflächenschatten
Damit sich Schatten richtig an Licht und Dunkel anpassen, müssen sowohl Farbe als auch Deckkraft geändert werden. Schatten im hellen Design sind am besten, wenn sie subtil und in Richtung der Oberflächenfarbe, die sie überlagern, eingefärbt sind. Schatten im dunklen Design müssen dunkler und gesättigter sein, damit dunklere Oberflächenfarben überlagert werden können.
--_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);
Mit adaptiven Farben und Stärken kann ich zwei Schattentiefen zusammenstellen:
--_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%));
Um den Schaltflächen eine etwas 3D-Darstellung zu verleihen, erzeugt ein 1px
-Feldschatten diese Illusion:
--_shadow-depth-light: 0 1px var(--_border-light);
--_shadow-depth-dark: 0 1px var(--_bg-dark);
--_shadow-depth: var(--_shadow-depth-light);
Schaltflächenübergänge
Gemäß dem Muster für adaptive Farben erstelle ich zwei statische Eigenschaften für die Optionen des Designsystems:
--_transition-motion-reduce: ;
--_transition-motion-ok:
box-shadow 145ms ease,
outline-offset 145ms ease
;
--_transition: var(--_transition-motion-reduce);
Alle Properties in der Auswahl
: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); }
Anpassungen des dunklen Designs
Der Wert der statischen Attribute -light
und -dark
wird deutlich, wenn die Attribute für das dunkle Design festgelegt sind:
@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);
}
}
Das ist nicht nur gut lesbar, Nutzer können sich aber auch darauf verlassen, dass sie sich angemessen an die Nutzerpräferenzen anpassen.
Reduzierte Bewegungsanpassung
Wenn die Bewegung für diesen Besucher in Ordnung ist, weisen Sie var(--_transition-motion-ok)
--_transition
zu:
@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);
}
}
Einige gemeinsame Stile
Für Schaltflächen und Eingaben muss die Schriftarten auf inherit
festgelegt sein, damit sie mit den restlichen Seitenschriftarten übereinstimmen. Andernfalls werden sie vom Browser formatiert. Dies gilt auch für letter-spacing
. Wenn Sie line-height
auf 1.5
setzen, wird die Größe des Buchstabenfelds so festgelegt, dass dem Text darüber und unten etwas Platz eingeräumt wird:
: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);
}
Stile für Schaltflächen festlegen
Anpassung der Auswahl
Der Selektor input[type="file"]
ist nicht der Schaltflächenteil der Eingabe, sondern das Pseudoelement ::file-selector-button
. Deshalb habe ich input[type="file"]
aus der Liste entfernt:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
}
Cursor- und Touch-Anpassungen
Zuerst gestalte ich den Cursor im Stil pointer
, sodass die Schaltfläche Nutzern der Maus anzeigt, dass sie interaktiv ist. Dann füge ich touch-action: manipulation
hinzu, damit Klicks nicht warten und einen möglichen Doppelklick beobachten müssen, damit sich die Schaltflächen schneller anfühlen:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
cursor: pointer;
touch-action: manipulation;
}
Farben und Rahmen
Als Nächstes passe ich die Schriftgröße, den Hintergrund, den Text und die Rahmenfarben mithilfe einiger der zuvor beschriebenen adaptiven benutzerdefinierten Eigenschaften an:
: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);
}
Schatten
Bei den Schaltflächen wurden tolle Techniken angewandt. Das text-shadow
passt sich an Hell- und Dunkel an und sorgt für ein dezentes Erscheinungsbild des Schaltflächentexts, der schön über dem Hintergrund liegt. Dem box-shadow
werden drei Schatten zugewiesen. Die erste, --_shadow-2
, ist ein normaler Boxschatten.
Der zweite Schatten ist ein Trick für das Auge, der den Eindruck vermittelt, dass die Schaltfläche etwas abgeschrägt wirkt. Der letzte Schatten ist für die Hervorhebung durch Bewegen des Mauszeigers bestimmt. Zu Beginn hat er die Größe 0, erhält aber später eine Größe und geht über die Schaltfläche hinaus.
: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
Ich habe der Schaltfläche ein Flexbox-Layout gegeben, genauer gesagt ein inline-flex
-Layout, das in den Inhalt passt. Dann zentriere ich den Text und richte die untergeordneten Elemente vertikal und horizontal an der center-Position aus. Symbole und andere Schaltflächenelemente
können dann richtig ausgerichtet werden.
: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;
}
Abstand
Für den Schaltflächenabstand habe ich gap
verwendet, um gleichgeordnete Elemente nicht zu berühren, und logische Eigenschaften für den Abstand, damit der Schaltflächenabstand bei allen Textlayouts funktioniert.
: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 für Touch- und Maus-Steuerung
Der nächste Abschnitt richtet sich hauptsächlich an Nutzer mit Touchscreen auf Mobilgeräten. Die erste Eigenschaft user-select
ist für alle Nutzer verfügbar. Sie verhindert, dass Text den Schaltflächentext hervorhebt. Dies macht sich vor allem auf Geräten mit Touchscreen bemerkbar, wenn eine Taste gedrückt wird und das Betriebssystem den Text der Schaltfläche markiert.
Ich habe im Allgemeinen festgestellt, dass dies nicht die Nutzererfahrung mit Schaltflächen in integrierten Apps ist. Deshalb deaktiviere ich sie, indem ich user-select
auf „none“ setze. Tipp-Hervorhebungsfarben (-webkit-tap-highlight-color
) und Betriebssystem-Kontextmenüs (-webkit-touch-callout
) sind weitere sehr weborientierte Schaltflächenfunktionen, die nicht den allgemeinen Nutzererwartungen der Schaltflächen entsprechen. Daher entferne ich sie ebenfalls.
: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;
}
Übergänge
Die adaptive Variable --_transition
ist dem Attribut transition zugewiesen:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
transition: var(--_transition);
}
Wenn der Nutzer den Mauszeiger auf die Schaltfläche bewegt, während er nicht aktiv drückt, passen Sie die Größe der Schatten-Hervorhebung so an, dass der Fokus von der Schaltfläche aus größer wird:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
):where(:not(:active):hover) {
--_highlight-size: .5rem;
}
Vergrößere im Fokus den Fokus, um den Abstand zur Schaltfläche zu vergrößern, damit die Schaltfläche auch optisch zu sehen ist:
:where(button, input):where(:not(:active)):focus-visible {
outline-offset: 5px;
}
Symbole
Zur Verarbeitung von Symbolen wurde im Selektor ein :where()
-Selektor für direkte untergeordnete SVG-Elemente oder Elemente mit dem benutzerdefinierten Attribut data-icon
hinzugefügt. Die Symbolgröße wird mit der benutzerdefinierten Eigenschaft mithilfe von Inline- und Blocklogikeigenschaften festgelegt. Die Strichfarbe wird festgelegt und es wird ein drop-shadow
für text-shadow
festgelegt. flex-shrink
ist auf 0
gesetzt, sodass das Symbol nie zusammengedrückt wird. Zuletzt wähle ich Liniensymbole aus und weise diese Stile hier mit den Linienabschlüssen fill: none
und round
zu:
: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;
}
Senden-Schaltflächen anpassen
Ich wollte, dass das Erscheinungsbild der Schaltflächen etwas verbessert wird. Dazu habe ich die Textfarbe der Schaltflächen als Akzentfarbe festgelegt:
:where(
[type="submit"],
form button:not([type],[disabled])
) {
--_text: var(--_accent);
}
Tasten zum Zurücksetzen anpassen
Ich wollte, dass die Schaltflächen zum Zurücksetzen mit eingebauten Warnhinweisen ausgestattet sind, um Nutzer auf potenziell destruktives Verhalten aufmerksam zu machen. Ich habe auch die Schaltfläche für das helle Design mit mehr roten Akzenten gestaltet als das dunkle. Für die Anpassung wird die entsprechende helle oder dunkle Farbe geändert und der Stil über die Schaltfläche aktualisiert:
: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%);
}
Außerdem fand ich es gut, dass die Farbe des Fokusumrisses zum Rot passt. Die Textfarbe passt sich von Dunkelrot in Hellrot an. Dafür muss die Umrissfarbe dem Keyword currentColor
entsprechen:
:where([type="reset"]):focus-visible {
outline-color: currentColor;
}
Deaktivierte Schaltflächen anpassen
Es kommt häufig vor, dass bei deaktivierten Schaltflächen während des Versuchs, die deaktivierte Schaltfläche zu deaktivieren, einen schlechten Farbkontrast hat, sodass sie weniger aktiv erscheint. Ich habe jeden Farbsatz getestet und überprüft, ob sie bestanden wurde. Dabei werte ich den HSL-Helligkeitswert aus, bis der Wert in den Entwicklertools oder VisBug bestanden wurde.
: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);
}
Schaltflächen zur Dateieingabe anpassen
Die Schaltfläche zur Dateieingabe ist ein Container für einen Span und eine Schaltfläche. CSS kann den Eingabecontainer und die verschachtelte Schaltfläche entsprechend gestalten, aber nicht den Span. Der Container erhält max-inline-size
, damit er nicht größer als nötig wird, während inline-size: 100%
Container verkleinert und kleiner als sie ist. Die Hintergrundfarbe wird auf eine adaptive Farbe festgelegt, die dunkler ist als andere Oberflächen, sodass sie hinter der Dateiauswahlschaltfläche liegt.
:where(input[type="file"]) {
inline-size: 100%;
max-inline-size: max-content;
background-color: var(--_input-well);
}
Die Schaltfläche für die Dateiauswahl und die Schaltflächen für den Eingabetyp erhalten appearance: none
, um alle vom Browser bereitgestellten Stile zu entfernen, die nicht von den anderen Schaltflächenstilen überschrieben wurden.
:where(input[type="button"]),
:where(input[type="file"])::file-selector-button {
appearance: none;
}
Zuletzt wird der Rand zu inline-end
der Schaltfläche hinzugefügt, um den Span-Text von der Schaltfläche wegzuschieben und dadurch etwas Platz zu schaffen.
:where(input[type="file"])::file-selector-button {
margin-inline-end: var(--_padding-inline);
}
Spezielle Ausnahmen für das dunkle Design
Für den Text habe ich einen dunkleren Hintergrund für die primären Aktionsschaltflächen gewählt.
@media (prefers-color-scheme: dark) {
:where(
[type="submit"],
[type="reset"],
[disabled],
form button:not([type="button"])
) {
--_bg: var(--_input-well);
}
}
Varianten erstellen
Aus Spaß und weil es praktisch ist, habe ich gezeigt, wie man ein paar Varianten erstellt. Eine Variante ist sehr farbenfroh, ähnlich wie primäre Schaltflächen häufig aussehen. Eine weitere Variante ist groß. Die letzte Variante hat ein Symbol mit Farbverlauf.
Leuchtende Schaltfläche
Für diesen Schaltflächenstil habe ich die Basis-Requisiten direkt mit blauen Farben überschrieben. Dies war zwar schnell und einfach, aber die adaptiven Requisiten wurden entfernt und sehen in hellen und dunklen Designs gleich aus.
.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%);
}
Große Schaltfläche
Dieser Schaltflächenstil wird durch Ändern der benutzerdefinierten Eigenschaft --_size
erreicht.
Innenabstände und andere Abstandselemente sind relativ zu dieser Größe und werden proportional mit der neuen Größe skaliert.
.btn-large {
--_size: 1.5rem;
}
Symbolschaltfläche
Dieser Symboleffekt hat nichts mit unseren Schaltflächenstile zu tun, zeigt aber, wie er mit nur wenigen CSS-Eigenschaften erreicht wird und wie gut die Schaltfläche Symbole verarbeitet, die kein Inline-SVG sind.
[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));
}
Fazit
Jetzt weißt du, wie ich es gemacht habe. Wie würdest du es erreichen? 🙂
Diversifizieren wir unsere Ansätze und lernen Sie alle Möglichkeiten kennen, wie wir das Web nutzen können.
Erstelle eine Demo und twittere mich über Links, und ich füge sie unten zum Abschnitt über Community-Remixe hinzu.
Community-Remixe
Hier gibt es noch nichts zu sehen.
Ressourcen
- Quellcode auf GitHub