Ako vytvoriť parallax efekt web stránky v CSS

paralax-2

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>