CSS3 a detekce podporovaných vlastností pomocí pravidla @supports

Proti každému webdesignerovi stojí celá fronta prohlížečů s dosti rozličnou podporou kaskádových stylů. Existují různé strategie, jak se s tímto problémem vypořádat. Jedná se nejspíš o věčný problém a detekce podporovaných vlastností se dostává přímo do CSS3.
Tento text je překladem článku Native CSS feature detection via the @supports rule, jehož autorem je Chris Mills a je zde zveřejněn pod licencí CC-BY-3.0.
Úvod
Podpora standardů v dnes používaných prohlížečích se dosti liší (od moderních prohlížečů po křápy jako IE6), a tak nám není proti srsti nabízet různým prohlížečům odlišný kód nabízející sice odlišný, ale stále přijatelný uživatelský zážitek. Dělá se to různými způsoby, obecně se spoléhá buď na (méně spolehlivou) detekci prohlížečů nebo na (chytřejší) detekci podporovaných vlastností.
Detekci vlastností obyčejně vykonáte vlastním kódem v JavaScriptu, kterým otestujete existenci patřičné vlastnosti, metody atd. nebo pomocí nějaké knihovny, jakou je např. skvělý Modernizr. Modernizr nabízí detekci řady vlastností HTML5 a CSS3 a mechanismus pro selektivní použití CSS a JavaScriptu na základě této detekce.
Je to užitečné, ale řada lidí se sháněla po nativním mechanismu. Dobrá zpráva je, že jsme na něm začali pracovat. Tento článek popisuje CSS pravidlo @supports
, které je součástí specifikace CSS3 Conditional Rules Module Level 3, která nabízí mechanismus pro selektivní použití kaskádových stylů na základě podporovaných vlastností. Podíváme se na základní syntaxi a ukážeme si příklad.
Pozn.: @supports
je zatím podporován v Opeře 12.10 a Firefoxu Aurora; prohlížeče neznající @supports
budou tento blok zcela ignorovat. To znamená, že tu už pro něj máme použití, ale pokud vám nestačí, zůstaňte zatím ještě u Modernizeru.
Syntaxe @supports
@supports
má podobu at-rule bloku („zavináčového pravidla“), které spustí test a vykoná CSS pravidla uvnitř bloku na základě toho, zda test vrátil true nebo ne. V tomto případě test vždy sestává z jedné nebo vícero deklarací CSS a prohlížeč vrátí true, pokud uvedené deklarace podporuje, např.:
@supports (display:flex) { section { display: flex } ... }
Pravidla uvnitř tohoto bloku budou použita, jen pokud prohlížeč podporuje display: flex
.
@supports
také podporuje klíčové slovo not
, můžeme tak použít styly pouze v případě, že daná vlastnosti není podporovaná. Mohli bychom tak nabídnout alternativní styl prohlížečům nepodporujícím display:flex
:
@supports not (display: flex) { // alternatiní layout // např. pomocí float }
@supports
také podporuje klíčová slova or
a and
, která zajistí aplikaci stylů jen v případě, že prohlížeč projde vícero testy nebo v případě, že test projde jedním z několika odlišných testů.
Kupříkladu flexbox je bez vendor prefixu podporovaný Operou a IE10. Pro otestování, zda prohlížeč podporuje vlastnost s prefixem nebo bez prefixu, můžete zapsat:
@supports (display: -webkit-flex) or (display: -moz-flex) or (display: flex) { section { display: -webkit-flex; display: -moz-flex; display: flex; … } }
A ještě příklad pro and
: mohli byste chtít použít multi-column layout pouze v prohlížečích, které podporují neprefixované vlastnosti column-width
a column-span
(prohlížeče, které podporují multi-col s prefixem, prozatím nepodporují column-span
, což je dost omezující):
@supports (column-width: 20rem) and (column-span: all) { div { column-width: 20rem } div h2 { column-span: all } div h2 + p { margin-top: 0; } ... }
A nesmíme zapomenout uvést, že kombinace and
, or
a not
je nutné uvádět s pomocí závorek, aby byly jasné jejich priority. Mohli byste chtít použít animaci zahrnující 3D transformaci pouze v prohlížečích podporujících animace a 3D transformace:
@supports ((-webkit-animation-name: my-animation) and (-webkit-transform: rotate3D(1,2,4,90deg))) or ((-moz-animation-name: my-animation) and (-moz-transform: rotate3D(1,2,4,90deg))) or ((-ms-animation-name: my-animation) and (-ms-transform: rotate3D(1,2,4,90deg))) or ((-o-animation-name: my-animation) and (-o-transform: rotate3D(1,2,4,90deg))) or ((animation-name: my-animation) and (transform: rotate3D(1,2,4,90deg))) { // sem přijde vaše skvělá animace }
Malá ukázka
Abych vám předvedl použití @supports
, upravím příklad z mé knihy Practical CSS3: develop and design — 3D rotující vizitka, která využívala Modernizr, aby nabídla alternativní zážitek prohlížečům bez podpory 3D a 2D transformací (jen jsem při hover zvětšil left padding, aby se odkryla zadní strana). Příklad pomocí Modernizeru si můžete zobrazit online. Na obrázcích 1 až 3 předvedu odlišný výsledek v závislosti na podpoře v prohlížečích.

Obr. 1: V prohlížečích podporujících 3D transformace se vizitka animovaně otočí.

Obr. 2: V prohlížečích bez podpory 3D transformací, ale s podporou 2D transformací, se přední strana vizitky animovaně odsune, a tím se zobrazí i její zadní strana.

Obr. 3: V prohlížečích bez podpory 3D a 2D transformací se přední strana vizitky jednoduše posune, aby se zobrazila i zadní strana vizitky.
V tomto příkladu jsem nabídl fallback kód prohlížečům bez podpory 3D transformací a následně i těm, které nepodporují ani 2D transformace. V našem příkladě za pomoci @supports budu postupovat opačně pomocí přístupu progressive enhancement. Napřed nabídnu základní funkčnost, která zobrazí obě dvě strany vizitky prakticky všem prohlížečům:
/* || Pro prohlížeče bez podpory 2D a 3D transformací */ #wrapper:hover #inner-wrapper #front, #wrapper:focus #inner-wrapper #front { margin-left: -350px; }
Starší prohlížeče použijí tento kód a další pravidla uvnitř @supports
budou ignorovat.
Přidáme pravidla pro prohlížeče s podporou 2D transformací:
/* || Pro prohlížeče podporující 2D transformace */ @supports (-webkit-transform: rotate(-30deg)) or (-moz-transform: rotate(-30deg)) or (-ms-transform: rotate(-30deg)) or (-o-transform: rotate(-30deg)) or (transform: rotate(-30deg)) { #inner-wrapper #front { -webkit-transition: 0.8s all ease-in; -moz-transition: 0.8s all ease-in; -ms-transition: 0.8s all ease-in; -o-transition: 0.8s all ease-in; transition: 0.8s all ease-in; } #wrapper:hover #inner-wrapper #front, #wrapper:focus #inner-wrapper #front { margin-left: 0; -webkit-transform: rotate(-30deg) translate(-50%,-100%); -moz-transform: rotate(-30deg) translate(-50%,-100%); -ms-transform: rotate(-30deg) translate(-50%,-100%); -o-transform: rotate(-30deg) translate(-50%,-100%); transform: rotate(-30deg) translate(-50%,-100%); } }
A nakonec přidáme kód pro prohlížeče podporující 3D transformace:
/* || Pro prohlížeče podporující 3D transformace */ @supports (-webkit-transform: rotateX(0deg)) or (-moz-transform: rotateX(0deg)) or (-ms-transform: rotateX(0deg)) or (-o-transform: rotateX(0deg)) or (transform: rotateX(0deg)) { #front, #back { -webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; -ms-backface-visibility: hidden; -o-backface-visibility: hidden; backface-visibility: hidden; } #front { -webkit-transform: rotateX(0deg); -moz-transform: rotateX(0deg); -ms-transform: rotateX(0deg); -o-transform: rotateX(0deg); transform: rotateX(0deg); } #back { -webkit-transform: rotateX(180deg); -moz-transform: rotateX(180deg); -ms-transform: rotateX(180deg); -o-transform: rotateX(180deg); transform: rotateX(180deg); } #wrapper:hover #inner-wrapper, #wrapper:focus #inner-wrapper { -webkit-transform: rotateX(180deg); -moz-transform: rotateX(180deg); -ms-transform: rotateX(180deg); -o-transform: rotateX(180deg); transform: rotateX(180deg); } #wrapper:hover #inner-wrapper #front, #wrapper:focus #inner-wrapper #front { -webkit-transform: none; -moz-transform: none; -ms-transform: none; -o-transform: none; transform: none; } }
window.supportsCSS();
Opera 12.10 je v tuhle chvíli jediný prohlížeč, který vedle supports
podporuje i odpovídající javascriptové API, které umožňuje spouštět kód na základě podpory CSS vlastností. Přepíšu úvodní příklad do JavaScriptu:
var flexy = window.supportsCSS('display:flex'); if(flexy) { alert('Podporuji Flexbox!'); }
Ve specifikaci můžete najít syntaxi CSS.supports
a nikoliv window.supportsCSS
. To protože jsme implementovali starší verzi specifikace a navíc jsme se u použití globálního objektu CSS
báli konfliktů se stávajícími weby. Ještě se ukáže, jak se tenhle problém vyřeší.
Shrnutí
A tím naše představení @supports
končí. Jedná se rozhodně o zajímavou vlastnost pomocí které můžete spolehlivě detekovat podporované vlastnosti a nabízet dle toho příslušný CSS kód. Problémem jsou starší prohlížeče nepodporující @supports
, kterým musíte nabídnout alternativní cestu. Doufáme, že to bylo pro vás přínosné a předpokládáme, že tahle vlastnost začne být časem mnohem víc užitečná. Dejte nám vědět, co si o ní myslíte, váš feedback nám můžete napsat do mailing listu www-style.
Rozměry prvků v rem se předpokládám zadávají jen v designech určených pro prohlížení v noci. .)
http://caniuse.com/#feat=rem
rem frčí docela dlouho
Trochu mi to připomíná WordArt nebo weby, které se dělaly před pěknými pár lety. Taky jsem kdysi takové stránky měl, písmo v plamenech a dokonce to bylo animované. Jo, to byly časy :-)
Zajímalo by mě, jestli jde tímto způsobem ověřit například, jestli bude fungovat použití SVG jako backround URL, takhle:
Nebo jestli to jen ověří, že je podporovaná vlastnost background a projde to. Nemůžu to momentálně vyzkoušet.
Díky
Zkoušel jsem v aktuální Opeře 12.11 a ta skrze supports hlásí, že podporuje, ať už do url() napíši cokoliv, třeba i „document.doc“. Netuším, zda jde je to problém specifikace, nebo implementace.
Když jsem zkoušel podporu pro „color: nesmysl;“ nebo „width: 100nesmysl“, tak se opera skrze supports hlásí, že nepodporuje, obdobně je to i pro další CSS vlastnosti.
Neužitečná zajímavost:
Všechny prohlížeče ve quirk režimu chápou nenulovou délku bez jednotky jako pixely, ale Opera skrze supports hlásí, že nepodporuje.