Ola everyone !
I recently posted a demo of a sphere in pure CSS :
It's been a while since I've written a post, so I forced myself to write one about this pen. I think you can find a few interesting tips about 3D in CSS and how to create an animation for 200 divs !
I'm absolutely not an expert in CSS or SCSS so please, put a comment if something could be improved !
I tried to divide this post in five steps to make it more readable.
- Generate a circle with Jade and SCSS
- Convert our circle into a sphere
- Rotate your sphere
- Customize your sphere
Please, do not use this for any real project, CSS is not supposed to be used for that kind of effects :)
1. Generate a circle with Jade and SCSS
a. Generate 200 div with jade
The first step for the creation of a circle is to generate all the particles that will shape our circle. Thanks to Jade,
we won't have to write 200 'divs' by hand.
In the parameters of your pen, you can select an HTML Preprocessor. In
my case I'm using Jade because I already used it a few times before but I
think you can use another one ;)
Now that we have access to all the power of Jade, let's create our divs !
Here is the code to define a container mommy
and the 200 divs.
Let's apply a bit of CSS to be sure the divs are correctly generated !
.mommy
- for (var x = 0; x < 200; x++)
div
.mommy{
border:1px solid black;
}
div{
width: 4px;
height: 4px;
background:red;
}
As you can see in the pen below, we have a 800px tall red block: our 200*4px divs !
See the Pen A. Generate 200 span with Pug by Louis Hoebregts (@Mamboleoo) on CodePen.
b. Set divs along a circle
Now that we have our divs in the body, it's time to position them along a circle ! For this we will need a CSS processor, for this demo I'll use SCSS but again, I think you can have the same result with another one.
Let's add some more CSS on our elements so we can move them more
easily. I'm applying an absolute position on the divs with a top &
left on -2px to center them on the 0,0 coordinates of the container, and
I'm setting a fixed size on the container.
Here is the CSS we now have :
.mommy{
border:1px solid black;
width: 400px;
height: 400px;
position: relative;
}
div{
width: 4px;
height: 4px;
background:red;
position: absolute;
top: -2px;
left: -2px;
}
Thanks to SCSS, we can apply the position for each div in a for loop so we don't have to set it manually on each one. I'm first creating a variable where I set the amount of divs created in the HTML. I will use this number a few time later so it will be easier to get the value from a variable instead of setting '200' each time. If one day I want 400 divs, I'll have to change only one line in the CSS !
Let's take a look at the loop :
$amount : 200;
@for $i from 1 through $amount {
//The inside of our loop
}
Now that we can apply the coordinates of each div in our loop, let's calculate those coordinates.
Here is the function I'm using to determine the positions of the elements around a circle :
x = cos((index/amount)*(PI*2))*radius + radius;
y = sin((index/amount)*(PI*2))*radius + radius;
Now, let's convert that function in SCSS, here is the result :
$x : cos(($i/$amount)*360deg)*200px + 200;
$y : sin(($i/$amount)*360deg)*200px + 200;
And finally, we need to apply the coordinates we just calculated :
div:nth-child(#{$i}) {
transform: translate3d($x, $y,0px);
}
Here is the result of this first step ! Not really beautiful but Eh, you just created a circle from scratch !
See the Pen B. Set spans along a circle by Louis Hoebregts (@Mamboleoo) on CodePen.
2. Convert your circle into a sphere
c. Convert our circle into a sphere
Phew, we made the longest part of this post !
Now we have a circle generated with SCSS but what we want to achieve here is a sphere.
Circles are part of 2D geometry, but Spheres are in the 3D geometry. 2D geometries have only two axis : X and Y. With 3D, we add a new axis : Z. This means we will have to calculate the Z position of our divs. Luckily there is a function that allows you to calculate the position of elements along a sphere. I won't go too much into details about that function but here it is :
Now that we have a function which does exactly what we need, we can insert it into our position loop !
θ : (index / amount) * 120; //Theta
δ : (index / amount) * PI; //Delta
x : radius * cos(δ) * cos(θ);
y : radius * cos(δ) * sin(θ);
z : radius * sin(δ);
@for $i from 1 through $amount {
$theta : ($i / $amount) * 120;
$delta : ($i / $amount) * pi();
$x : 200px * cos($delta) * cos($theta) + 200; //+200 to center our sphere in our 3D world
$y : 200px * cos($delta) * sin($theta) + 200; //+200 to center our sphere in our 3D world
$z : 200px * sin($delta);
div:nth-child(#{$i}){
transform: translate3d($x, $y,$z);
}
}
Let's take a look at our sphere. As you can see below, all the divs have new positions but we don't see too much 3D in it.
See the Pen C. Convert our circle into a sphere by Louis Hoebregts (@Mamboleoo) on CodePen.
d. Add perspective to our container
In CSS there is a property called perspective which allow us to set a specific perspective to any element. In our case, we want .mommy
to have some 3D. We also need to specify a transform-style: preserve-3d;
so our divs will be in a 3D environment.
See the Pen D. Add perspective to our container by Louis Hoebregts (@Mamboleoo) on CodePen.
Now we can see that all the divs have different sizes. The more distance between the "screen" and the div you have, the smaller your div will be. That means they are in a new world, a 3D one :)
3. Rotate your sphere
e. Make your sphere turn
Now that all your divs have their final position, it would be nice if we could see them to fully see the result. For this part we will use a keyframe animation with only one keyframe :
.mommy{
// [...]
animation: rotation 10s linear infinite;
}
@keyframes rotation{
to{
transform:rotateY(360deg);
}
}
See the Pen E. Make your sphere turn by Louis Hoebregts (@Mamboleoo) on CodePen.
f. Make all divs facing the camera
As you may have noticed, sometimes the divs disappear when they are not facing the camera but are at 90° from it. To prevent this unwanted effect, we need to rotate each div with an opposite value of it's parent. That way, all the divs will always be facing the camera !
We need to apply a negative rotation on the divs, but since they
already have a transform applied on it, we will create a pseudo element
which will be our red square. Thay way, the div will set the position,
and our pseudo element will be the visual we want. We also need to apply
a transform-style
on the div to turn our div into a 3D world.
div {
// [...]
transform-style: preserve-3d;
&:before{
content:"";
display: block;
width: 4px;
height:4px;
background:red;
animation: rotation 10s infinite linear reverse; //We use the same animation as on .mommy but in reverse mode !
}
}
See the Pen F. Make all spans facing the camera by Louis Hoebregts (@Mamboleoo) on CodePen.
Tada !
You have now a beautiful sphere in pure CSS :)
4. Customize your sphere
Here are a few examples of what you can do from the code you created. Free your mind for 10min and I'm sure you will find tons of ideas !
I hope this article taught you a few tips & tricks !
Let me know if you spot any English mistake or CSS bad practice :)
Mamboleoo