Toto je epizoda # 20 ze série zkoumající moderní CSS řešení problémů, které jsem řešil za posledních 13 a více let, kdy jsme frontendovým vývojářem.
Moderní CSS nám poskytuje řadu vlastností k dosažení vlastních stylů výběru, které mají téměř identické počáteční vzhled pro jednotlivé, vícenásobné a deaktivované prvky select
v horních prohlížečích.
Několik vlastností a technik, které naše řešení použije:
-
clip-path
vytvořit vlastní rozevírací šipku - rozvržení mřížky CSS pro zarovnání nativního výběru a šipky
- vlastních proměnných CSS pro flexibilní styl
-
em
jednotky pro relativní velikost
Běžné problémy s nativními výběry #
Stejně jako u všech typů polí formulářů se i <select>
v různých prohlížečích liší ve svém původním vzhledu.
Zleva doprava, zde je počáteční vzhled <select>
ve Firefoxu, Chrome a Safari:
Mezi rozdíly patří velikost rámečku, velikost písma, výška řádku a nejvíce vyniká rozdíl ve stylu stylů indikátoru rozevíracího seznamu.
Naše cílem je vytvořit stejný počáteční vzhled v těchto prohlížečích, včetně několika výběrů a deaktivovaných stavů.
Poznámka: Rozbalovací seznam stále není stylový, Jakmile je tedy
<select>
otevřen, bude stále vyhledávat styly jednotlivých prohlížečů pro seznamoption
. To je v pořádku – s tím si můžeme poradit, abychom zachovali volnou přístupnost nativního výběru!
Základní HTML #
My “ Zaměřím se na začátek jediného <select>
.
Štítek není součástí našeho stylingového cvičení, ale je zahrnut jako obecný požadavek, zejména u for
atribut s hodnotou id
na <select>
.
Abychom dosáhli svých vlastních stylů, zabalili jsme nativní výběr do zvláštního divu třídou select
pro jednoduchost tohoto tutoriálu.
Obnovit a odebrat zděděné styly #
Jak je součástí všech mých výukových programů jako moderní osvědčený postup, nejprve přidáme následující reset:
Poté, můžeme začít s pravidlem pro nativní select
a aplikovat následující, abychom zachovali jeho vzhled:
Zatímco většina z nich je pravděpodobně známá, oddball out je . Toto je zřídka používaná vlastnost a vy si všimnete, že to není úplně místo, kde bychom ji chtěli kvůli podpoře, ale to, co nám v tomto případě primárně poskytuje, je odstranění šipky rozevíracího seznamu nativního prohlížeče.
Poznámka: CodePen je nastaven tak, aby používal autoprefixer, který přidá požadované přednastavené verze vlastnosti
appearance
. Možná budete muset toto pro svůj projekt konkrétně nastavit nebo je přidat ručně. Můj HTML / Sass Jumpstart obsahuje autoprefixer jako součást produkčního sestavení.
Dobrou zprávou je, že můžeme přidat ještě jedno pravidlo pro získání odstranění šipky pro nižší verze IE, pokud to potřebujete:
Tento tip naleznete v vynikající článek od skupiny Filament Group, který ukazuje alternativní metodu vytváření vybraných stylů.
Poslední částí je odstranění výchozích outline
. Nedělejte si starosti – my “ Později přidám náhradu za :focus
stát!
A tady je gif našeho pokroku. Můžete vidět, že nyní neexistuje žádná vizuální indikace, že se jedná o select
před kliknutím na něj:
Styly vlastního výběrového pole #
Nejprve nechme nastavit některé proměnné CSS. To umožní, aby byl náš výběr flexibilně přebarvován tak, aby představoval chybový stav.
Poznámka k usnadnění přístupu: Jako prvek uživatelského rozhraní musí mít ohraničení kontrastu 3: 1 nebo větší proti barvě okolního povrchu.
Nyní je čas vytvořit vlastní výběrové styly, které použijeme na náš obal div.select
:
Nejprve jsme nastavili určitá omezení šířky. Hodnoty min-width
a max-width
jsou většinou pro tuto ukázku a můžete ji pro svůj případ použití zrušit nebo upravit.
Poté použijeme některé vlastnosti modelu pole, včetně border
, border-radius
a padding
. Všimněte si použití jednotky em
, která udrží tyto vlastnosti úměrné množině font-size
.
Ve resetovacích stylech jsme nastavili několik vlastností na inherit
, takže zde definujeme ty, včetně font-size
, cursor
a line-height
.
Nakonec mu poskytneme vlastnosti pozadí, včetně přechodu pro nejmenší část dimenze. Pokud odeberete vlastnosti pozadí, výběr bude průhledný a vyzvedne pozadí stránky. To může být žádoucí, ale uvědomte si a otestujte dopady na kontrast.
A tady je náš pokrok:
Vlastní Vyberte rozevírací šipku #
Pro naši rozevírací šipku použijeme jednu z nejzajímavějších moderních vlastností CSS: clip-path
.
Ořezové cesty umožňují vytvářet všechny druhy tvarů „ořezáváním“ jinak čtvercových a obdélníkových tvarů, které dostáváme jako výchozí hodnoty od většiny prvků. Bavil jsem se použitím clip-path
na svém nedávném redesignu portfoliového webu.
Před clip-path
lepší podporou byly zahrnuty i alternativní metody:
-
background-image
– obvykle png, o něco modernější by byl SVG - vložený SVG jako další prvek
- hraniční trik k vytvoření trojúhelníku
SVG se může cítit jako optimální řešení, ale při použití jako background-image
ztrácí schopnost chovat se jako ikona ve smyslu, že není schopen o změnit jeho vlastnosti, jako je barva výplně, aniž byste ji zcela předefinovali. To znamená, že nemůžeme použít naši vlastní proměnnou CSS.
Umístěním řádku SVG vyřešíte barevný problém fill
, ale znamená to, že pokaždé, když a <select>
je definováno.
S clip-path
získáme ostrý, škálovatelný „grafický“ šíp, který se bude cítit jako SVG, ale s výhodami možnosti používat naši vlastní proměnnou a být obsažen ve stylu oproti značce HTML.
Chcete-li vytvořit šipku, definujeme ji jako ::after
pseudo-element.
Syntaxe clip-path
je trochu divná, a protože je tento článek není hlavním zaměřením, doporučuji následující zdroje:
- Colby Fayock vysvětluje syntaxi pomocí příkladu v tomto videu s intelektuálem
- Clippy je online nástroj, který umožňuje můžete vybrat tvar a upravit body při dynamickém generování
clip-path
CSS
Pokud jste follo podél křídla, možná jste si všimli, že se šipka neobjevuje navzdory definování width
a height
. Při kontrole bylo zjištěno, že ::after
ve skutečnosti není povolena jeho šířka.
Vyřešíme to aktualizací našeho .select
použít rozložení mřížky CSS.
Tím se šipka zobrazí tak, že ji v podstatě rozšíříte o zobrazovací hodnotu podobnou „bloku“.
V této fázi můžeme ověřit, zda jsme skutečně vytvořili trojúhelník.
Chcete-li zarovnání opravit, použijeme můj oblíbený CSS grid hack (starý klobouk, pokud jste si přečetli několik článků zde!).
Staré řešení CSS: position: absolute
Nové řešení CSS: Jediný grid-template-areas
, který je obsahuje všechny
Nejprve definujeme naši oblast, pak definujeme, že select
a ::after
to oba používají. Název je vymezen na prvek, pro který byl vytvořen, a my ho „ulehčíme voláním„ select “:
Což nám dává překrývání šipka nad nativním výběrem kvůli kontextu stohování prostřednictvím zdrojové objednávky:
K dokončení zarovnání nyní můžeme použít vlastnosti mřížky každého prvku:
Ta-da!
: focus state #
No jo – pamatujete si, jak jsme odstranili outline
? Musíme vyřešit chybějící :focus
stav z toho upuštění.
Existuje nadcházející vlastnost, kterou bychom mohli použít, nazvaná :focus-within
, ale stále je nejlepší do ní zahrnout polyfill času.
V tomto výukovém programu použijeme alternativní metodu, která dosáhne stejného výsledku, jen o něco heftierější.
Bohužel to znamená, že musíme přidat jeden další prvek do DOM.
Po nativním prvku select jako poslední dítě v .select
, přidat:
Proč? Protože se jedná o čisté řešení CSS, jeho umístění po nativním výběru znamená, že jej můžeme změnit, když je select
zaměřen pomocí sousedního voliče sourozenců – +
.
To nám umožňuje vytvořit následující pravidlo:
Možná si říkáte, proč se vracíme k position: absolute
po pouhém seznámení se s předchozím grid-area
hackem.
Důvodem je vyhnout se přepočtu úprav na základě odsazení. Pokud to zkusíte na vlastní pěst, uvidíte, že i když width
a height
na 100% stále sedíte v polstrování .
Úloha position: absolute
se nejlépe hodí k přizpůsobení velikosti prvku. Stahujeme z něj další pixel v každém směru, abychom se ujistili, že překrývá hranici vlastnost.
Musíme však přidat ještě jeden doplněk k .select
, abychom zajistili, že je to relativní k našemu výběru podle – no, position: relative
.
A tady je náš vlastní výběr všeho, jak je vidět v prohlížeči Chrome:
Vícenásobný výběr #
Výběr má druhou příchuť, která uživateli umožňuje vybrat více než jednu možnost. Z pohledu HTML to jednoduše znamená přidat atribut multiple
, ale přidáme také třídu, která nám pomůže vytvořit úpravy stylu s názvem select--multiple
:
A při pohledu na to vidíme, že většina našich stylů je zděděna příznivě, až na to, že v tomto pohledu šipku nepotřebujeme.
Toto je rychlá oprava k nastavení našeho selektoru, který definuje šipku. Pomocí :not()
vylučujeme nově definovanou třídu:
Pro vícenásobný výběr máme provést několik drobných úprav, první je odstranění výplně, která byla dříve přidána, aby se vytvořil prostor pro šipku:
Ve výchozím nastavení budou možnosti s dlouhou hodnotou přetékat viditelnou oblastí a budou oříznuty, ale zjistil jsem, že hlavní prohlížeče umožňují přepsání obtékání, pokud si přejete:
Volitelně můžeme nastavit height
na výběr, který přinese trochu spolehlivější chování mezi prohlížeči. Při testování jsem zjistil, že Chrome a Firefox zobrazí částečnou možnost, ale Safari úplně skryje možnost, kterou nelze plně zobrazit.
Výška musí být nastavena přímo v nativním výběru . Vzhledem k našim dalším stylům bude hodnota 6rem
schopna zobrazit 3 možnosti:
V tomto okamžiku vzhledem k současné podpoře prohlížeče jsme provedli tolik úprav, kolik jsme schopni.
Stav
:selected
options
je docela přizpůsobitelný v prohlížeči Chrome, něco ve Firefoxu, a vůbec ne v Safari. V ukázce CodePen najdete sekci, kterou lze odkomentovat a zobrazit její náhled.
: deaktivované styly #
I když bych se zastával jednoduše nezobrazovat zakázané ovládací prvky, měli bychom připravit styly pro tento stav, abychom pokryli naše základny.
Abychom zdůraznili deaktivovaný stav, chceme použít šedé pozadí. Ale protože jsme nastavili styly pozadí na .select
a není tam selektor „ta :parent
, musíme vytvořit poslední třídu, kterou budeme zpracovávat pro tento stav:
Zde jsme aktualizovali kurzor jako další nápovědu, se kterou nelze pole interagovat, a aktualizovali jsme hodnoty pozadí, které jsme dříve nastavili na být bílá, aby nyní byla pro deaktivovaný stav více šedá.
Výsledkem budou následující vzhledy:
Demo #
Můžete si to vyzkoušet sami, ale zde je náhled úplného řešení napříč (zleva) Firefox, Chrome a Safari:
Stephanie Eckles (@ 5t3ph)