Com Funciona

L'algoritme de foc està inspirat en How DOOM fire was done de Fabien Sanglard. L'excel·lent explicació de Fabien va ser tan útil que em va inspirar a intentar explicar com funciona la meva implementació.

CSS pur

És habitual que animacions com aquestes incloguin elements HTML. Normalment són elements <div> que animarà el CSS.

Aquest no té res d'això, que és el que vull dir quan l'anomeno una implementació "pura CSS". No hi ha HTML excepte el mínim necessari per lliurar el CSS d'una manera vàlida. Així, tota l'animació s'executa amb un pseudoelement de l'element <body>.

Un quadrat, un fotograma

Necessitem un quadrat negre estàtic com a punt de partida.

body::after {
 background: black;
 content: "";
 position: absolute;
 width: 128px;
 height: 128px;
}
Quadrat blanc amb un quadrat negre a la part superior esquerra.
El quadrat negre és el pseudoelement ::after.

Dos quadrats, un fotograma

El següent pas és convertir aquest quadrat en una pantalla bidimensional mitjançant box-shadow. En la majoria del desenvolupament web quotidià, aquestes box-shadow són borroses i enfosquides per l'element al qual pertanyen. Per utilitzar-los per a això, hi ha tres regles:

  1. Amagar l'element en si: sense background-color.
  2. Col·locar-los completament fora de l'element.
  3. Sense desenfocament.

Aquí tens un exemple actualitzat amb això.

body::after {
 content: "";
 position: absolute;
 width: 128px;
 height: 128px;
 box-shadow:
  128px calc(128px*0) yellow,
  128px calc(128px*1) red;
}
Quadre blanc amb un quadrat groc a la part superior dreta i un de vermell a la part inferior dreta.
El quadrat groc el dibuixa el primer <box-shadow> i el quadrat vermell el dibuixa el segon.

Dos quadrats, tres fotogramas

Augmentar la resolució és qüestió d'afegir més <box-shadow> a la llista. I fer-los actualitzar per semblar un incendi és una animació keyframe.

@keyframes fire {
 33% {
  box-shadow:
   128px calc(128px*0) white,
   128px calc(128px*1) white;
 }
 66% {
  box-shadow:
   128px calc(128px*0) white,
   128px calc(128px*1) red;
 }
 99% {
  box-shadow:
   128px calc(128px*0) yellow,
   128px calc(128px*1) red;
 }
}
Animació en la qual apareixen i desapareixen repetidament el quadrat groc i vermell.
Ara comença a semblar un foc.

Compensacions de rendiment

Un dels inconvenients d'aquesta tècnica és la ineficient que és. Les animacions de <box-shadow> no són eficients.

I cada píxel de cada fotograma de l'animació s'ha de declarar explícitament, cosa que utilitza una gran quantitat d'amplada de banda. Aquesta animació de 16 segons és de 3,5 megabytes de CSS! En lloc de tallar-lo bruscament després de 16 segons, l'he fet circular infinitament. Això vol dir que falta la part del principi on el foc s'estén des de la part inferior.

Tanmateix, no tot són desavantatges. La implementació original sembla molt pixelada. El motiu per la qual aquesta versió s'assembla més a flames reals és gràcies a CSS. L'ús d'un pseudoelement llarg i prim en lloc d'un quadrat estira les flames molt bé. El filtre de desenfocament afegeix el toc final.