box-shadow (tanto exterior como interior) para lograr efectos de relieve y profundidad de forma sencilla pero efectiva.El diseño web moderno no solo se trata de estructuras estáticas; las pequeñas animaciones y detalles visuales, como este experimento de una luna con cráteres y fases, añaden una capa de interacción que mejora la experiencia del usuario. A continuación, veremos cómo lograr este efecto paso a paso.
Construyendo nuestra Luna en tres pasos
1. La estructura base y el halo lunar
Todo comienza con un simple div circular. Para darle ese aspecto "brillante", utilizaremos la propiedad box-shadow. En lugar de un color sólido, aplicaremos una animación de pulsación que emula el resplandor natural de la luna en una noche despejada.
He modernizado el posicionamiento utilizando left: 50% y transform para asegurar que la luna esté siempre centrada independientemente del tamaño del contenedor:
#moon {
position: absolute;
top: 15%;
left: 50%;
transform: translateX(-50%);
width: 200px;
height: 200px;
border-radius: 50%;
background: #CCC;
box-shadow: 0 0 100px #FFFF8C;
z-index: 5;
animation: moonPulse 3s infinite ease-in-out;
}
@keyframes moonPulse {
0%, 100% { box-shadow: 0 0 80px #FFF; }
50% { box-shadow: 0 0 120px #FFF; }
}2. Cráteres y profundidad con Box-Shadow Inset
Para los cráteres, el secreto está en la propiedad box-shadow: inset. Esto crea una sombra interna que da la sensación de hundimiento sin necesidad de imágenes o SVG complejos. Además, añadimos una capa superior para simular las fases lunares mediante sombras.
#moonFase {
position: absolute;
top: 15%;
left: 50%;
transform: translateX(-50%);
width: 200px;
height: 200px;
border-radius: 50%;
background: rgba(153, 153, 153, 0);
/* Sombra interna para efecto de fase */
box-shadow: inset -25px 0px 0 0px #999;
z-index: 6;
animation: moonFaseAnimation 600s infinite linear;
}
.crater {
position: absolute;
background: #555;
box-shadow: inset 3px -2px 0 0px #414043;
z-index: 7;
border-radius: 50%;
}Tip de SEO y Rendimiento: Al usar CSS puro en lugar de imágenes pesadas, reducimos el tiempo de carga de la página, un factor clave para el posicionamiento en Google.
3. Fondo estrellado dinámico con JavaScript Moderno
Posicionar 250 estrellas manualmente sería ineficiente. Por ello, utilizamos un pequeño script que genera las estrellas en posiciones aleatorias. He actualizado el código original a ES6 utilizando const y DocumentFragment para minimizar los "reflows" del navegador, mejorando el rendimiento.
const generateStars = () => {
const w = window.innerWidth;
const h = window.innerHeight;
const fragment = document.createDocumentFragment();
for (let i = 0; i < 250; i++) {
const star = document.createElement("div");
star.className = "star";
// Posicionamiento aleatorio
const x = Math.floor(Math.random() * w);
const y = Math.floor(Math.random() * h);
star.style.bottom = `${y}px`;
star.style.right = `${x}px`;
fragment.appendChild(star);
}
document.body.appendChild(fragment);
};
generateStars();El estilo de las estrellas sigue siendo minimalista, pero con un ligero resplandor para que parezcan titilar:
.star {
width: 2px;
height: 2px;
border-radius: 50%;
background: #FFF;
box-shadow: 0 0 2px 1px rgba(255, 255, 255, 0.8);
position: absolute;
}Llevándolo más allá: Personalización
Este experimento es la base perfecta para practicar. Puedes intentar cambiar el color de la luna por un tono rojizo para un "eclipse lunar", o modificar la velocidad de la animación de las fases. Si quieres profundizar en el mundo de las animaciones, te recomiendo leer mi artículo sobre cómo dar tus primeros pasos con animaciones en CSS.
¿Te ha gustado este tutorial? No olvides revisar también cómo resaltar contenido de manera animada con CSS para seguir mejorando tus habilidades de diseño web.