Hogyan készítsünk visszaszámlálót CSS-el? ShiwaForce Admin 2015. május 06

Hogyan készítsünk visszaszámlálót CSS-el?

Rengeteg preloader megoldás található a neten: generátorok, megírt kis kódok, gifek és egyebek. Viszont én mindenképpen olyan megoldást szerettem volna, ami natív CSS, lehetőleg javascript nélkül. Mivel a böngészők egyre fejlettebb CSS támogatással vannak felvértezve, gondoltam, használjuk ki ezeket. Hamar rá is bukkantam a megfelelőnek ígérkező megoldásra, és némi átírás és kibővítés után végül meg is született az alábbi kód.

A HTML markup végtelenül egyszerű, magyarázatra sem szorul:

<div class="countdown-wrap">
  <div class="countdown">
    <span class="numbers num1">1</span>
    <span class="numbers num2">2</span>
    <span class="numbers num3">3</span>
    <span class="side side-left">
      <span class="fill"></span>
    </span>
    <span class="side side-right">
      <span class="fill"></span>
    </span>
  </div>
</div>

Ez jelen esetben háromtól számol vissza, de ez elég könnyen módosítható.

A kódunkban így mutat a countdown-wrap div konténerünk, az alábbi néhány formázással:

.countdown-wrap {
  display: inline-block;
  margin: 0 10px;
  font-family: 'Arial';
  position: relative;
}

Ezt a div-et alapvetően el is hagyhatnánk, és a szükséges tulajdonságokat a countdown div-re ruházhatjuk át – nekem így tisztábbnak tűnt és könnyebben kezelhetőnek; módosíthatónak, bárhová beilleszthetőnek .

A countdown div-vel formázzuk hát meg a szürke hátterű kört és megadjuk egy animation-nel, hogy 3 másodperc után legyen láthatatlan. A “pörgettyűnk” 50×50 px méretet kapta:

.countdown-wrap .countdown {
  position: relative;
  border-radius: 100%;
  width: 50px;
  height: 50px;
  background: #eee;
  opacity: 0;
  animation-duration: 3s;
  animation-name: countdown-hide;
}

@keyframes countdown-hide {
  0% {opacity: 1;}
  99% {opacity: 1;}
  100% {opacity: 0;}
}

Készítünk egy after pszeudót a countdown div-nek, ami egy “fake mask” – egy fehér hátterű kör, ami kisebb a countdown div-nél, így kapjuk meg a 3 px vékony szürke kört. Ha nem fehér háttérre tesszük a “pörgettyűt”, akkor az itt lévő háttérszínt kell módosítanunk, hogy továbbra is maszknak tűnjön, már ha ez a cél.

Íme:

.countdown-wrap .countdown::after {
  content: "";
  background: #fff;
  position: absolute;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  top: 3px;
  left: 3px;
  display: block;
}

Ezt követően megformázzuk a számokat, hogy a megfelelő méretben, a megfelelő helyen és időben jelenjenek meg, majd tűnjenek el. A számokat abszolút pozícióval kell a bal felső sarokhoz igazítani ahhoz, hogy a kör közepén jelenjenek meg. Átlátszóságuk nulla, melyet majd az animáció módosít az 1 másodperces futásakor, elején és végén az idő 10%-a alatt, láthatóra, majd nem láthatóra. Azért, hogy a számok ne egyszerre jelenjenek meg, hanem egymás után, ahogyan egy visszaszámlálóhoz illik, megadunk nekik 0, 1 és 2 másodperces várakoztatást, hogy melyik szám mikor hívja meg az animációt. Így tehát a hármas szám, amivel kezdünk, nem várakozik;  kettes szám 1 másodperc után hívja az animációt, míg az egyes szám 2 másodpercet várakozik az animáció hívása előtt.

.countdown-wrap .countdown .numbers {
  position: absolute;
  left: 15px;
  top: 5px;
  color: #555;
  font-size: 36px;
  font-weight: bold;
  z-index: 100;
  opacity: 0;
  animation-duration: 1s;
  animation-name: num-show-hide;
}

