.
button {
border-bottom: 1px solid hsla(0, 0%, 100%, 0.2);
text-shadow: 0 1px 0 hsla(0, 0%, 0%, 0.2);
text-decoration: none !important;
text-transform: uppercase;
color: #fff !important;
font-weight: bold;
border-radius: 5px;
padding: 10px 20px;
margin: 0 3px;
position: relative;
display: inline-block;
-webkit-transition: all 0.1s;
-moz-transition: all 0.1s;
-o-transition: all 0.1s;
transition: all 0.1s;
}
.button:active {
-webkit-transform: translateY(7px);
-moz-transform: translateY(7px);
-o-transform: translateY(7px);
transform: translateY(7px);
}
.button-purple {
background: #ba54d3;
box-shadow: 0 10px 0 #8e29a7,
0 11px 5px hsla(0, 0%, 0%, 0.5);
}
.button-purple:active {
box-shadow: 0 3px 0 #8e29a7,
0 4px 6px hsla(0, 0%, 0%, 0.7);
}
.button-orange {
background: #ff9819;
box-shadow: 0 10px 0 #cc7000,
0 11px 5px hsla(0, 0%, 0%, 0.5);
}
.button-orange:active {
box-shadow: 0 3px 0 #cc7000,
0 4px 6px hsla(0, 0%, 0%, 0.7);
}
.button-green {
background: #589900;
box-shadow: 0 10px 0 #3a6600,
0 11px 5px hsla(0, 0%, 0%, 0.5);
}
.button-green:active {
box-shadow: 0 3px 0 #3a6600,
0 4px 6px hsla(0, 0%, 0%, 0.7);
}
.button-pink {
background: #FF1493;
box-shadow: 0 10px 0 #cc006e,
0 11px 5px hsla(0, 0%, 0%, 0.5);
}
.button-pink:active {
box-shadow: 0 3px 0 #cc006e,
0 4px 6px hsla(0, 0%, 0%, 0.7);
}
.button-blue {
background: #1E90FF;
box-shadow: 0 10px 0 #005ab2,
0 11px 5px hsla(0, 0%, 0%, 0.5);
}
.button-blue:active {
box-shadow: 0 3px 0 #005ab2,
0 4px 6px hsla(0, 0%, 0%, 0.7);
}
<h3 class="text-center">Botón 3D animado creado con CSS3</h3>
<div class="text-center">
<a href="javascript:void(0)" class="button button-orange">¡Haz click aquí!</a>
<a href="javascript:void(0)" class="button button-green">¡Haz click aquí!</a>
<a href="javascript:void(0)" class="button button-blue">¡Haz click aquí!</a>
</div>
9juego
codigo js
/*cuando termine de cargar se ejecute con el init o la funcion automaticamente
un escucha a la ventana*/
[Link]('load',init,false);
var canvas=null,ctx=null; //variables definidas en nulas para guardar el canvas y su contexto
//animacion declaramos 2 variables
//var x=50,y=50;
var player=new Rectangle(40,40,10,10);
var lastKey=null; //interaccion con usuario, var para tecla presionada
var dir=0; //variable para almacenar la dirección de nuestro rectángulo
var PAUSE=true; //poner el juego en pausa
var food=new Rectangle(80,80,10,10); //nuevo elemento, variable food
var score=0; //declaramos el puntaje
var GAMEOVER=true; //saber si perdio
var wall=new Array(); //contendrra los elementos de pared
[Link](new Rectangle(100,50,10,10));
[Link](new Rectangle(100,100,10,10));
[Link](new Rectangle(200,50,10,10));
[Link](new Rectangle(200,100,10,10));
//lugar random
function random(max){
return parseInt([Link]()*max);
}
function init(){
canvas=[Link]('canvas'); //buscamos por ID para desplegarlo
[Link]='#000'; //background en hexadecimal
ctx=[Link]('2d'); // el contexto 2D es nuestra herramienta para pintar dentro del lienzo
//paint(ctx); //llamamos a la funcion de paint
run(); //llamamos a la funcion run
}
//esta funcion permitira llamar a paint() una y otra vez
function run(){
/*llamamos a un temporizador, el cual volverá a llamar a “run” en 50 milisegundos
imprimiendo 20 cuadros por segundo*/
setTimeout(run,50);
game();
//x+=10; //aumento de la cordenada en x a 10
//if(x>[Link]) //si su posición es mayor a la del ancho de lienzo
//x=0; //regrese a la posición 0.
paint(ctx); //llamamos la funcion paint()
}
function reset(){
score=0;
dir=1;
player.x=40;
player.y=40;
food.x=random([Link]/10-1)*10;
food.y=random([Link]/10-1)*10;
GAMEOVER=false;
}
function game(){
if(!PAUSE){
// GameOver Reset
if(GAMEOVER)
reset();
/*las flechas con valores numericos*/
// Change Direction
if(lastKey==38)
dir=0;
if(lastKey==39)
dir=1;
if(lastKey==40)
dir=2;
if(lastKey==37)
dir=3;
//si no dejo el player se van solo x y
// Move Rect
if(dir==0)
player.y-=10;
if(dir==1)
player.x+=10;
if(dir==2)
player.y+=10;
if(dir==3)
player.x-=10;
// Out Screen
if(player.x>[Link])
player.x=0;
if(player.y>[Link])
player.y=0;
if(player.x<0)
player.x=[Link];
if(player.y<0)
player.y=[Link];
// Food Intersects
if([Link](food)){
score++;
food.x=random([Link]/10-1)*10;
food.y=random([Link]/10-1)*10;
}
// Wall Intersects
// comprobamos si hace una intersección con la comida o el jugador
for (i=0;i<[Link];i++){
if([Link](wall[i])){
food.x=random([Link]/10-1)*10;
food.y=random([Link]/10-1)*10;
}
if([Link](wall[i])){
GAMEOVER=true;
PAUSE=true;
}
}
}
// Pause/Unpause
if(lastKey==13){
PAUSE=!PAUSE;
lastKey=null;
}
}
function paint(ctx){
[Link](0,0,[Link],[Link]); //limpiamos la pantalla
[Link]='#0f0'; //color del rectangulo
//[Link](x,y,10,10); //posicion, ancho y largo
[Link](player.x,player.y,[Link],[Link]);
[Link]='#f00';
[Link](food.x,food.y,[Link],[Link]);
[Link]='#fff';
[Link]='#999';
for(i=0;i<[Link];i++){ //imprimir las paredes con un for
[Link](wall[i].x,wall[i].y,wall[i].width,wall[i].height);
}
//[Link]('Last Key: '+lastKey,0,20); //saber cual fue la ultima tecla
[Link]('Score: '+score,0,10);
//if(PAUSE) //imprimir la pausa
if(PAUSE){
[Link]='center';
if(GAMEOVER)
[Link]('GAME OVER',150,75);
else
[Link]('PAUSE',150,75);
[Link]='left';
}
//[Link]('PAUSE',140,75);
//puntaje en la pantalla
}
/*Mediante este método, podremos tomar decisiones en el juego sabiendo la última tecla
presionada.
Cada tecla tiene un valor numérico, el cual tendremos que comparar para realizar la acción deseada
dependiendo la tecla presionada. */
[Link]('keydown',function(evt){
lastKey=[Link];
},false);
//nos dirá si está en una intersección con un segundo elemento
// recibimos X, Y, Ancho y Alto
function Rectangle(x,y,width,height){
this.x=(x==null)?0:x;
this.y=(y==null)?0:y;
[Link]=(width==null)?0:width;
[Link]=(height==null)?[Link]:height;
[Link]=function(rect){
if(rect!=null){
return(this.x<rect.x+[Link]&&
this.x+[Link]>rect.x&&
this.y<rect.y+[Link]&&
this.y+[Link]>rect.y);
}
}
}
codigohtml
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<!--[if lte IE 8]><meta http-equiv="X-UA-Compatible" content="chrome=1" /><![endif]-->
<title>Juego Canvas | HTML5</title>
<!--se llama al script [Link] que contiene el juego-->
<script type="application/javascript" src="js/[Link]"></script>
</head>
<body>
<!--<h1>Juego con HTML5</h1>-->
<!--se imprime el juego en la pantalla-->
<p><canvas id="canvas" width="300" height="150" style="border:1px solid #000">
Canvas No es soportado por tu navegador.
</canvas></p>
</body>
</html>
10 juegoculebra
<h1>Nokia 3310 snake</h1>
<div class="muestraPuntaje"></div>
<div class="cuadrilla"></div>
<div class="boton">
<button class="superior">superior</button>
<button class="fondo">fondo</button>
<button class="izquierda">izquierda</button>
<button class="derecha">derecha</button>
</div>
<div class="popup">
<button class="juegaDeNuevo">Inténtelo de nuevo</button>
</div>
codigocss
body {
background: rgb(212, 211, 211);
}
.cuadrilla {
width: 200px;
height: 200px;
border: 1px solid red;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
}
.cuadrilla div {
width: 20px;
height: 20px;
/*border:1px black solid;
box-sizing:border-box*/
}
.serpiente {
background: blue;
}
.manzana {
background: yellow;
border-radius: 20px;
}
.popup {
background: rgb(32, 31, 31);
width: 100px;
height: 100px;
position: fixed;
top: 100px;
left: 100px;
display: flex;
justify-content: center;
align-items: center;
}
En CSS, la cuadrilla, que es el tablero del juego, tiene una dimensión establecida y un
display de flex. Esto permite que los contenidos (div) de esta cuadrilla estén alineados de
forma horizontal como si fuesen elementos en línea en lugar de la disposición normal de los
bloques.
La propiedad flex wrap mueve los divs hacia la próxima línea para que no traspasen la
dimensión del elemento padre establecida (cuadrilla).
Crearemos de forma dinámica los contenidos del tablero del juego desde JS pero podemos darle
anchura y altura desde CSS (con el .cuadrilla div). En el ejemplo, incluí comentarios para
ayudarte a ver los divs; por lo que, a medida que avancemos dejaremos el código sin comentarios.
Las clases serpiente y manzana nos muestran donde está la serpiente y el bonus en el juego,
mientras que la clase popup es un div fijo que alberga el botón juegaDeNuevo.
En este punto, obtendrás lo siguiente:
let cuadrilla = [Link](".cuadrilla")
let popup = [Link](".popup");
let juegaDeNuevo = [Link](".juegaDeNuevo");
let muestraPuntaje = [Link](".muestraPuntaje")
let izquierda = [Link](".izquierda")
let fondo = [Link](".fondo")
let derecha = [Link](".derecha")
let arriba = [Link](".superior")
let ancho = 10;
let indiceActual = 0
let indiceManzana = 0
let serpienteActual = [2,1,0]
let direccion = 1
let puntaje = 0
let velocidad = 0.8
let tiempoInterval = 0
let interval = 0
La variable ancho es la anchura de la cuadrilla (10). Las otras variables tendrán más sentidos a
medida que avancemos. Sin embargo, aunque no lo creas, nuestra serpiente en realidad es un
arreglo llamado serpienteActual.
Ahora veamos las funciones:
[Link]("DOMContentLoaded",function(){
[Link]("keyup",control)
crearTablero()
comiezaJuego()
[Link]("click", repeticion);
})
Hay un eventListener en el objeto del documento llamado DomContentLoaded y este
evento se ejecutará una vez que el contenido del HTML se cargue en la pantalla.
Una vez que esto sucede, establecemos un eventListener en el documento para esperar clics
del [Link], queremos crear el juego de mesa, empezar el juego y prestarle atención a los
clics en el botón de juegaDeNuevo.
Función crearTablero
function crearTablero(){
[Link] = "none";
for(let i=0;i<100;i++){
let div = [Link]("div")
[Link](div)
}
}
Como mencioné antes, este es un cuadrilla de 10 por 10 por lo cual vamos a necesitar 100 divs.
Entonces, co el fragmento anterior, cerramos el div popup, creamos un nuevo div con un bucle de
100 iteraciones y insertamos a la cuadrilla (juego de meza).
Inmediatamente se añadirán algunos de los estilos creados en un principio (el .cuadrilla div). Puedes
remover los /* */del estilo CSS y observarás los divs creados (vuelve agregar los /* */).
Función comenzaJuego
function comenzaJuego(){
let cuadrados = [Link](".cuadrilla div")
manzanaAlAzar(cuadrados)
// manzana al azar
direccion = 1
[Link] = puntaje
tiempoInterval = 1000
serpienteActual = [2,1,0]
indiceActual = 0
[Link](index => cuadrados[index].[Link]("serpiente"))
interval = setInterval(moverResultado,tiempoInterval)
}
La función comenzaJuego primero toma todos los divs (ya que estamos creando los divs en el
tiempo de ejecución, no podemos incluirlos en la parte superior del código).
El siguiente paso es seleccionar un lugar dónde ubicar la manzana. Esto se realizará más abajo
dentro de la función manzanaAlAzar. La variable direccion se refiere hacia donde se dirige
la serpiente -1 para la derecha, -1 para la izquierda y así.
Con tiempoInterval se establece el tiempo que le toma a la serpiente moverse, mientras que
serpienteActual define la ubicación exacta de la serpiente en el cuadrilla (ten en cuenta que
básicamente la serpiente está formada por un par de divs con un color particular).
Para mostrar a nuestra serpiente en la pantalla, realizaremos bucles sobre el
arregloserpienteActual con un forEach. Cada valor obtenido, se utilizará con
cuadrados. Recuerda que debes utilizar querySelectorAll para acceder a los cuadrilla divs
y, después, podemos tener acceso a ellos como un arreglo que está utilizando números. En este caso,
estos son los valores de serpienteActual.
El siguiente paso insertar el método setInterval (moverResultado, tiempoInterval) en la
variable interval. Con esto podemos llamar fácilmente a clearInterval en esa variable.
moverResultado se ejecuta cada 1000ms (1s) y básicamente define qué sucede cuando mueves
la serpiente.
Función moverResultado
function moverResultado() {
let cuadrados = [Link](".cuadrilla div")
if(compruebaPorGolpes(squares)) {
alert("golpeaste algo")
[Link]="flex"
return clearInterval(interval)
} else {
mueveSerpiente(cuadrados)
}
}
Como con la función comenzaJuego mencionada previamente, primero obtenemos todos los
cuadrilla divs y luego verificamos si la función compruebaPorGolpes devuelve true
(verdadero).
Si lo hace, quiere decir que la serpiente se chocó con algo y aparece el botón "Inténtelo de nuevo" y
borra el interval. Si la función devuelve false (falso), la serpiente no chocó con nada y podemos
mover la serpiente con la función mueveSerpiente.
Por lo tanto, cada 1 segundo el juego termina si compruebaPorGolpes es true o la serpiente
realiza un movimiento más si compruebaPorGolpes es false. Primero explicaré la función
mueveSerpiente.
Función mueveSerpiente
function mueveSerpiente(cuadrados){
let cola = [Link]()
cuadrados[cola].[Link]("serpiente")
[Link](serpienteActual[0]+direccion)
// movimiento termina aquí
comeManzanas(cuadrados,cola)
cuadrados[serpienteActual[0]].[Link]("serpiente")
}
La función mueveSerpiente recibe un argumento llamado cuadrados lo que no es necesario
obtener de nuevo el .cuadrilla div en esta función.
Lo primeo que necesitamos hacer es quitar el último elemento del arreglo serpienteActual
con un pop (este sería la cola y el primer elemento del arreglo sería la cabeza). Básicamente, la
serpiente se mueve un paso hacia adelante y sale de la posición en la que estaba anteriormente.
Después de esto, insertamos un nuevo valor al principio del arreglo con unShift.
Supongamos que nuestra serpiente empezó a moverse y se dirige hacia la derecha (direccion = 1).
La dirección se añadirá a cabeza serpienteActual y la suma se colocará como el nuevo
cabezaDeSerpiente.
Por ejemplo, si la serpiente estaba en posición [2,1,0], eliminamos el último elemento y dejamos la
posición [2,1]. Luego, tomamos la cabeza que sería el elemento 2, le añadimos la dirección que es
el elemento 1 y hacemos que este valor sea el nuevo valor [3,2,1] que mueve nuestra serpiente un
paso hacia a la derecha después de un segundo.
Si queremos mover la serpiente hacia abajo, la dirección se establecerá a el ancho (que es 10) y se
insertará en el primer elemento (que es 12 y se pondrá al principio del arreglo) [12,2,1].
Después, verificamos si la serpiente se comió la manzana y si se visualiza la nueva cabeza de la
serpiente en el DOM.
Función compruebaPorGolpes
function compruebaPorGolpes(cuadrados) {
if (
(serpienteActual[0] + ancho >=(ancho * ancho) && direccion === ancho) ||
(serpienteActual[0] % ancho === ancho -1 && direccion ===1) ||
(serpienteActual[0] % ancho === 0 && direccion === -1) ||
(serpienteActual[0] - ancho <= 0 && direccion === -ancho) ||
cuadrados[serpienteActual[0] + direccion].[Link]("serpiente")
) {
return true
} else {
return false
}
}
La función compruebaPorGolpes tiene una sentencia if. Según la condición definida, podría
devolver true (la serpiente se chocó con algo) o false.
La primera condición es si serpienteActual [0] (la cabeza de la serpiente) + ancho (10) es igual al
total del área del ancho (que es ancho * ancho = 100) y la dirección es igual al ancho.
Ahora asumamos que la cabeza de la serpiente está en posición 97 que es la última capa de nuestro
cuadrilla. Si añadieses 10 a 97 (= 107), superaría al total de la cuadrilla que es de 100. Si la
dirección de la serpiente continúa hacia abajo, quiere decir que la serpiente se chocó con el borde
inferior.
Si la serpiente estaba en 97 (97 + 10= 107) pero el jugador pudo cambiar la dirección a 1 (tocando
la tecla izquierda), no se chocará con nada.
Si la cabeza de la serpiente está en posición 39 y la dirección todavía es 1 (la serpiente sigue
dirigiéndose hacia la pared) y se chocará con el borde derecho.
Cualquier otra condición es prácticamente lo contrario de las dos condiciones anteriores. La última
condición permite que si la cabeza de la serpiente se dirige hacia otro elemento que ya contiene la
clase serpiente, la serpiente se chocará con sí misma.
Por lo que si una de las condiciones mencionadas previamente se cumple, significa que la serpiente
se chocó con algo y se devolverá true (sino false). Y en ese caso, el juego se terminó. Pero si es
falso, con mueveSerpiente mueves la serpiente realiza otro movimiento.
Function comeManzanas
function comeManzanas(cuadrados,cola){
if(cuadrados[serpienteActual[0]].[Link]("manzanas")){
cuadrados[serpienteActual[0]].[Link]("manzanas")
cuadrados[cola].[Link]("serpiente")
[Link](cola)
manzanaAlAzar(cuadrados)
puntaje++
[Link] = puntaje
clearInterval(interval)
tiempoInterval = tiempoInterval * velocidad
interval = setInterval(moverResultado, tiempoInterval)
}
}
A la función comeManzana se la llama desde la función mueveSerpiente cada vez que la
serpiente realiza un movimiento.
Recibe dos argumentos cuadrados, .cuadrilla div y cola, básicamente es el valor que
apareció de la serpiente en moverResultado. Luego verifica si la próxima posición del
movimiento de la serpiente contiene una manzana.
Si lo hace, simplemente añade la cola que sacamos devuelta al arreglo. Esto sucede porque cada vez
que nuestra serpiente se come una manzana, su largo incrementa un valor.
Después solo tenemos que seleccionar una nueva posición para nuestra manzana con
manzanaAlAzar (ver más adelante). Y insertamos un valor de uno a nuestra puntuación, se lo
mostramos al usuario, y borramos el tiempoInterval (para poder incrementar la velocidad de
la serpiente). Por último, establecemos el intervalo de nuevo.
Función manzanaAlAzar
function manzanaAlAzar(cuadrados){
do {
appleIndex = [Link]([Link]() * [Link])
} while(cuadrados[appleIndex].[Link]("serpiente"))
cuadrados[appleIndex].[Link]("manzana")
}
Lo que hace manzanaAlAzar es seleccionar un lugar donde ubicar a nuestra manzana al utilizar
un bucle do while. Primero selecciona una posición al azar con [Link]() en el bucle do y
verifica si el lugar seleccionado ya contiene la clase serpiente.
Esto quiere decir que la condición en la sentencia do se ejecutará hasta que encuentre un lugar en el
que no esté la serpiente (esto se continua ejecutando hasta que sea true). Una vez que encuentre un
lugar, le da a ese lugar la clase manzana.
Establecer controles
Vamos a empezar con los usuarios del teclado.
function control(e){
if ([Link] === 39){
direccion = 1 // derecha
} else if ([Link] === 38){
direccion = -ancho // si presionamos la flecha de arriba, la serpiente
irá 10 divs hacia arriba
}else if ([Link] === 37){
direccion = -1 // izquierda, la serpiente irá un div a la izquierda
}else if ([Link] === 40){
direccion = +ancho // la serpiente irá 10 divs hacia abajo desde el div
actual
}
}
Recuerda que establecimos un eventListener para keyup. Esta función se ejecuta inmediatamente al
presionar y soltar una tecla.
Ahora cada botón del teclado tiene un valor llamado keycode (numeros) desde el cual tenemos
acceso y nos permite saber qué numero se cliqueó. Básicamente, estaremos atentos a las flechas con
sus respectivos valores (keycodes). Gracias a esto, cambiamos la dirección, por ejemplo -1, 10 y así.
Espero que hayan comprendido cómo ahora se podrá mover a la serpiente.
El siguiente conjunto de botones es para dispositivos móviles y básicamente estamos haciendo lo
mismo:
[Link]("click",() => direccion = -ancho )
[Link]("click",() => direccion = +ancho )
[Link]("click",() => direccion = -1 )
[Link]("click",() => direccion = 1 )
Por último, necesitamos crear el div repetición que aparecerá cuando la serpiente se choque con
algo. Con este botón, podremos borrar el juego.
Función repetición
function repetición() {
[Link]=""
crearTablero()
comiezaJuego()
[Link] = "none";
}
Con este fragmento, borramos la cuadrilla (juego de mesa) y ejecutamos las funciones previas.
11taedro
<body>
<h2>Tetraedro 3D con puro HTML5 y CSS3</h2>
<div class="espacio3D">
<div class="cubo3D">
<div class="base"></div> <!--sombra-->
<aside class="triangulo cara2"></aside>
<aside class="triangulo cara3"></aside>
<aside class="triangulo cara4"></aside>
</div><!-- termina cubo 3d -->
</div><!-- termina espacio 3d -->
</body>
codigo css
h2{
text-align:center;
color:#666;
font-family:Helvetica;
}
div.espacio3D {
width: 200px;
height: 200px;
margin: 5em auto 0 auto;
/*border: 1px solid rgba(0,255,0,0.5);*/
position: relative;
perspective-origin: center -50%; /*punto desde donde se coloca la cámara*/
perspective: 500px; /*area de distorsion de figura*/
transform: scale(0.90); /* tamaño de cubo */
}
div.cubo3D {
width: 100%;
height: 100%;
position: absolute;
transform-style: preserve-3d;/* indica la perspectiva*/
transform: translateZ(-10px);
animation-name: gira;
animation-duration: 3000ms;
animation-iteration-count: infinite;
}
[Link] {
width: 0;
height: 0;
position: absolute;
}
aside.cara2 { /* centro */
transform: rotateY(120deg) translateZ(0px) translateY(0px) rotateX(35deg);
border-right: 150px solid transparent;
border-top: 150px solid transparent;
border-left: 150px solid transparent;
border-bottom: 150px solid rgba(15,115,145,0.45);
}
aside.cara3 { /* Izquierda */
transform: rotateY(-120deg) translateZ(0px) translateY(0px) rotateX(35deg);
border-right: 150px solid transparent;
border-top: 150px solid transparent;
border-left: 150px solid transparent;
border-bottom: 150px solid rgba(96,16,142,0.45);
}
aside.cara4 { /* derecha */
transform: rotateY(0deg) translateZ(0px) translateY(0px) rotateX(35deg);
border-right: 150px solid transparent;
border-top: 150px solid transparent;
border-left: 150px solid transparent;
border-bottom: 150px solid rgba(226,207,32,0.45);
}
@keyframes gira {
0% {
transform: translateZ(-100px) rotateY(0deg);
}
100% {
transform: translateZ(-100px) rotateY(360deg);
}
}
neon texto
neonText {
color: #fff;
text-shadow:
0 0 7px #fff,
0 0 10px #fff,
0 0 21px #fff,
0 0 42px #0fa,
0 0 82px #0fa,
0 0 92px #0fa,
0 0 102px #0fa,
0 0 151px #0fa;
}
h1 {
font-size: 4.2rem;
animation: flicker 1.5s infinite alternate;
}
/* Flickering animation */
@keyframes flicker {
0%, 18%, 22%, 25%, 53%, 57%, 100% {
text-shadow:
0 0 4px #fff,
0 0 11px #fff,
0 0 19px #fff,
0 0 40px #0fa,
0 0 80px #0fa,
0 0 90px #0fa,
0 0 100px #0fa,
0 0 150px #0fa;
20%, 24%, 55% {
text-shadow: none;
}
}
/* Additional styling */
h2 {
font-size: 1.8rem;
}
.container {
margin-top: 20vh;
}
body {
font-size: 18px;
font-family: "Helvetica Neue", sans-serif;
background-color: #010a01;
}
h1, h2 {
text-align: center;
text-transform: uppercase;
font-weight: 400;
}
Codigo html
<div class="container">
<h1 class="neonText">
404
</h1>
<h2 class="neonText">Page Not Found</h2>
</div>