Preface:

Recently, I played with CSS to build 3D effects and wrote several demos, so the blog summary. Before reading this blog, check out the properties of CSS 3D for yourself, such as transform-style, transform-origin, transform, perspective.

demo1

Variable height cube, let’s have a look at the final result, it’s a little ugly, if the designer changed the color, add some elements should look much better

  

1. We first use CSS to realize a cuboid. A cuboid has six sides

<div class="cube-box">
    <div class="cube1 cube"></div>
    <div class="cube2 cube"></div>
    <div class="cube3 cube"></div>
    <div class="cube4 cube"></div>
    <div class="cube5 cube"></div>
    <div class="cube6 cube"></div>
</div>Copy the code

2. Set the width and height of the.cube-box and preserve-3D attributes to preserve all sub-elements of the.cube 3d conversion, and all sub-elements of the.cube are absolutely located

.cube-box{
    transform-style: preserve-3d;
    width: 30px;
    height: 100px;
    position: relative;
}
.cube{
    position: absolute;
    left: 0;
    top: 0;
}Copy the code

3. Create a surface. Cube1 with 100% width and height equal to the parent element and a background color of red

.cube1{
    width: 100%;
    height: 100%;
    background: red;
}Copy the code

4. To make it easier for us to see the stereo effect later, now let’s rotate the parent element and add the following code to make it look like this

.cube-box{
    transform: rotateX(-30deg) rotateY(45deg);
}Copy the code

Cube1 as the first element, we don’t need to rotate it, it’s the default surface, now we concatenate the second surface.cube2 as.cube1, but we make it green, it looks like this,.cube2 superimposed on.cube1, so we need to rotate.cube2 as well

.cube2{
    width: 100%;
    height: 100%;
    background: green;
}Copy the code

6. Now we try to rotate.cube2, which becomes the following effect. The rotate direction of the rotate is not explained here. If you don’t understand the rotate direction, you can check other documents.

.cube2{
    width: 100%;
    height: 100%;
    background: green;
    transform: rotateY(-90deg);
}Copy the code

7. Move it again with translate3D. Here’s what it looks like. Diadiadiaosi. The width of translate is 30px, so we need to move half of it 15px to concatenate it. This value needs to be calculated manually, or we can use JS to calculate it. It’s too low. I only need js to dynamically set the parent element according to the back-end data. The width and height of the cube box and all the child elements are self-adaptive, so that it is more convenient to use.

.cube2{ width: 100%; height: 100%; background: green; The transform: rotateY (90 deg) translate3d (15 px, 0 2 px); }Copy the code

8. So now we’ll use another property transform-origin, transform-origin defaults to “center center 0;” Or “50%, 50%, 0;” So in step 6, we rotated.cube2 according to its middle position. We changed the position to the left of the element, which also achieved the effect. The code was simpler

.cube2{
    width: 100%;
    height: 100%;
    background: green;
    transform-origin: left top;
    transform: rotateY(-90deg);
}Copy the code

9. We rotate.cube3 in the same way as.cube2, and set it to blue. The effect is as follows

.cube3{
    width: 100%;
    height: 100%;
    background: blue;
    transform-origin: right top;
    transform: rotateY(90deg);
}Copy the code

10. Cube4 is a little different, you don’t need to rotate it, you just need to move it 30px in the Z direction, you can set the percentage of the X and Y axes using width and height, for example, if width is 20px, if you want to move it 20px in the X direction, You can set translateX(100%), but you can only use a specific value for Z. So here I did not solve the problem of low, I can only write the value of translateZ manually or use JS to dynamically assign the value. The effect is as follows. If you have a better solution, please let me know by commenting on the blog.

.cube4{
    width: 100%;
    height: 100%;
    background: gray;
    transform-origin: right top;
    transform: translateZ(30px);
}Copy the code

