This one uses no images. Just good old CSS sleight-of-hand. For the animation, we'll use jQuery UI. Is it absolutely necessary? No, but I feel like it.
The starting HTML looks like this. We have a div, id container. Below it, we'll have a h1 tag. All divs are set to have red outlines. Trust me, we'll need it.
<!DOCTYPE html>
<html>
<head>
<title>Easter 2026</title>
<style>
div
{
border: 1px solid rgb(255, 0, 0);
}
</style>
<script src="https://code.jquery.com/jquery-3.7.1.js"></script>
<script src="https://code.jquery.com/ui/1.13.3/jquery-ui.js"></script>
<script>
</script>
</head>
<body>
<div id="container">
</div>
<h1>HAPPY EASTER</h1>
</body>
</html>
<html>
<head>
<title>Easter 2026</title>
<style>
div
{
border: 1px solid rgb(255, 0, 0);
}
</style>
<script src="https://code.jquery.com/jquery-3.7.1.js"></script>
<script src="https://code.jquery.com/ui/1.13.3/jquery-ui.js"></script>
<script>
</script>
</head>
<body>
<div id="container">
</div>
<h1>HAPPY EASTER</h1>
</body>
</html>
Here, we define h1 with some aesthetics. container is set to a small size, centered in the screen via use of margin properties. Round corners and all, because it's cute. I also gave it a thick orange border.
<!DOCTYPE html>
<html>
<head>
<title>Easter 2026</title>
<style>
div
{
border: 1px solid rgb(255, 0, 0);
}
h1
{
font-family: verdana;
text-align: center;
color: rgb(255, 200, 0);
}
#container
{
margin: 100px auto 0 auto;
border-radius: 50px;
border: 5px solid rgb(255, 200, 0);
<html>
<head>
<title>Easter 2026</title>
<style>
div
{
border: 1px solid rgb(255, 0, 0);
}
h1
{
font-family: verdana;
text-align: center;
color: rgb(255, 200, 0);
}
#container
{
margin: 100px auto 0 auto;
border-radius: 50px;
border: 5px solid rgb(255, 200, 0);
width: 300px;
height: 200px;
height: 200px;
}
</style>
<script src="https://code.jquery.com/jquery-3.7.1.js"></script>
<script src="https://code.jquery.com/ui/1.13.3/jquery-ui.js"></script>
<script>
</script>
</head>
<body>
<div id="container">
</div>
<h1>HAPPY EASTER</h1>
</body>
</html>
</style>
<script src="https://code.jquery.com/jquery-3.7.1.js"></script>
<script src="https://code.jquery.com/ui/1.13.3/jquery-ui.js"></script>
<script>
</script>
</head>
<body>
<div id="container">
</div>
<h1>HAPPY EASTER</h1>
</body>
</html>
In container, we have two divs - ids aura and hills.
<div id="container">
<div id="aura">
</div>
<div id="hills">
</div>
</div>
<div id="aura">
</div>
<div id="hills">
</div>
</div>
In hills, we have five other divs. The first three are styled using the CSS class hill. The fourth and fifth have the ids cross and shadow. They contain the HTML crucfix symbol.
<div id="container">
<div id="aura" class="unrotated">
</div>
<div id="hills">
<div class="hill"></div>
<div id="aura" class="unrotated">
</div>
<div id="hills">
<div class="hill"></div>
<div class="hill"></div>
<div class="hill"></div>
<div id="cross">✝</div>
<div id="shadow">✝</div>
</div>
</div>
</div>
Here's some styling. We want aura to overlap the entirety of container. I've made it bigger than container's width and height, offset the margins accordingly, and turned it into a circle using the border-radius property. This isn't strictly necessary, but we're going to rotate it later, and it's easier to gauge if aura will still cover container that way. As for hills, we want it to cover container's full width but only the bottom half. So I've set the margin-top property accordingly. I've set position to relative and z-index to a positive number to ensure that hills always stays on top of aura in that order. This will be very relevant later.
<style>
div
{
border: 1px solid rgb(255, 0, 0);
}
h1
{
font-family: verdana;
text-align: center;
color: rgb(255, 200, 0);
}
#container
{
margin: 100px auto 0 auto;
border-radius: 50px;
border: 5px solid rgb(255, 200, 0);
width: 300px;
height: 200px;
}
#aura
{
width: 400px;
height: 400px;
margin-top: -100px;
margin-left: -50px;
border-radius: 50%;
}
#hills
{
width: 300px;
height: 100px;
margin-top: -120px;
position: relative;
z-index: 2;
}
</style>
div
{
border: 1px solid rgb(255, 0, 0);
}
h1
{
font-family: verdana;
text-align: center;
color: rgb(255, 200, 0);
}
#container
{
margin: 100px auto 0 auto;
border-radius: 50px;
border: 5px solid rgb(255, 200, 0);
width: 300px;
height: 200px;
}
#aura
{
width: 400px;
height: 400px;
margin-top: -100px;
margin-left: -50px;
border-radius: 50%;
}
#hills
{
width: 300px;
height: 100px;
margin-top: -120px;
position: relative;
z-index: 2;
}
</style>
So far, it's all here.
Now, what happens if we style hill this way? All black 150 pixel squares with rounded corners, and rotated 45 degrees.
#hills
{
width: 300px;
height: 100px;
margin-top: -120px;
position: relative;
z-index: 2;
}
.hill
{
width: 150px;
height: 150px;
border-radius: 10px;
background-color: rgb(0, 0, 0);
transform-origin: 50% 50%;
transform: rotate(45deg);
}
</style>
{
width: 300px;
height: 100px;
margin-top: -120px;
position: relative;
z-index: 2;
}
.hill
{
width: 150px;
height: 150px;
border-radius: 10px;
background-color: rgb(0, 0, 0);
transform-origin: 50% 50%;
transform: rotate(45deg);
}
</style>
This is what you should have.
We use the nth-of-type pseudoselector because each of these will now have their own properties at this point.
#hills
{
width: 300px;
height: 100px;
margin-top: -120px;
position: relative;
z-index: 2;
}
.hill
{
width: 150px;
height: 150px;
border-radius: 10px;
background-color: rgb(0, 0, 0);
transform-origin: 50% 50%;
transform: rotate(45deg);
}
.hill:nth-of-type(1)
{
}
.hill:nth-of-type(2)
{
}
.hill:nth-of-type(3)
{
}
</style>
{
width: 300px;
height: 100px;
margin-top: -120px;
position: relative;
z-index: 2;
}
.hill
{
width: 150px;
height: 150px;
border-radius: 10px;
background-color: rgb(0, 0, 0);
transform-origin: 50% 50%;
transform: rotate(45deg);
}
.hill:nth-of-type(1)
{
}
.hill:nth-of-type(2)
{
}
.hill:nth-of-type(3)
{
}
</style>
The first hill gets moved 50 pixels left.
.hill:nth-of-type(1)
{
margin-left: -50px;
}
.hill:nth-of-type(2)
{
}
.hill:nth-of-type(3)
{
}
{
margin-left: -50px;
}
.hill:nth-of-type(2)
{
}
.hill:nth-of-type(3)
{
}
So far so good.
We move the middle "hill" up and to the right. It should placed higher than the other two.
.hill:nth-of-type(1)
{
margin-left: -50px;
}
.hill:nth-of-type(2)
{
margin-top: -180px;
margin-left: 75px;
}
.hill:nth-of-type(3)
{
}
{
margin-left: -50px;
}
.hill:nth-of-type(2)
{
margin-top: -180px;
margin-left: 75px;
}
.hill:nth-of-type(3)
{
}
See this?
Finally, we use margin-top and margin-left properties to move the last "hill".
.hill:nth-of-type(1)
{
margin-left: -50px;
}
.hill:nth-of-type(2)
{
margin-top: -180px;
margin-left: 75px;
}
.hill:nth-of-type(3)
{
margin-top: -120px;
margin-left: 200px;
}
{
margin-left: -50px;
}
.hill:nth-of-type(2)
{
margin-top: -180px;
margin-left: 75px;
}
.hill:nth-of-type(3)
{
margin-top: -120px;
margin-left: 200px;
}
Yep. It's coming along nicely.
What's next? The cross, of course! For cross, ensure that it's a large font size. margin-top is the property that moves the div vertically upwards while text-align is set to center so that it rests on top of the middle "hill".
.hill:nth-of-type(3)
{
margin-top: -120px;
margin-left: 200px;
}
#cross
{
font-size: 5em;
font-family: arial;
font-weight: bold;
margin-top: -270px;
text-align: center;
}
</style>
{
margin-top: -120px;
margin-left: 200px;
}
#cross
{
font-size: 5em;
font-family: arial;
font-weight: bold;
margin-top: -270px;
text-align: center;
}
</style>
See? There's the cross. Where's shadow? Look to the left "hill", it's hiding there.
What we do here is repeat the styling for shadow, but with a slightly different margin-top property.
#cross
{
font-size: 5em;
font-family: arial;
font-weight: bold;
margin-top: -270px;
text-align: center;
}
#shadow
{
font-size: 5em;
font-family: arial;
font-weight: bold;
margin-top: -100px;
text-align: center;
}
</style>
{
font-size: 5em;
font-family: arial;
font-weight: bold;
margin-top: -270px;
text-align: center;
}
#shadow
{
font-size: 5em;
font-family: arial;
font-weight: bold;
margin-top: -100px;
text-align: center;
}
</style>
Now shadow overlaps cross, but not perfectly. So the cross beam looks thicker. But that's not a problem. The animation later will take care of this.
For aura, we want the background to have spokes radiating from the center. So that means it's going to be a repeating conic gradient of yellow and orange.
#aura
{
width: 400px;
height: 400px;
margin-top: -100px;
margin-left: -50px;
border-radius: 50%;
background-image: repeating-conic-gradient(rgb(255, 255, 0) 5deg 10deg, rgb(255, 200, 0) 15deg 20deg, rgb(255, 255, 0) 25deg 30deg);
}
{
width: 400px;
height: 400px;
margin-top: -100px;
margin-left: -50px;
border-radius: 50%;
background-image: repeating-conic-gradient(rgb(255, 255, 0) 5deg 10deg, rgb(255, 200, 0) 15deg 20deg, rgb(255, 255, 0) 25deg 30deg);
}
Now would you look at that!
At this point, remove the red outlines. And set the overflow property of container to hidden.
div
{
border: 0px solid rgb(255, 0, 0);
}
h1
{
font-family: verdana;
text-align: center;
color: rgb(255, 200, 0);
}
#container
{
margin: 100px auto 0 auto;
border-radius: 50px;
border: 5px solid rgb(255, 200, 0);
width: 300px;
height: 200px;
overflow: hidden;
}
{
border: 0px solid rgb(255, 0, 0);
}
h1
{
font-family: verdana;
text-align: center;
color: rgb(255, 200, 0);
}
#container
{
margin: 100px auto 0 auto;
border-radius: 50px;
border: 5px solid rgb(255, 200, 0);
width: 300px;
height: 200px;
overflow: hidden;
}
Oh, this is looking so good.
Time to animate!
Add the classes unrotated and rotated. We want aura to rotate, see? So unrotated is the start state and rotated is the end state. I also use the transition property in both cases, to determine duration and style. Not a big issue, carry on.#aura
{
width: 400px;
height: 400px;
margin-top: -100px;
margin-left: -50px;
border-radius: 50%;
background-image: repeating-conic-gradient(rgb(255, 255, 0) 5deg 10deg, rgb(255, 200, 0) 15deg 20deg, rgb(255, 255, 0) 25deg 30deg);
}
.unrotated
{
transform: rotate(0deg);
transition: 10s ease;
}
.rotated
{
transform: rotate(360deg);
transition: 10s ease;
}
#hills
{
width: 300px;
height: 100px;
margin-top: -120px;
position: relative;
z-index: 2;
}
{
width: 400px;
height: 400px;
margin-top: -100px;
margin-left: -50px;
border-radius: 50%;
background-image: repeating-conic-gradient(rgb(255, 255, 0) 5deg 10deg, rgb(255, 200, 0) 15deg 20deg, rgb(255, 255, 0) 25deg 30deg);
}
.unrotated
{
transform: rotate(0deg);
transition: 10s ease;
}
.rotated
{
transform: rotate(360deg);
transition: 10s ease;
}
#hills
{
width: 300px;
height: 100px;
margin-top: -120px;
position: relative;
z-index: 2;
}
What we'll want to do here is set the class of aura to unrotated.
<div id="aura" class="unrotated">
</div>
</div>
Now use the toggleClass() method on aura.
<script>
$(document).ready(function() {
$("#aura").toggleClass("rotated");
});
</script>
$(document).ready(function() {
$("#aura").toggleClass("rotated");
});
</script>
And then use jQuery UI's "puff" effect on shadow. We'll set the animation to last 1 second, and specify that the end size of shadow will be 250% of the original.
<script>
$(document).ready(function() {
$("#aura").toggleClass("rotated");
$("#shadow").effect( "puff", {percent: 250}, 1000 );
});
</script>
$(document).ready(function() {
$("#aura").toggleClass("rotated");
$("#shadow").effect( "puff", {percent: 250}, 1000 );
});
</script>
See the effect! It looks like the crucifix with a fading black aura amid the rotating spokes.
And if you want to make this continuous, put that in a setInterval() function.
<script>
$(document).ready(function() {
$("#aura").toggleClass("rotated");
$("#shadow").effect("puff", {percent: 250}, 1000 );
setInterval
(
function()
{
$("#aura").toggleClass("rotated");
$("#shadow").effect("puff", {percent: 250}, 1000 );
},
10000
);
});
</script>
$(document).ready(function() {
$("#aura").toggleClass("rotated");
$("#shadow").effect("puff", {percent: 250}, 1000 );
setInterval
(
function()
{
$("#aura").toggleClass("rotated");
$("#shadow").effect("puff", {percent: 250}, 1000 );
},
10000
);
});
</script>
Auran't you glad it's Easter?
T___T
T___T