@keyframes num-show-hide {
  0% {opacity: 0;}
  10% {opacity: 1;}
  90% {opacity: 1;}
  100% {opacity: 0;}
}

.countdown-wrap .countdown .numbers.num1 {
  animation-delay: 2s;
}

.countdown-wrap .countdown .numbers.num2 {
  animation-delay: 1s;
}

.countdown-wrap .countdown .numbers.num3 {
  animation-delay: 0s;
}

A végére hagytam az igazán látványos részt, amikor a “pörgettyű” animációját alakítjuk ki.

A side div-ek mindketten egy 50% széles téglalapok, melyek balra és jobbra helyezkednek el egymás mellett, kitöltve így a countdown szülő elemet. Ezek maszkként funkcionálnak majd a fill div gyermek elemük számára.

.countdown-wrap .countdown .side {
  width: 50%;
  height: 100%;
  overflow: hidden;
  position: absolute;
}

.countdown-wrap .countdown .side-left {
  left: 0;
}

.countdown-wrap .countdown .side-right {
  right: 0;
}

A fill div-ek mindketten egy-egy félkört alkotnak, az ellenkező oldalon, mint a szülőelemük, így alapesetben nem láthatóak, hiszen pozíciójuk kívül helyezi őket a szülőelem által befoglalt területen.

.countdown-wrap .countdown .side .fill {
  border-radius: 50px;
  position: absolute;
  width: 100%;
  height: 100%;
  background: #bfbfbf; /* countdown color */
  animation-iteration-count: infinite;
  animation-timing-function: linear;
  animation-duration: 2s;
  animation-iteration-count: 2;
  opacity: 1;
}

.countdown-wrap .countdown .side-left .fill {
  left: 100%;
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  animation-name: countdown-rotate-left;
  transform-origin: 0 50%;
}

.countdown-wrap .countdown .side-right .fill {
  left: -100%;
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
  animation-name: countdown-rotate-right;
  transform-origin: 100% 50%;
}

Ezek az elemek 2 másodperc alatt fordulnak teljesen körbe, bevárva egymást minkét oldalon. Így a “pörgettyű” felváltva lesz kitöltött és nem kitöltött egy-egy másodpercre, azaz világosszürke (ez a countdown div háttérszine), és sötétszürke (ez a fill div-ek háttérszine).

A csík színe úgy változik, hogy az adott fill div elfordulásakor, vagy a szülőelemének pozíciójára fordul rá (ekkor lesz látható és kitölti a világos szürke csíkot a sötét szürke), vagy abból fordul ki (ekkor pedig a sötétszürke csíkból egyre kevesebb, végül semmi nem lesz látható).

@keyframes countdown-rotate-right {
  0% {transform: rotate(0deg);}
  25% {transform: rotate(180deg);}
  50% {transform: rotate(180deg);}
  75% {transform: rotate(360deg);}
  100% {transform: rotate(360deg);}
}

@keyframes countdown-rotate-left {
  0% {transform: rotate(0deg);}
  25% {transform: rotate(0deg);}
  50% {transform: rotate(180deg);}
  75% {transform: rotate(180deg);}
  100% {transform: rotate(360deg);}
}

A leírt kódokban nem használtam a prefix-eket (-webkit-, -moz-, stb.) a szükséges helyeken, ezeket mindenképpen érdemes elkészíteni hozzá, amennyiben ezt a megoldást választjuk.

A countdown nagyon jól működött, azonban végül az igény úgy módosult, hogy a visszaszámlálás időtartama dinamikusan módosítható legyen, így mégis befészkelte magát az eredménybe a javascript. Azonban ha fix másodpercre van szükség, akkor ez jó megoldás lehet bárki számára.

Végül a teljes kód JADE és LESS formátumban, és az eredmény.

See the Pen LEwEYZ by Gabor (@alecpen) on CodePen.