Dies ist Episode 20 in einer Reihe, in der moderne CSS-Lösungen für Probleme untersucht werden, die ich gelöst habe In den letzten mehr als 13 Jahren als Frontend-Entwickler.
Modernes CSS bietet uns eine Reihe von Eigenschaften, um benutzerdefinierte Auswahlstile zu erzielen, die nahezu identisch sind Erstes Erscheinungsbild für einzelne, mehrere und deaktivierte select
-Elemente in den Top-Browsern.
Einige Eigenschaften und Techniken, die unsere Lösung verwenden wird:
-
clip-path
zum Erstellen des benutzerdefinierten Dropdown-Pfeils - CSS-Rasterlayout zum Ausrichten der nativen Auswahl- und Pfeil
- benutzerdefinierten CSS-Variablen für flexibles Styling
-
em
Einheiten für die relative Größe
Häufige Probleme mit nativen Auswahlen #
Wie bei allen Formularfeldtypen variiert <select>
in der ursprünglichen Darstellung zwischen den Browsern.
Von links nach rechts sehen Sie hier das erste Erscheinungsbild von <select>
in Firefox, Chrome und Safari:
Die Unterschiede umfassen Boxgröße, Schriftgröße, Zeilenhöhe und das herausragendste ist der Unterschied in der Gestaltung der Dropdown-Anzeige.
Unsere Ziel ist es, in diesen Browsern das gleiche Erscheinungsbild zu erzielen, einschließlich Mehrfachauswahl und deaktivierter Zustände.
Hinweis: Die Dropdown-Liste ist immer noch nicht stilisierbar. Sobald die Datei
<select>
geöffnet ist, werden die Stile der einzelnen Browser für die Listeoption
übernommen. Dies ist in Ordnung – wir können damit umgehen, um die freie Zugänglichkeit einer nativen Auswahl beizubehalten!
Basis-HTML #
We “ Ich werde mich zunächst auf eine einzelne <select>
konzentrieren.
Das Etikett ist nicht Teil unserer Styling-Übung, wird jedoch als allgemeine Anforderung verwendet, insbesondere bei der for
-Attribut mit dem Wert id
auf dem <select>
.
Um unsere benutzerdefinierten Stile zu erreichen, haben wir die native Auswahl zur Vereinfachung in diesem Lernprogramm in ein zusätzliches Div mit der Klasse select
eingeschlossen.
Vererbte Stile zurücksetzen und entfernen #
Wie in allen meinen Tutorials als moderne Best Practice enthalten, fügen wir zuerst den folgenden Reset hinzu:
Anschließend Wir können die Regel für das native select
beginnen und Folgendes anwenden, um sein Erscheinungsbild zu verbessern:
Während die meisten davon wahrscheinlich bekannt sind, ist der seltsame Ausgang . Dies ist eine selten verwendete Eigenschaft, und Sie werden feststellen, dass es nicht genau dort ist, wo wir sie zur Unterstützung wünschen, aber in diesem Fall ist sie in erster Linie für uns das Entfernen des Dropdown-Pfeils des nativen Browsers. P. >
Hinweis: Der CodePen ist für die Verwendung des Autoprefixers eingerichtet, der die erforderlichen voreingestellten Versionen der Eigenschaft
appearance
hinzufügt. Möglicherweise müssen Sie dies speziell für Ihr Projekt einrichten oder manuell hinzufügen. Mein HTML / Sass-Starthilfe enthält Autoprefixer als Teil des Produktionsbuilds.
Die gute Nachricht ist, dass wir eine weitere Regel hinzufügen können, um den Pfeil für niedrigere IE-Versionen zu entfernen, wenn Sie ihn benötigen:
Dieser Tipp befindet sich in der Hervorragender Artikel aus der Filament Group, der eine alternative Methode zum Erstellen ausgewählter Stile zeigt.
Der letzte Teil besteht darin, die Standardeinstellung outline
zu entfernen. Keine Sorge – wir “ Ich werde später einen Ersatz für die :focus
state!
Und hier ist ein GIF unseres Fortschritts. Sie können sehen, dass jetzt keine visuelle Anzeige mehr vorliegt, dass dies eine select
ist, bevor Sie darauf klicken:
Benutzerdefinierte Auswahlfeldstile #
Lassen Sie uns zunächst einige CSS-Variablen einrichten. Dadurch kann unsere Auswahl flexibel neu eingefärbt werden, um einen Fehlerzustand darzustellen.
Hinweis zur Barrierefreiheit: Als Element der Benutzeroberfläche muss der Auswahlrahmen einen 3: 1-Kontrast haben oder größer gegen die Farbe der umgebenden Oberfläche.
Jetzt ist es an der Zeit, die benutzerdefinierten Auswahlstile zu erstellen, die wir auf unsere Umhüllung anwenden werden div.select
:
Zuerst richten wir einige Breitenbeschränkungen ein. Die Werte min-width
und max-width
gelten hauptsächlich für diese Demo. Sie können sie für Ihren Anwendungsfall löschen oder ändern. P. >
Anschließend wenden wir einige Eigenschaften des Boxmodells an, darunter border
, border-radius
und padding
. Beachten Sie die Verwendung der Einheit em
, die diese Eigenschaften proportional zur Menge font-size
hält.
In den Reset-Stilen setzen wir mehrere Eigenschaften auf inherit
. Hier definieren wir diese, einschließlich font-size
, cursor
und line-height
.
Schließlich liefern wir Hintergrundeigenschaften, einschließlich eines Verlaufs für das kleinste Stück von Abmessungen. Wenn Sie die Hintergrundeigenschaften entfernen, ist die Auswahl transparent und nimmt den Seitenhintergrund auf. Dies kann jedoch wünschenswert sein. Beachten Sie die Auswirkungen auf den Kontrast.
Und hier ist unser Fortschritt:
Benutzerdefiniert Wählen Sie den Dropdown-Pfeil #
Für unseren Dropdown-Pfeil verwenden wir eine der aufregendsten modernen CSS-Eigenschaften: clip-path
.
Mit Clip-Pfaden können wir alle Arten von Formen erstellen, indem wir die ansonsten quadratischen und rechteckigen Formen, die wir standardmäßig von den meisten Elementen erhalten, „beschneiden“. Ich hatte Spaß daran, clip-path
bei meiner kürzlich erfolgten Neugestaltung der Portfolio-Site zu verwenden.
Bevor clip-path
eine bessere Unterstützung hat, sind alternative Methoden enthalten:
-
background-image
– In der Regel ist ein png, etwas moderner ein SVG - ein Inline-SVG als zusätzliches Element
- der Randtrick zum Erstellen eines Dreiecks
SVG mag sich als die optimale Lösung anfühlen, aber wenn es als background-image
verwendet wird, verliert es die Fähigkeit, sich wie ein Symbol in dem Sinne zu verhalten, dass es nicht in der Lage ist, t o Ändern Sie seine Eigenschaften wie die Füllfarbe, ohne sie vollständig neu zu definieren. Dies bedeutet, dass wir unsere benutzerdefinierte CSS-Variable nicht verwenden können.
Durch Platzieren einer SVG-Inline wird das Farbproblem fill
behoben. Es bedeutet jedoch, jedes Mal ein weiteres Element einzuschließen, wenn ein <select>
ist definiert.
Mit clip-path
erhalten wir eine gestochen scharfe, skalierbare Pfeilgrafik, die sich jedoch wie eine SVG anfühlt Mit dem Vorteil, dass Sie unsere benutzerdefinierte Variable verwenden können und im Stil im Vergleich zum HTML-Markup enthalten sind.
Um den Pfeil zu erstellen, definieren wir ihn als ::after
Pseudoelement.
Die clip-path
-Syntax ist etwas seltsam, und da es „s“ ist Ich empfehle die folgenden Ressourcen:
- Colby Fayock erläutert die Syntax anhand eines Beispiels in diesem Egghead-Video.
- Clippy ist ein Online-Tool, das dies ermöglicht Sie können eine Form auswählen und die Punkte anpassen, während Sie dynamisch das
clip-path
CSS
generieren, wenn Sie folgen Möglicherweise haben Sie bemerkt, dass der Pfeil trotz der Definition von width
und height
nicht angezeigt wird. Bei der Überprüfung wurde festgestellt, dass die Breite des ::after
tatsächlich nicht zulässig ist.
Wir werden dies beheben, indem wir unsere , um das CSS-Rasterlayout zu verwenden.
Dadurch wird der Pfeil angezeigt, indem er im Wesentlichen um einen Anzeigewert erweitert wird, der „block“ ähnelt.
In diesem Stadium können wir überprüfen, ob wir tatsächlich ein Dreieck erstellt haben.
Um die Ausrichtung zu korrigieren, Wir werden meinen Lieblings-CSS-Grid-Hack verwenden (alter Hut für Sie, wenn Sie hier ein paar Artikel gelesen haben!).
Alte CSS-Lösung: position: absolute
Neue CSS-Lösung: Eine einzelne grid-template-areas
, die alle enthält
Zuerst definieren wir unseren Bereich und dann die select
und die ::after
verwenden es beide. Der Name ist auf das Element beschränkt, für das er erstellt wurde, und wir werden es einfach halten, indem wir ihn „select“ nennen:
Dies gibt uns eine Überlappung von Der Pfeil über der nativen Auswahl aufgrund des Stapelkontexts über die Quellreihenfolge:
Wir können jetzt Rastereigenschaften verwenden, um die Ausrichtung abzuschließen von jedem Element:
Ta-da!
: Fokusstatus #
Oh ja – erinnern Sie sich, wie wir die outline
entfernt haben? Wir müssen die fehlende :focus
Zustand vom Löschen.
Es gibt eine bevorstehende Eigenschaft namens :focus-within
, aber es ist immer noch am besten, eine Polyfüllung dafür hinzuzufügen Zeit.
In diesem Tutorial verwenden wir eine alternative Methode, mit der das gleiche Ergebnis erzielt wird, nur ein bisschen kräftiger.
Leider bedeutet dies, dass wir ein weiteres Element hinzufügen müssen das DOM.
Nach dem nativen Auswahlelement als letztes Kind innerhalb von .select
, füge hinzu:
Warum danach? Da dies eine reine CSS-Lösung ist, bedeutet das Platzieren nach der nativen Auswahl, dass wir sie ändern können, wenn die select
mithilfe des benachbarten Geschwister-Selektors – .
Auf diese Weise können wir die folgende Regel erstellen:
Sie fragen sich möglicherweise, warum wir wieder zu position: absolute
nachdem ich gerade den vorherigen grid-area
Hack gelernt habe.
Der Grund dafür ist, dass Anpassungen aufgrund der Polsterung nicht neu berechnet werden. Wenn Sie es selbst versuchen, werden Sie feststellen, dass selbst wenn Sie width
und height
auf 100% setzen, es immer noch innerhalb der Polsterung sitzt
Der Job position: absolute
passt am besten zur Größe eines Elements. Wir ziehen ein zusätzliches Pixel in jede Richtung, um sicherzustellen, dass es den Rand überlappt Eigenschaft.
Wir müssen jedoch noch eine weitere Ergänzung zu .select
vornehmen, um sicherzustellen, dass es relativ zu unserer Auswahl von – na ja, .
Und hier ist unsere benutzerdefinierte Auswahl, wie in Chrome gezeigt:
Mehrfachauswahl #
Die Auswahl erfolgt in einer zweiten Variante, mit der ein Benutzer mehr als eine Option auswählen kann. Aus HTML-Sicht bedeutet dies einfach, das Attribut multiple
hinzuzufügen. Wir werden jedoch auch eine Klasse hinzufügen, um Stilanpassungen mit dem Namen select--multiple
zu erstellen :
Und wenn wir es uns ansehen, können wir sehen, dass es die meisten unserer Stile positiv vererbt hat, außer dass wir den Pfeil in dieser Ansicht nicht benötigen.
Dies ist eine schnelle Lösung zum Anpassen unseres Selektors, der den Pfeil definiert. Wir verwenden :not()
, um unsere neu definierte Klasse auszuschließen:
Wir müssen einige kleinere Anpassungen für die Mehrfachauswahl vornehmen. Die erste ist das Entfernen der zuvor hinzugefügten Polsterung, um Platz für den Pfeil zu schaffen:
Standardmäßig laufen Optionen mit einem langen Wert über den sichtbaren Bereich und werden abgeschnitten. Ich habe jedoch festgestellt, dass die Hauptbrowser das Umschreiben des Umbruchs ermöglichen, wenn Sie dies wünschen:
Optional können wir eine height
für die Auswahl festlegen, um a zu bringen etwas zuverlässigeres browserübergreifendes Verhalten. Durch das Testen habe ich erfahren, dass Chrome und Firefox eine Teiloption anzeigen, Safari jedoch eine Option vollständig ausblendet, die nicht vollständig angezeigt werden kann.
Die Höhe muss direkt in der nativen Auswahl festgelegt werden . In Anbetracht unserer anderen Stile kann der Wert 6rem
drei Optionen anzeigen:
Zu diesem Zeitpunkt Aufgrund der aktuellen Browserunterstützung haben wir so viele Anpassungen wie möglich vorgenommen.
Der Status
:selected
vonoptions
ist in Chrome ziemlich anpassbar, etwas in Firefox und überhaupt nicht in Safari. In der CodePen-Demo finden Sie einen Abschnitt, der nicht kommentiert werden kann, um eine Vorschau anzuzeigen.
: deaktivierte Stile #
Ich würde mich dafür einsetzen Da deaktivierte Steuerelemente einfach nicht angezeigt werden, sollten wir die Stile für diesen Status vorbereiten, um unsere Grundlagen abzudecken.
Um den deaktivierten Status hervorzuheben, möchten wir einen grau hinterlegten Hintergrund anwenden. Da wir jedoch Hintergrundstile für .select
festgelegt haben und es keinen „ta :parent
-Selektor gibt, müssen wir eine letzte Klasse erstellen, für die verarbeitet werden soll Dieser Status:
Hier haben wir den Cursor als zusätzlichen Hinweis aktualisiert, mit dem das Feld nicht interagieren kann, und die zuvor festgelegten Hintergrundwerte aktualisiert weiß sein, um jetzt für den deaktivierten Status grauer zu sein.
Dies führt zu folgenden Erscheinungen:
Demo #
Sie können es selbst testen, aber hier ist eine Vorschau der vollständigen Lösung für Firefox, Chrome und Safari (von links):
Von Stephanie Eckles (@ 5t3ph)