Cómo construir un spinner de carga inspirado en Reddit con solo HTML y CSS

La aplicación móvil de Reddit tiene una ruleta de carga bastante llamativa que recuerda a los cuerpos orbitales que rodean un planeta o una estrella. La mayoría de los desarrolladores usarían JavaScript o SVG para una tarea como esta, pero gracias aanimation-iteration-count: infinite;y algunos otros trucos y trucos, eso ni siquiera es necesario. ¡Hoy les mostraré cómo codificar un spinner inspirado en Reddit puramente en HTML y CSS!

Aquí está el resultado final:

Configuración básica

Comencemos escribiendo algunos elementos DOM HTML en los que podemos fijar el círculo central y cada uno de los orbitales giratorios.

 ... ... 

Los elementos inner-spiny outer-spinserán los nodos padres de todo lo que necesita ser animado y, finalmente, aplicaremos las transformaciones de fotogramas clave CSS a estos nodos principales.

En el ejemplo de código anterior, las elipses ( ) representan los arcos y las "lunas" en órbita. Tanto el anillo interior como el exterior contienen dos arcos y dos lunas, pero por razones que se aclararán un poco más adelante, cada arco en realidad está compuesto por dos formas CSS, por lo que necesitamos un total de ocho arcos y cuatro lunas. El HTML en su totalidad se ve así:

Formas CSS

Es posible dibujar círculos y arcos en CSS simplemente creando un cuadrado y estableciendo el border-radius50%.

Cada lado del borde puede tomar un color diferente o se puede configurar transparent. La background-colorpropiedad establece el relleno de la forma, si lo hay.

Es fácil dibujar arcos de 90, 180 y 270 grados simplemente configurando uno o más lados del borde para que sean transparentes. Sin embargo, si miras de cerca la ruleta en la parte superior de la página, notarás que la “cola” de cada orbital deja un espacio entre él y la luna detrás de él. Eso significa que, aunque las longitudes de arco están cerca de los 180 grados, son un poco tímidas a los 180.

Dibujar segmentos circulares de longitudes irregulares en CSS requiere un poco de truco. Para hacer esto, necesitamos dibujar dos segmentos de arco adyacentes de 90 grados y rotar uno ligeramente para que se superpongan, dejando un segmento de arco aparente de aproximadamente 160 grados.

Mirando hacia atrás en el HTML ahora, ahora puede adivinar por qué hemos establecido dos nodos para cada arco (un arc_starty arc_end). Estos se utilizarán para representar cada parte de un solo arco superpuesto que representa la cola de cada orbital.

Configurar el CSS

Para empezar, estableceremos una variable CSS para representar el color de la ruleta y otra variable para representar una traducción de -50%, -50% que usaremos en todo el CSS para centrar las formas alrededor de su centro (en oposición a su esquina superior izquierda, que es la predeterminada).

html { --spinner: #1EAAF0; --center: translate(-50%, -50%); }

Ahora podemos seguir adelante y dibujar también el círculo central.

.center { position: absolute; width: 30px; height: 30px; background: var(--spinner); border-radius: 50%; top: 50%; left: 50%; transform: var(--center); }

Los nodos secundarios de cada orbital se incluyen dentro de los nodos principales llamados inner-spiny outer-spin. Por ahora solo los usaremos para centrar la ruleta dentro de la ventana.

.outer-spin, .inner-spin { position: absolute; top: 50%; left: 50%; }

Dibujar los orbitales

La ruleta de carga es básicamente una serie de círculos concéntricos, así que centrémonos primero en dibujar un solo arco.

Dado que cada arco consta de dos secciones superpuestas, comencemos dibujando dos arcos uno al lado del otro.

.inner-arc { width: 62px; height: 62px; } .inner-arc_start-a { border-color: transparent transparent transparent green; /* NOTE: the order here very much matters! */ transform: var(--center) rotate(0deg); } .inner-arc_end-a { border-color: red transparent transparent transparent; transform: var(--center) rotate(0deg); }

La primera transformación centra el en la ventana. La rotación se establece en cero grados para mostrar el estado predeterminado de los arcos.

Observe que los arcos no se alinean con los cruces x en el círculo unitario. Para corregir esto y facilitar el trabajo con los arcos, rotamos los arcos 45 grados. Luego giramos ligeramente uno de los arcos para crear una longitud de arco total de aproximadamente 160 grados.

.inner-arc_start-a { border-color: transparent transparent transparent green; transform: var(--center) rotate(65deg); } .inner-arc_end-a { border-color: red transparent transparent transparent; transform: var(--center) rotate(45deg); }

A continuación, podemos posicionar una de las lunas orbitales moviéndola a lo largo del eje x. Desafortunadamente, a diferencia de los gráficos vectoriales como los SVG, los bordes CSS no son vectores sin ancho que aceptan un estilo de trazo. Eso significa que las distancias no se miden automáticamente al punto central de la línea. Debemos tener en cuenta el ancho del borde a la hora de posicionar objetos.

Esto da como resultado algunos "números mágicos" que probablemente podríamos minimizar si quisiéramos establecer más variables CSS y usar la calc()función. Sin embargo, eso parece un poco complicado, así que por ahora posicionaré el círculo por valor de píxel.

.inner-moon-a { position: absolute; top:50%; left:50%; width: 12px; height: 12px; background: red; border-radius: 50%; transform: var(--center) translate(33px, 0); }

A continuación, dibujamos dos arcos más, pero esta vez usamos la scale(-1, -1)transformación. Esto invierte los arcos a través de los ejes x e y, esencialmente reflejando la estela.

.inner-arc_start-b { border-color: transparent transparent transparent var(--spinner); transform: var(--center) rotate(65deg) scale(-1, -1); } .inner-arc_end-b { border-color: var(--spinner) transparent transparent transparent; transform: var(--center) rotate(45deg) scale(-1, -1);

Finalmente, para la órbita exterior, simplemente repetimos el CSS desde la órbita interior, ¡pero establecemos una altura y un ancho mayores ! (¡Imagínese lo corto que podría ser este CSS con los mixins de SASS!)

.outer-arc { width: 100px; height: 100px; }

Agregar la animación

El último paso es agregar animación. Primero necesitamos agregar un único elemento de fotogramas clave que establezca el tipo de comportamiento de la animación y los elementos CSS afectados por la animación, en este caso la rotación a través de una transformpropiedad.

@keyframes spin { 100% {transform: rotate(360deg); } }

El identificador “ spin” conecta los fotogramas clave de nuevo a los atributos de animación que agregaremos dentro de cada elemento principal . La propiedad de animación establece la información temporal para la animación, lo que significa que cada orbital orbitará a una velocidad diferente.

.outer-spin { animation: spin 4s linear infinite; } .inner-spin { animation: spin 3s linear infinite; }

¡Eso es!

The code for this tutorial can be found on CodePen.io. Please comment — or Tweet at me @PleathrStarfish — if you have a suggestion, observation, or a cool fork of my code!