11. Cube5 is also the top surface, our top and low surface are square,.cube5 if write 100% width and height is rectangular, in order to not manually or automatically write height, here use another writing method set width:100%; Leave height unset, padding-top: 100%; This also makes.cube5 a square, define pink, rotate 90 degrees along the X-axis, code and effect as follows

.cube5{
    width: 100%;
    padding-top: 100%;
    background: pink;
    transform-origin: left top;
    transform: rotateX(90deg);
}Copy the code

12. Finally,.cube6 and.cube5 are written the same way, except that we need to position them absolutely at the bottom. In this case, set the.cube class to 50% opacity for easy viewing

.cube6{
    width: 100%;
    padding-top: 100%;
    background: black;
    top: inherit;
    bottom: 0;
    transform-origin: left bottom;
    transform: rotateX(-90deg);
}Copy the code

13. We defined each face as red and adjusted the color value of each face so that it looked like a perspective

14. Now the cuboid has been written, let’s click on the motion effect, add a div. cubo-wapper and wrap the cubo-box again, so that the cubo-box is definitely positioned at the bottom of the parent element, so that the height of the cubo-box will extend and shrink upward when the height changes, js timer will change the height of the box every 5 seconds. Results the following

let boxs = document.getElementsByClassName('cube-box');
setInterval(()=>{
    for(let item in boxs){
        if(boxs[item].style) boxs[item].style.height = `${Math.random()*300}px`; }}, 5000).Copy the code

15. No, why is the bottom still moving? The reason is that tranform’s rotate is written on a.cube box, and when the height changes, it will be offset by rotation, so we can write the.cube box tranform into a.cube wrapper. Results the following

demo2

A cylinder, which is a bit poor when converted to GIF, works much better. The implementation of this is a bit weird and almost useless in the real world, so I’ll give you a rough idea of how to implement it.

1. Same as Demo1, define the wrapper layer and preserve-3D

<div class="wrapper">
    <div class="box" id="circles"> </div> </div> <style> .wrapper{ transform-style: preserve-3d; width: 100px; height: 100px; } .box{ width: 100%; height: 100%; position: relative; transform-style: preserve-3d; The transform: rotateX (73.5 deg) rotateY (5 deg); } </style>Copy the code

2. Insert n div in box, each div has the same style and is set to border-radius:50% and 1px border, the only difference is that the translateZ position of each div is 1 different, in fact, 1px border is arranged in order to form a column. This will generate a lot of divs, so we’ll use JS to generate the number of divs we need.

let circles = document.getElementById('circles');
for(leti=0; i<100; i++){let div = document.createElement('div');
    div.style = `transform: translateZ(${i}px)`;
    div.className = `circle ${i==0||i==99? 'bg':''}`;
    circles.appendChild(div);
}Copy the code

N 1px divs are seamlessly stitched together. Why are there gaps? Imagine a circle drawn on a piece of paper. If you look at the thinnest side of the paper, you can’t see the circle. If you change the Angle a little bit, you can only see a little bit. This way I also tried, write a ball, here do not upload GIF, screenshots to see the effect, github will have code you can download down to see, the effect is quite magical

demo3

String hanging card effect, the effect is roughly as follows, like hanging on the line of 6 photos, but also a little wind blowing effect. In fact, it is very simple, still use the principle of demo1 above to rotate the cards, and then arrange the cards by positioning, define an infinite loop swing animation, give each card a different time, and finally bind the click event, and use CSS transition animation for the elements. Transition animation ensures that elements will work when they are changed or restored, so transition animation is very suitable for interaction. Note: After 3d conversion, pay attention to the clickable area of the element, which can be viewed more accurately with chrome debugger.

Conclusion:

CSS 3D is mostly used in a few scenes, and is also a bit of a performance drain, so if you have the opportunity to use it, it’s nice to be able to add a little bit of surprise to the user experience on the web.

Ok, I know what you need, the warehouse address is ready github.com/zimv/css3d.

Now that you’ve seen this, don’t give me a thumbs up


Follow the official account of the great poet, the first time to get the latest articles.