And it's not a bad thing!
Hashnode for those who don't know, it is a blogging platform for technical articles. Since the early days, I've been a member, and it has grown massively since then.
Recently one of the founders shared these impressive statistics on Twitter:
And right before that Nazanin, announced on Twitter that she would organize a CSS art challenge, before I even knew what it was going to be about, I've said yes.
And here we are. This article describes how I made my CSS artwork for this Hashnode CSS Art Challenge.
My result looks like this:
Note: You can try it out at the bottom
The rules and my idea
The rules for this challenge are super simple.
- Use the Hashnode logo and run it into whatever you think of.
I was trying to fall asleep, but this challenge kept me up. I just couldn't put my finger on what I wanted to create.
And then it hit me!
Hashnode is taking over the world! So let's make a character out of this logo and have it walk around the world.
My idea is to combine the CSS art I know and try out pixel art, as that sounds cool to me!
Creating the logo
Let's start with the logo. I'm sure you might think, oh well, you can use a rounded square and put a round div over it, r right?
And yes, we could do that, but then we can't use backgrounds behind it.
So I decided to go with a little different approach.
I've added a div that I called hashnode
and inside created a body
which will hold the logo.
.hashnode {
margin-top: -10%;
position: relative;
width: 40vmin;
aspect-ratio: 1;
.body {
width: 100%;
height: 100%;
position: absolute;
border-radius: 27%;
transform: rotate(45deg);
background: #2962ff;
-webkit-mask: radial-gradient(#0000 28%, #000 28%);
mask: radial-gradient(#0000 28%, #000 28%);
z-index: 2;
}
}
The magic here is actually in the webkit-mask
. This defines a transparent radial gradient.
This will create a round gap in the body.
Note: This idea was demoed out by Alvaro. Thank you very much for that.
Then I decided to add arms to the character, which would move. The arms are two times the same styling with a different offset. I've also made sure the right arm is one second delayed.
.arm {
width: 50%;
height: 30%;
border: solid 5px #000;
border-color: #001 transparent transparent #001;
border-radius: 50%/70% 0% 0 0;
position: absolute;
animation: 2s move-arm infinite;
transform: rotate(45deg) scaleY(-1);
top: 20%;
transform-origin: bottom left;
&:before {
content: '';
width: 10%;
background: #000;
position: absolute;
aspect-ratio: 1;
right: -5%;
top: -10%;
border-radius: 50%;
}
&-left {
left: 10%;
z-index: 3;
}
&-right {
animation-delay: 1s;
left: 70%;
z-index: 1;
}
}
You can see I used the before
selector to add the little round hand-like shapes, which would make the arms look neater.
This shape is a square box where we color only two sides of a rounded border.
This is what it looks like if we color it completely.
A good thing to note about the arm is this:
transform-origin: bottom left;
This defines what axis the transform should take place. Setting this to bottom left
allows the rotation to happen on a solid axis, making the arm "swing".
As for the swing animation goes:
@keyframes move-arm {
0% {
transform: rotate(45deg) scaleY(-1);
}
50% {
transform: rotate(0deg) scaleY(-1);
}
100% {
transform: rotate(45deg) scaleY(-1);
}
}
A very straightforward rotating from 45 degrees to 0 and back. I'm using the scaleY to invert because I started upside down and was too lazy to revert it π.
The legs are a very similar approach, but they are longer, and the shoes are slightly different.
.leg {
width: 30%;
height: 50%;
border: solid 5px #000;
border-color: #000 #000 transparent transparent;
border-radius: 0 80%/45%;
position: absolute;
z-index: 10;
transform-origin: top left;
transform: rotate(30deg);
top: 100%;
left: 50%;
animation: 2s move-leg infinite;
&:before {
content: '';
width: 50%;
height: 10%;
background: #000;
position: absolute;
bottom: -10%;
border-radius: 50%;
left: 90%;
}
&-left {
animation-delay: 1s;
}
&-right {
z-index: 1;
}
}
And for the animation, I used the same approach. But with fewer degrees since your legs don't swing as much as your arms.
@keyframes move-leg {
0% {
transform: rotate(30deg);
}
50% {
transform: rotate(0deg);
}
100% {
transform: rotate(30deg);
}
}
Meme glasses pixel art
I decided to give the character some glasses and meme glasses for that Mather.
They are perfect for trying out pixel art, as they are pixels.
The glasses look like this:
.glasses {
display: block;
width: 10px;
height: 10px;
position: absolute;
left: 15%;
z-index: 3;
box-shadow: 10px 10px #000000, 20px 10px #000000, 30px 10px #000000, 40px 10px #000000,
50px 10px #000000, 60px 10px #000000, 70px 10px #000000, 80px 10px #000000,
90px 10px #000000, 100px 10px #000000, 110px 10px #000000, 120px 10px #000000,
130px 10px #000000, 140px 10px #000000, 150px 10px #000000, 160px 10px #000000,
170px 10px #000000, 180px 10px #000000, 190px 10px #000000, 200px 10px #000000,
10px 20px #000000, 20px 20px #000000, 30px 20px #000000, 40px 20px #000000,
50px 20px #000000, 60px 20px #000000, 70px 20px #000000, 80px 20px #000000,
90px 20px #000000, 120px 20px #000000, 130px 20px #000000, 140px 20px #000000,
150px 20px #000000, 160px 20px #000000, 170px 20px #000000, 180px 20px #000000,
190px 20px #000000, 200px 20px #000000, 20px 30px #000000, 30px 30px #000000,
40px 30px #000000, 50px 30px #000000, 60px 30px #000000, 70px 30px #000000,
80px 30px #000000, 90px 30px #000000, 120px 30px #000000, 130px 30px #000000,
140px 30px #000000, 150px 30px #000000, 160px 30px #000000, 170px 30px #000000,
180px 30px #000000, 190px 30px #000000, 30px 40px #000000, 40px 40px #000000,
50px 40px #000000, 60px 40px #000000, 70px 40px #000000, 80px 40px #000000,
130px 40px #000000, 140px 40px #000000, 150px 40px #000000, 160px 40px #000000,
170px 40px #000000, 180px 40px #000000, 40px 50px #000000, 50px 50px #000000,
60px 50px #000000, 70px 50px #000000, 140px 50px #000000, 150px 50px #000000,
160px 50px #000000, 170px 50px #000000;
}
This stacking of border shadows allows us to create a pixel-like effect.
I enjoyed using this and will most likely dedicate a complete article to pixel art and how it works.
Making the character whistle
I thought it would be cool to make the character whistle. In this case, it means a musical note comes out of its "hole" (mouth?).
For this, I used the before
selector on the hashnode div.
.hashnode {
&:before {
content: 'π΅';
position: absolute;
font-size: 2rem;
animation: 5s notes infinite;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
opacity: 0;
z-index: 3;
}
}
As you can see, it plays an infinite notes
animation.
The notes animation looks like this:
@keyframes notes {
0% {
opacity: 1;
transform: rotate(0deg);
}
5% {
opacity: 1;
transform: rotate(0deg);
}
75% {
transform: rotate(360deg);
top: -100%;
}
100% {
opacity: 0;
transform: rotate(360deg);
}
}
It starts by setting the opacity to 1 and resetting the rotation. Then we use a 5% step not to make the animation super fast and rotate the note as we move it upwards. And eventually, we fade it out.
This will then re-loop, making it start from 0%.
I think it turned out to be quite a fantastic addition.
Run the world animation
The last part is the globe that spins around. For this, I created a big circle.
.world {
position: absolute;
width: 75vmin;
aspect-ratio: 1;
background: blue;
border-radius: 50%;
top: 100%;
left: -50%;
background-image: url(https://cdn.hashnode.com/res/hashnode/image/upload/v1641971056244/tPSv8apET.png);
background-size: cover;
background-position: center center;
animation: 15s world linear infinite;
}
The circle is then filled with a PNG image of the world. You can open the above image to see what it looks like.
I've added a world
animation that will spin it around. It's important to note the linear
animation so it won't slow down once it's almost complete but move at the same speed all the time.
The animation itself looks like this:
@keyframes world {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
Just a simple from 0 degrees to 360 degrees animation that makes the world go round, and round and round!
Finishing touch
Go ahead, click the character...
(Put your music up! π΅)
Yes, I decided to add "Daft Punk - Around the world" when clicking the logo.
For this, we leverage a little bit of JavaScript that looks like this:
const audio = new Audio('https://download.mp3very.buzz/d/Daft-Punk-Around-The-World.mp3');
const hashnode = document.querySelector('.hashnode');
hashnode.addEventListener('click', () => {
audio.paused ? audio.play() : audio.pause();
});
This will load a new Audio object, and once we click the logo, it will toggle between playing and pausing the music.
Conclusion
I loved doing this challenge as it allowed me to try out different types of CSS art.
And I think it came out pretty cool π
A big shoutout to the following people for all their parts of information around it:
- Nazanin Ashrafi for setting this up! β‘οΈ
- Alvaro Montoro for the mask setup π
- Ale Thomas Ale for the pixel-art idea πΎ
Thank you for reading, and let's connect!
Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter