Basics of CSS 3D

With the expansion of CSS we finally are able to place gradients, animation and 3D objects on the web without clogging users' computers.

Here we will talk about some basics of getting into 3D using only CSS
(No JavaScript!).

To begin with, let's talk about how to compose such objects and what CSS properties are necessary.

Composition

 

In order to animate (via keyframes or input events) a 3D object, we need to compose it, as it looks on the first frame.

Meaning we need to create:

  • Sides of that object.
  • Container which will hold all sides of that object.
  • A viewport that will hold the container.

 

So, from the top:

 

• Sides of the object

 

Whether you are creating a rotating 2D or 3D object, you need to remember about CSS property called backface-visibility, which causes an element to have its back visible, or not. If it is visible it will be a reversed image of your that element.
So, let’s assume you have dom element with red background and text saying “Hello”. Without backface-visibility set or backface-visibility: visible our object will have mirror-like reverse if you flip it 180 degrees.

However, if you set it to hidden (like backface-visibility:hidden) then rotation your object will be hidden (a white backface will only show up).

It’s important for you in case you need it for a card flip or a cube where you explicitly do not want that reverse look.

 

• Container

 

The next thing is the container, which usually is the div that must have property transform-style: preserve-3d. Once you have that placed it is time to actually set all sides of the object. Let’s take an example of a flipping card. We do so, by creating both sides, front and back of the card.

 

<div class="container">
    <div class="card front">FRONT</div>
    <div class="card back">BACK</div>
</div>

 

assigning them backface-visibility: hidden rule and transform-style: preserve-3d to .container class:

 

.container {
    transform-style: preserve-3d;
}
.card {
    backface-visibility: hidden;
}

 

and *flipping our backside* so the first frame it already looks like a real card:

 

.card.back {
    transform: rotateY(180deg);
}

 

By the way, *whenever you can*, use transform set of rules. This way you can be 100% sure it uses hardware GPU. If you want to move things, rotate them, skew them, whatever, just use transform. You will have the best performance this way.

 

To sum up all info in the example, check this link:[Live Code Example]

 

• Viewport

 

Alright, the next thing is setting up perspective in the viewport.

This will allow you to modify the distance between the Z plane and the user.
This distance creates a certain feeling of a 3D object, this way you can create a sort of fish-eye effect or a normal, everyday object, depending just on distance.

You can use whatever unit you prefer. The smaller the value the more “fish-eye” effect you get, the bigger – more vertices will have the same size.
So, to update our code, let us create additional `div` that covers whole content:

<div class="scene">
    <div class="container">
        <div class="card front">FRONT</div>
        <div class="card back">BACK</div>
    </div>
</div>

 

And appropriate CSS rule to it:

 

.scene {
    perspective: 1000px; // you can use other units if you want
}

[Live Code Example]

 

• Animating it!

 

Last but not least, time to spin it.

We’re going to use a keyframe in order to spin the whole card, don’t try and spin individual sides, since Chromium-based browsers will not allow you to do it.
The product of spinning sides individually will cause one side to spin normally, but the other will just jump to the last keyframe, without a smoothing animation effect.

Firefox has no problem with it, but let’s be honest, spinning the whole thing has more sense than moving individual parts of it.

So, let’s add keyframes rule:

 

.container {
    animation: spin-it 2s ease alternate infinite;
}
@keyframes spin-it {
    from {
        transform: rotateY(-30deg);
    }
}
to {
    transform: rotateY(180deg);
}

 

If your card is rotating by its side and not through the centre that means your .card class does not have the same width and height as it’s a container, you can fix this by assigning those values to the container and then having your .card class *inherit* it:

.container {
    width: 200px;
    height: 100px;
}
.container .card {
    width: inherit;
    height: inherit;
}

 

• My object is blurry, what gives?!

 

Animating with CSS has good sides (GPU accelerated animation, instead of CPU), but it does have some bad sides – the animated object is actually a copy.
Created by the browser that copy can be most of the time blurry.

You can work around that with transform: scale(0.9).
It will create a bit smaller image but will be as sharp as the original:

.container {
    transform: scale(0.9); // add it here as well to prevent image jumping to smaller size once the animation starts.
    animation: spin-it 2s ease infinite;
}
@keyframes spin-it {
    from {transform: rotateY(0) scale(0.9);}
    to {transform: rotateY(360deg) scale(0.9);}
}

[Final Live Code Demo]

 

 

______________

Title photo by Sebastian Svenson on Unsplash

Krzysztof Wisznarewski

Published:07/29/2021

Tags:

Insights Show all articles

4 steps to choose BI tool

Read more

Basics of CSS 3D

Read more

Do I need Business Intelligence?

Read more

MS Dynamics 365 vs SAP S4\HANA

Read more

Agile Teams

Read more

How to improve the defect management process?

Read more

10 hints for keeping your project well documented

Read more

The IT Revolution is upon us!

Read more