2023 is the Year of the Rabbit in the Chinese Zodiac, and for this upcoming Lunar New Year, this is what the web tutorial will revolve around.
As I did in the Year of the Rat, I am going to turn the numbers into an animal, only this time, I will be using CSS and simple transformations to pull this off.
Here's some code. We first have a div with id
container. We want the div to be centered, so set the
margin property, and a width and height. Also, let's have a temporary
red outline for divs. Since we'll be using some Chinese text as well, we should also specify UTF-8 as the character set.
<!DOCTYPE html>
<html>
<head>
<title>Year of the Rabbit</title>
<meta charset="UTF-8">
<style>
div {outline: 1px solid red;}
.container
{
width: 700px;
height: 500px;
margin: 10% auto 0 auto;
}
</style>
<script>
</script>
</head>
<body>
<div class="container">
</div>
</body>
</html>
Our objective is to have the numbers 2023, with each number in a different div styled using the
number CSS class.
<div class="container">
<div class="number">2</div>
<div class="number">0</div>
<div class="number">2</div>
<div class="number">3</div>
</div>
Here's the styling for
number. I've set width and height, centering text and making the font large. The color is
light grey. Most importantly, the
position property is set to
absolute and
transition is at 1 second.
.container
{
width: 700px;
height: 500px;
margin: 10% auto 0 auto;
}
.number
{
width: 150px;
height: 200px;
text-align: center;
font-size: 160px;
font-family: verdana;
color: rgba(200, 200, 200, 1);
position: absolute;
-webkit-transition: all 1s;
transition: all 1s;
}
And here's how it looks. All cramped together!
For each of these numbers, we need to specify the
margin-top and
margin-left properties, since their divs are styled using the number CSS class already, and
number has the
position property set to
absolute. Bake this right in the HTML.
<div class="number" style="margin-left:50px;margin-top:100px">2</div>
<div class="number" style="margin-left:200px;margin-top:100px">0</div>
<div class="number" style="margin-left:350px;margin-top:100px">2</div>
<div class="number" style="margin-left:500px;margin-top:100px">3</div>
Now the numbers are nicely spaced out!
We want animation to happen when the user mouses over the container div, and the animation to reverse when the user mouses out. So add this in the div.
<div class="container" onmouseover="doChange()" onmouseout="reverseChange()">
Let's define these functions in the script tag.
<script>
function doChange()
{
}
function reverseChange()
{
}
</script>
In each of these functions, define
numbers as an array obtained from running the
getElementsByClassName() method. We want to get all elements with that have been styled using the CSS class number, which is all the large numbers making up "2023".
<script>
function doChange()
{
var numbers = document.getElementsByClassName("number");
}
function reverseChange()
{
var numbers = document.getElementsByClassName("number");
}
</script>
Now these numbers will animate to form a rabbit! Let's work on the
doChange() function. The first element (index 0) will be moved right and slightly down, and scaled to flip horizontally to form the left hind leg.
<script>
function doChange()
{
var numbers = document.getElementsByClassName("number");
numbers[0].style.transform = "translate(130px, 40px) scale(-1.2, 1.2) ";
}
function reverseChange()
{
var numbers = document.getElementsByClassName("number");
}
</script>
The second element (index 1) is the "0", and it will move right, all the way to the center, and enlarged with scaling. This forms the body.
<script>
function doChange()
{
var numbers = document.getElementsByClassName("number");
numbers[0].style.transform = "translate(130px, 40px) scale(-1.2, 1.2) ";
numbers[1].style.transform = "translate(70px, 0px) scale(1.5, 1.5)";
}
function reverseChange()
{
var numbers = document.getElementsByClassName("number");
}
</script>
The third element (index 2) is the other "2", and will move right and down, and enlarge to form the right hind leg.
<script>
function doChange()
{
var numbers = document.getElementsByClassName("number");
numbers[0].style.transform = "translate(130px, 40px) scale(-1.2, 1.2) ";
numbers[1].style.transform = "translate(70px, 0px) scale(1.5, 1.5)";
numbers[2].style.transform = "translate(20px, 40px) scale(1.2, 1.2)";
}
function reverseChange()
{
var numbers = document.getElementsByClassName("number");
}
</script>
The final element is the "3", and we will move it upwards and leftwards, rotate and elongate it to form ears.
<script>
function doChange()
{
var numbers = document.getElementsByClassName("number");
numbers[0].style.transform = "translate(130px, 40px) scale(-1.2, 1.2) ";
numbers[1].style.transform = "translate(70px, 0px) scale(1.5, 1.5)";
numbers[2].style.transform = "translate(20px, 40px) scale(1.2, 1.2)";
numbers[3].style.transform = "translate(-230px, -180px) rotate(-90deg) scale(3, 0.5)";
}
function reverseChange()
{
var numbers = document.getElementsByClassName("number");
}
</script>
Now with
reverseChange(), we also fiddle with the
transform property. Except that this is far simpler. All translations will be reverted to 0 pixels. Scaling will be at 1, and rotation will be 0 degrees.
<script>
function doChange()
{
var numbers = document.getElementsByClassName("number");
numbers[0].style.transform = "translate(130px, 40px) scale(-1.2, 1.2) ";
numbers[1].style.transform = "translate(70px, 0px) scale(1.5, 1.5)";
numbers[2].style.transform = "translate(20px, 40px) scale(1.2, 1.2)";
numbers[3].style.transform = "translate(-230px, -180px) rotate(-90deg) scale(3, 0.5)";
}
function reverseChange()
{
var numbers = document.getElementsByClassName("number");
numbers[0].style.transform = "translate(0px, 0px) scale(1, 1)";
numbers[1].style.transform = "translate(0px, 0px) scale(1, 1)";
numbers[2].style.transform = "translate(0px, 0px) scale(1, 1)";
numbers[3].style.transform = "translate(0px, 0px) rotate(0deg) scale(1, 1)";
}
</script>
Neat! Now when you mouse over container, this happens.
Let's add some shading. Add 5 divs in container. Each of them will be styled using the CSS class
shading, and have an id.
<div class="container" onmouseover="doChange()" onmouseout="reverseChange()">
<div class="shading" id="s1"></div>
<div class="shading" id="s2"></div>
<div class="shading" id="s3"></div>
<div class="shading" id="s4"></div>
<div class="shading" id="s5"></div>
<div class="number" style="margin-left:50px;margin-top:100px">2</div>
<div class="number" style="margin-left:200px;margin-top:100px">0</div>
<div class="number" style="margin-left:350px;margin-top:100px">2</div>
<div class="number" style="margin-left:500px;margin-top:100px">3</div>
</div>
Here is the styling for
shading. It has the following properties...
border-radius - set at 50% to make sure they are round.
background-color - set to a solid
black. We will manipulate this later.
position - this is
absolute, because we will be positioning the div later via the
margin-left and
margin-top properties.
transition - this is set at 1 second.
.number
{
width: 150px;
height: 200px;
text-align: center;
font-size: 160px;
font-family: verdana;
color: rgba(200, 200, 200, 1);
position: absolute;
-webkit-transition: all 1s;
transition: all 1s;
}
.shading
{
border-radius: 50%;
background-color: rgba(0, 0, 0, 1);
position: absolute;
-webkit-transition: all 3s;
transition: all 3s;
}
Now, we have stylings for each of the divs. We will reference them using the ids. Each of them has different widths, heights and
margin-left and
margin-top properties.
.shading
{
border-radius: 50%;
background-color: rgba(0, 0, 0, 1);
position: absolute;
-webkit-transition: all 3s;
transition: all 3s;
}
#s1
{
width: 20px;
height: 150px;
margin-left: 320px;
margin-top: -20px;
}
#s2
{
width: 20px;
height: 150px;
margin-left: 350px;
margin-top: -20px;
}
#s3
{
width: 80px;
height: 130px;
margin-left: 305px;
margin-top: 150px;
}
#s4
{
width: 50px;
height: 100px;
margin-left: 250px;
margin-top: 200px;
transform: rotate(-45deg);
}
#s5
{
width: 50px;
height: 100px;
margin-left: 390px;
margin-top: 200px;
transform: rotate(45deg);
}
This is what the divs look like.
Mouse over, and you will see how it aligns with the transformed numbers.
But let's animate the shading as well. Set this to 0% opacity.
.shading
{
border-radius: 50%;
background-color: rgba(0, 0, 0, 0);
position: absolute;
-webkit-transition: all 3s;
transition: all 3s;
}
In
doChange(), we declare
shadings as an array of all elements styled using CSS class
shading.
function doChange()
{
var numbers = document.getElementsByClassName("number");
var shadings = document.getElementsByClassName("shading");
numbers[0].style.transform = "translate(130px, 40px) scale(-1.2, 1.2) ";
numbers[1].style.transform = "translate(70px, 0px) scale(1.5, 1.5)";
numbers[2].style.transform = "translate(20px, 40px) scale(1.2, 1.2)";
numbers[3].style.transform = "translate(-230px, -180px) rotate(-90deg) scale(3, 0.5)";
}
Then we use a
For loop to iterate through
shadings, and set each element's
background-color property to 20% opacity.
function doChange()
{
var numbers = document.getElementsByClassName("number");
var shadings = document.getElementsByClassName("shading");
numbers[0].style.transform = "translate(130px, 40px) scale(-1.2, 1.2) ";
numbers[1].style.transform = "translate(70px, 0px) scale(1.5, 1.5)";
numbers[2].style.transform = "translate(20px, 40px) scale(1.2, 1.2)";
numbers[3].style.transform = "translate(-230px, -180px) rotate(-90deg) scale(3, 0.5)";
for (var i = 0; i < shadings.length; i++)
{
shadings[i].style.backgroundColor = "rgba(100, 100, 100, 0.2)";
}
}
And we do the same in
reverseChange(), except we, well,
reverse the change!
function doChange()
{
var numbers = document.getElementsByClassName("number");
var shadings = document.getElementsByClassName("shading");
numbers[0].style.transform = "translate(130px, 40px) scale(-1.2, 1.2) ";
numbers[1].style.transform = "translate(70px, 0px) scale(1.5, 1.5)";
numbers[2].style.transform = "translate(20px, 40px) scale(1.2, 1.2)";
numbers[3].style.transform = "translate(-230px, -180px) rotate(-90deg) scale(3, 0.5)";
for (var i = 0; i < shadings.length; i++)
{
shadings[i].style.backgroundColor = "rgba(100, 100, 100, 0.2)";
}
}
function reverseChange()
{
var numbers = document.getElementsByClassName("number");
var shadings = document.getElementsByClassName("shading");
numbers[0].style.transform = "translate(0px, 0px) scale(1, 1)";
numbers[1].style.transform = "translate(0px, 0px) scale(1, 1)";
numbers[2].style.transform = "translate(0px, 0px) scale(1, 1)";
numbers[3].style.transform = "translate(0px, 0px) rotate(0deg) scale(1, 1)";
for (var i = 0; i < shadings.length; i++)
{
shadings[i].style.backgroundColor = "rgba(100, 100, 100, 0)";
}
}
So when you mouse over, you can see the change!
When you mouse out, the shadings disappear. But you can still see the
red outline! That's useful.
Now let's add some text. This will take the form of two divs within the
container div. Both are styled using the
text CSS class. The first div contains a message in Chinese text. It is a standard CNY greeting which translates to "Good fortune and prosperity to you, happy Year of the Rabbit!" The second div contains a simple instruction.
<div class="container" onmouseover="doChange()" onmouseout="reverseChange()">
<div class="shading" id="s1"></div>
<div class="shading" id="s2"></div>
<div class="shading" id="s3"></div>
<div class="shading" id="s4"></div>
<div class="shading" id="s5"></div>
<div class="number" style="margin-left:50px;margin-top:100px">2</div>
<div class="number" style="margin-left:200px;margin-top:100px">0</div>
<div class="number" style="margin-left:350px;margin-top:100px">2</div>
<div class="number" style="margin-left:500px;margin-top:100px">3</div>
<div class="text">恭喜发财,兔年快乐!</div>
<div class="text">(Hover to play)</div>
</div>
Here is the styling for text. We have a height and width, center alignment and font specifications. These are cosmetic. The important thing is the
position property, which is set to
absolute, and the
transition property which sets animation speed to 1 second.
#s5
{
width: 50px;
height: 100px;
margin-left: 390px;
margin-top: 200px;
transform: rotate(45deg);
}
.text
{
width: 500px;
height: 100px;
text-align: center;
font-weight: bold;
font-size: 30px;
font-family: verdana;
position: absolute;
-webkit-transition: all 1s;
transition: all 1s;
}
Right now, you can see that both divs are overlapping.
Let's fix this stuff. In the HTML itself, we embed
margin-left and
margin-top properties.
<div class="text" style="margin-left:100px;margin-top:400px;">恭喜发财,兔年快乐!</div>
<div class="text" style="margin-left:100px;margin-top:400px;">(Hover to play)</div>
Now you see both divs are moved lower, and to the middle. But they still overlap!
So let's change the first div to 0% opacity. When you next refresh, it should no longer be visible.
<div class="text" style="margin-left:100px;margin-top:400px;color:rgba(255, 0, 0, 0);">恭喜发财,兔年快乐!</div>
<div class="text" style="margin-left:100px;margin-top:400px;color:rgba(200, 200, 200, 1);">(Hover to play)</div>
In
doChange(), declare
text as an array of all elements styled using CSS class
text.
function doChange()
{
var numbers = document.getElementsByClassName("number");
var shadings = document.getElementsByClassName("shading");
var text = document.getElementsByClassName("text");
numbers[0].style.transform = "translate(130px, 40px) scale(-1.2, 1.2) ";
numbers[1].style.transform = "translate(70px, 0px) scale(1.5, 1.5)";
numbers[2].style.transform = "translate(20px, 40px) scale(1.2, 1.2)";
numbers[3].style.transform = "translate(-230px, -180px) rotate(-90deg) scale(3, 0.5)";
for (var i = 0; i < shadings.length; i++)
{
shadings[i].style.backgroundColor = "rgba(100, 100, 100, 0.2)";
}
}
Set the first element (index 0) to 100% opacity, and the second element (index 1) to 0% opacity.
function doChange()
{
var numbers = document.getElementsByClassName("number");
var shadings = document.getElementsByClassName("shading");
var text = document.getElementsByClassName("text");
text[0].style.color = "rgba(255, 0, 0, 1)";
text[1].style.color = "rgba(200, 200, 200, 0)";
numbers[0].style.transform = "translate(130px, 40px) scale(-1.2, 1.2) ";
numbers[1].style.transform = "translate(70px, 0px) scale(1.5, 1.5)";
numbers[2].style.transform = "translate(20px, 40px) scale(1.2, 1.2)";
numbers[3].style.transform = "translate(-230px, -180px) rotate(-90deg) scale(3, 0.5)";
for (var i = 0; i < shadings.length; i++)
{
shadings[i].style.backgroundColor = "rgba(100, 100, 100, 0.2)";
}
}
In
reverseChange(), do the exact opposite!
function reverseChange()
{
var numbers = document.getElementsByClassName("number");
var shadings = document.getElementsByClassName("shading");
var text = document.getElementsByClassName("text");
text[0].style.color = "rgba(255, 0, 0, 0)";
text[1].style.color = "rgba(200, 200, 200, 1)";
numbers[0].style.transform = "translate(0px, 0px) scale(1, 1)";
numbers[1].style.transform = "translate(0px, 0px) scale(1, 1)";
numbers[2].style.transform = "translate(0px, 0px) scale(1, 1)";
numbers[3].style.transform = "translate(0px, 0px) rotate(0deg) scale(1, 1)";
for (var i = 0; i < shadings.length; i++)
{
shadings[i].style.backgroundColor = "rgba(100, 100, 100, 0)";
}
}
And there you go. Fade in...
...fade out!
This would look much better without the
red outline.
div {outline: 0px solid red;}
Yep!
Happy holidays!
I know this doesn't look
exactly like a rabbit. But whatevs, dude.
Thank you and have a great 兔 0 兔 3!
T___T