Tento článok ukazuje, ako pomocou CSS transformácie, perspektívy a nejakých scale trikov vytvoríme len z čistého CSS parallax efekt web stránky pri scrolovaní.
Parallax je takmer vždy zviazaný s JavaScriptom. Čo keby ste ale mohli úplne odstrániť závislosť na JavaScripte a vytvoriť paralax efekt bez neho? Prehliadaču tým umožníte naplno využiť hardverovú akceleráciu a výsledkom bude konzistentná snímková frekvencia a dokonalé plynulé posúvanie.
Než sa ponoríme do teórie ako efekt funguje – poďme si vytvoriť základný layout:
<div class="parallax"> <div class="parallax__layer parallax__layer--back"> ... </div> <div class="parallax__layer parallax__layer--base"> ... </div> </div>
A tu je základné CSS nášho parallax efektu:
.parallax { perspective: 1px; height: 100vh; overflow-x: hidden; overflow-y: auto; } .parallax__layer { position: absolute; top: 0; right: 0; bottom: 0; left: 0; } .parallax__layer--base { transform: translateZ(0); } .parallax__layer--back { transform: translateZ(-1px); }
V triede parallax definujeme výšku a perspektívnu nášho prvku / elementu, ktorú zamkneme do jeho stredu. Nastavenie overflow-y: auto umožní obsah vo vnútri prvku posúvať obvyklým spôsobom, ale teraz sa potomkovia prvku budú renderovať relatívne vzhľadom na fixný pohľad. To je kľúč k vytvoreniu parallax efektu.
Ďalej máme triedu parallax__layer. Ako už názov napovedá, definuje vrstvu obsahu, na ktorý bude aplikovaný parallax efekt – prvok je vytiahnutý z obsahu a nakonfigurovaný tak, aby vyplnil priestor kontajnera.
Nakoniec máme modifikátor tried .parallax__layer–base a .parallax__layer–back. Tie sú určené na definovanie rýchlosti posúvania parallax elementu pozdĺž osi Z. Pre stručnosť som definoval iba rýchlosť dvoch vrstiev – ďalšie pridáme ešte neskôr.
Korekcia hĺbky
Vzhľadom na to, že vytvorený parallax efekt používa 3D transformáciu, posúvanie prvku pozdĺž osi Z má vedľajší efekt – účinná zmena veľkosti prvku bude závisieť toho, či je bližšie alebo ďalej vzdialený od výrezu. Proti tomu je potrebné použiť scale() transformáciu na prvok – takže sa nám bude zdať, že sa renderuje v jeho pôvodnej veľkosti:
.parallax__layer--back { transform: translateZ(-1px) scale(2); }
Mierku (scale factor) možno vypočítať prostredníctvom vzorca: 1 + (translateZ * -1) / perspective. Napríklad: ak vaša perspektíva je nastavená na 1px a translateZ na -2px – scale factor by bol 3:
.parallax__layer--deep { transform: translateZ(-2px) scale(3); }
Sledovanie rýchlosti vrstvy
Rýchlosť vrstvy je závislá od kombinácie perspektívy a translateZ. Prvky s negatívnymi hodnotami translateZ sa budú rolovať pomalšie než tie, ktoré budú mať kladnú hodnotu. Ďalej hodnota od 0 má výraznejší vplyv na parallax (t.j. translateZ(-10px) sa bude posúvať pomalšie ako translateZ(-1px)).
Paralax section
Predchádzajúce príklady ukázali základné techniky pomocou veľmi jednoduchého obsahu, ale väčšina stránok s parallaxom rozbije stránku do odlišných častí, kde je možné aplikovať rôzne efekty. Tu je návod, ako to urobiť.
Po prvé, potrebujeme prvok parallax__group, aby sme spojili do skupiny naše vrstvy:
<div class="parallax"> <div class="parallax__group"> <div class="parallax__layer parallax__layer--back"> ... </div> <div class="parallax__layer parallax__layer--base"> ... </div> </div> <div class="parallax__group"> ... </div> </div>
Tu je CSS pre element skupiny:
.parallax__group { position: relative; height: 100vh; transform-style: preserve-3d; }
V tomto príklade chcem, aby všetky skupiny vyplnili výrez, takže som nastavil výšku: 100vh, ale ľubovoľné hodnoty možno nastaviť v prípade potreby pre každú skupinu zvlášť. Transform-style: preserve-3d zabraňuje prehliadaču sploštenie prvku s triedou parallax__layer a position: relative slúži umožniť elementu parallax__layer child, aby sa umiestnilo relatívne do skupiny.
Podpora prehliadačov
Všetky moderné prehliadače v najnovších verziách podporujú použité vlastnosti CSS3 (Firefox, Opera, Chrome). Problém je s IE, ktorý nepodporuje preserve-3d a preto parallax efekt v ňom nefunguje.
A teraz sa možeme pozrieť na kompletný kód parallax efektu v praxi.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <meta name="robots" content="noindex, nofollow"> <title>Ako vytvoriť paralax efekt web stránky v CSS</title> <style> /* Parallax base styles --------------------------------------------- */ .parallax { height: 500px; /* fallback for older browsers */ height: 100vh; overflow-x: hidden; overflow-y: auto; -webkit-perspective: 300px; perspective: 300px; } .parallax__group { position: relative; height: 500px; /* fallback for older browsers */ height: 100vh; -webkit-transform-style: preserve-3d; transform-style: preserve-3d; } .parallax__layer { position: absolute; top: 0; left: 0; right: 0; bottom: 0; } .parallax__layer--fore { -webkit-transform: translateZ(90px) scale(.7); transform: translateZ(90px) scale(.7); z-index: 1; } .parallax__layer--base { -webkit-transform: translateZ(0); transform: translateZ(0); z-index: 4; } .parallax__layer--back { -webkit-transform: translateZ(-300px) scale(2); transform: translateZ(-300px) scale(2); z-index: 3; } .parallax__layer--deep { -webkit-transform: translateZ(-600px) scale(3); transform: translateZ(-600px) scale(3); z-index: 2; } /* demo styles --------------------------------------------- */ body, html { overflow: hidden; height: 100%; } body { font: 100% / 1.5 Arial; } * { margin:0; padding:0; } .parallax { font-size: 200%; } /* centre the content in the parallax layers */ .title { text-align: center; position: absolute; left: 50%; top: 50%; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); } /* style the groups --------------------------------------------- */ #group1 { z-index: 5; /* slide over group 2 */ } #group1 .parallax__layer--base { background: rgb(102,204,102); } #group2 { z-index: 3; /* slide under groups 1 and 3 */ } #group2 .parallax__layer--back { background: rgb(123,210,102); } #group3 { z-index: 4; /* slide over group 2 and 4 */ } #group3 .parallax__layer--base { background: rgb(153,216,101); } #group4 { z-index: 2; /* slide under group 3 and 5 */ } #group4 .parallax__layer--deep { background: rgb(184,223,101); } #group5 { z-index: 3; /* slide over group 4 and 6 */ } #group5 .parallax__layer--base { background: rgb(214,229,100); } #group6 { z-index: 2; /* slide under group 5 and 7 */ } #group6 .parallax__layer--back { background: rgb(245,235,100); } #group7 { z-index: 3; /* slide over group 7 */ } #group7 .parallax__layer--base { background: rgb(255,241,100); } </style> </head> <body> <div class="parallax"> <div id="group1" class="parallax__group"> <div class="parallax__layer parallax__layer--base"> <div class="title">Base Layer</div> </div> </div> <div id="group2" class="parallax__group"> <div class="parallax__layer parallax__layer--base"> <div class="title">Base Layer</div> </div> <div class="parallax__layer parallax__layer--back"> <div class="title">Background Layer</div> </div> </div> <div id="group3" class="parallax__group"> <div class="parallax__layer parallax__layer--fore"> <div class="title">Foreground Layer</div> </div> <div class="parallax__layer parallax__layer--base"> <div class="title">Base Layer</div> </div> </div> <div id="group4" class="parallax__group"> <div class="parallax__layer parallax__layer--base"> <div class="title">Base Layer</div> </div> <div class="parallax__layer parallax__layer--back"> <div class="title">Background Layer</div> </div> <div class="parallax__layer parallax__layer--deep"> <div class="title">Deep Background Layer</div> </div> </div> <div id="group5" class="parallax__group"> <div class="parallax__layer parallax__layer--fore"> <div class="title">Foreground Layer</div> </div> <div class="parallax__layer parallax__layer--base"> <div class="title">Base Layer</div> </div> </div> <div id="group6" class="parallax__group"> <div class="parallax__layer parallax__layer--back"> <div class="title">Background Layer</div> </div> <div class="parallax__layer parallax__layer--base"> <div class="title">Base Layer</div> </div> </div> <div id="group7" class="parallax__group"> <div class="parallax__layer parallax__layer--base"> <div class="title">Base Layer</div> </div> </div> </div> </body> </html>