It has been a long time since I came back to review the knowledge of CSS. It happens to be the deadline…… for writing an article at the end of the month

All the previous articles were posted in SF, nuggets is the first.

So this time I chose to consolidate the knowledge of CSS3 animation in detail, because I only used some properties before and did not delve into the details.

By the time I finished writing this article, I realized that CSS can do a lot of cool things.

The completion of the demo of this article is also checked a lot of relevant knowledge points and refer to the content of some articles. But no matter what, as a front-end rookie, is always learning to grow. This sentence is written here in my mind also a little more comfortable. (to escape…

Final demo effect address

Below I will explain step by step how to use pure CSS to achieve a rotating rubik’s cube effect.

In general, we need to implement the following two main functions:

  • Build a cube that rotates

  • Let the cube have the characteristics of basic rotation

However, before completing the above two points, we need to understand or become familiar with the basic knowledge of CSS3 to achieve its function:

  1. transition

  2. transform

  3. perspective

  4. preserve-3d

  5. animation

Transition property – Transition effect

transition: property duration timing-fucntion delay;
Copy the code

This property should be familiar and not covered in detail, except to list all the child properties it has.

Transition attribute — transition duration — transition function (curve) — transition delay

transition-timing-function: linear|ease|ease-in|ease-out|ease-in-out; Primitive has basic transition functionsCopy the code

Transform property – Transforms elements 2D or 3D

It has several common transformation methods: Scale Scale3D Translate Translate3D Rotate rotate3D and so on.

transform-origin: x-axis y-axis z-axis; Transform-style: preserve-3d; Make the children of the transformation retain the 3D transformation (used with the perspective)Copy the code

Perspective attribute – Gives elements a 3D perspective

perspective: 1000px; It can be written in two ways: transform (1000px);Copy the code

This property gives the object a three-dimensional 3D perspective effect. The larger the value is, the farther the object is from our eyes to see the object on the screen. On the contrary, the smaller the value is, the closer it is to our perspective, that is, the larger the size displayed on the screen. It is used in conjunction with Preserve-3D to build a stage view on the parent element that needs to be 3d, allowing the child element to perform a true 3D transformation.

Detailed explanation of Transform (Zhang Xinxu)

A basic cube needs to combine the above three properties to achieve.

Cube

<div class="cube-wrap">
    <div class="cube">
        <div class="cube-face front"><img src="1.jpg"></div>
        <div class="cube-face back"><img src="2.jpg"></div>
        <div class="cube-face left"><img src="3.jpg"></div>
        <div class="cube-face right"><img src="4.jpg"></div>
        <div class="cube-face top"><img src="5.jpg"></div>
        <div class="cube-face bottom"><img src="6.jpg"></div>
    </div>
</div>
Copy the code

Important CSS styles

.cube-wrap{
    width: 300px;
    height: 300px;
    perspective: 1000px;
    position: relative;
}
.cube-wrap .cube{
    width: 100%;
    height: 100%;
    position: absolute;
    transform-style: preserve-3d;
    transition: all .5s ease;
}
.cube-wrap .cube .cube-face{
    width: 100%;
    height: 100%;
    position: absolute;
    overflow: hidden;
    opacity: 0.9;
    border: 1px solid #ccc;
}
.cube-wrap .cube .cube-face img{
    width: 100%;
    height: 100%;
}
.cube-face.front{
    transform: translateZ(150px);
}
.cube-face.back{
    transform: rotateX(180deg) translateZ(150px);
}
.cube-face.left{
    transform: rotateY(-90deg) translateZ(150px);
}
.cube-face.right{
    transform: rotateY(90deg) translateZ(150px);
}
.cube-face.top{
    transform: rotateX(90deg) translateZ(150px);
}
.cube-face.bottom{
    transform: rotateX(-90deg) translateZ(150px);
}
Copy the code

Here we use Perspective and prepreserve – 3D for the parent element before the child element’s 3D transformation takes effect.

How does the above code fit into a complete cube? A closer look inside the browser developer tools shows that the cube element is located on the center side of the cube. So we have an idea of how to use the code to construct each side of the cube.

Firstly, it should be clear about the directions of x, Y and Z axes of the spatial cartesian coordinate system established during the transform correlation transformation.

That is, take the computer screen as the plane, the horizontal direction is the X axis, the vertical direction is the Y axis, and the vertical direction is the Z axis.

So it’s very easy to make the six faces of the cube, the cube starts in the center, the length of the cube is 300px, so translateZ(150px) is the face. To create the back side, first reverse the initial face 180deg counterclockwise, at this point the front face points to the back side, so just translateZ(150px) more. To construct the left side, rotate rotateY(-90deg) around the Y-axis and rotateY(90deg) around the right side, and then translateZ(150px). It should be noted that when a surface rotates around an axis, counterclockwise rotation is positive and clockwise rotation is negative.

Animation attributes

This property is certainly the most important in CSS3 animation, and each of its sub-properties is worth examining carefully.

animation: name duration timing-function delay iteration-count direction fill-mode play-state; animation-delay: 1s; When set to a negative value for the animation began immediately, and skip 1 seconds before the animation animation - direction: normal | reverse | alternate | alternate - reverse; Defines whether the alternate animation is played in an odd number of cycles (1, 3, 5...). Forward, in even number of times (2, 4, 6...) Play alternate-reverse animation in odd number of times (1, 3, 5...) Play backwards, in even numbers (2, 4, 6...) Positive play animation - fill - mode: none | recently | backwards | to both; Specifies that when the animation is not playing, Towards the end of the elements' forwards animation, stay in the last frame backwards. During the animation-delay, both activate the first frame of the animation to move forwards and backwards animation-play-state: paused|running; Controls the animation to pause or run. @keyframes to set animation keyframes, in this case we use from... To or percentage to implement custom animationsCopy the code

Animation,

Now we add an animation to the cube we have built:

.cube-wrap .cube{ ...... animation: spin 10s linear infinite; } @keyframes spin { from { transform: rotateX(45deg) rotateY(45deg); } to { transform: rotateX(405deg) rotateY(765deg); }}Copy the code

Carousel

Now that we have a cube that can rotate freely, we need to complete the basic functions of the rotation.

  1. Switch between left and right buttons

  2. Bottom button switch

Before implementing these two features, we need to take a look at two powerful HTML tags that work together to achieve the effect of clicking on a toggle in a rotation diagram. These are label and input tags, so let’s look at their basic usage.

< Input type="radio" id="1"> < Label for="1" ></label> Click on the label label, and the input label with ID 1 is selectedCopy the code

Here, the for in the label tag is associated with the ID in the input tag, while the type in the input tag is radio, which is the effect of the checked field, and it has a checked attribute (To achieve the effect of the single field, you need to set name=” XXX “, at this time the name must be consistent, This effect is used below.)

Now is the time to start implementing concrete effects.

<div class="container">
    <div class="cube-wrap">
        <input type="radio" name="cuber" class="controller" id="1" checked="true">
        <input type="radio" name="cuber" class="controller" id="2">
        <input type="radio" name="cuber" class="controller" id="3">
        <input type="radio" name="cuber" class="controller" id="4">
        <input type="radio" name="cuber" class="controller" id="5">
        <input type="radio" name="cuber" class="controller" id="6">
        <div class="cube">.</div>
        <div class="cube_left">
            <label for="6" class="cube_action"></label>
            <label for="1" class="cube_action"></label>
            <label for="2" class="cube_action"></label>
            <label for="3" class="cube_action"></label>
            <label for="4" class="cube_action"></label>
            <label for="5" class="cube_action"></label>
        </div>
        <div class="cube_right">
            <label for="2" class="cube_action"></label>
            <label for="3" class="cube_action"></label>
            <label for="4" class="cube_action"></label>
            <label for="5" class="cube_action"></label>
            <label for="6" class="cube_action"></label>
            <label for="1" class="cube_action"></label>
        </div>
        <div class="indicators">
            <label for="1" class="indicator"></label>
            <label for="2" class="indicator"></label>
            <label for="3" class="indicator"></label>
            <label for="4" class="indicator"></label>
            <label for="5" class="indicator"></label>
            <label for="6" class="indicator"></label>
        </div>
    </div>
</div>
Copy the code

Implement the left, right and bottom CSS styles first

.cube_left .cube_action{
    left: -75px;
    top: 50%;
    transform: translateY(50%); }.cube_right .cube_action{
    right: -75px;
    top: 50%;
    transform: translateY(50%); }.cube_action{
    background-color: #fafafa;
    border-radius: 50%;
    cursor: pointer;
    display: none;
    width: 40px;
    height: 40px;
    opacity: 0.15;
    position: absolute;
    transition: opacity 0.5 s ease;
    z-index: 5;
}
.cube_action:hover{
    opacity: 1;
}
.cube_action::before{
    border-bottom: 4px solid # 111;
    border-right: 4px solid # 111;
    content: ' ';
    display: block;
    height: 25%;
    left: 50%;
    position: absolute;
    top: 50%;
    width: 25%;
    transform: translate(70%, 50%)rotate(-45deg);
}
.cube_left .cube_action::before{
    transform: translate(40%, 50%)rotate(135deg);
}
.indicators{
    position: absolute;
    left: 0;
    right: 0;
    bottom: -80px;
    padding: 20px;
    text-align: center;
    opacity:0;
    transition: opacity .3s;
}
.container:hover .indicators{
    opacity: 1;
}
.indicators .indicator{
    background-color: #fafafa;
    border-radius: 50%;
    cursor: pointer;
    display: inline-block;
    width: 14px;
    height: 14px;
    margin: 6px;
    opacity:.15;
}
.controller{
    display: none;
}
Copy the code

After writing the above code, we don’t see the results we want because they all need hover events to trigger.

Now let’s style the outermost container and define an entry animation.

.container{
    width: 600px;
    height: 600px;
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: -300px;
    margin-left: -300px;
    transition: all .5s ease;
    transform: scale(0.25);
}
.container:hover {
    transform: scale(1);
}
.container:hover .cube-wrap .cube{
    animation: entrance .5s ease ;
}
@keyframes entrance {
    from {
        transform: rotateX(-225deg) rotateY(-225deg); }}Copy the code

When the mouse moves into the cube, the animation is replaced with the entrance instead of spin.

So the key point again, in the end CSS is how to achieve click to switch round the image?

The principle is simple, but it’s really the combination of the label tag and the input tag mentioned earlier to achieve amazing results.

.controller:nth-of-type(1):checked ~ .cube{
    transform: translateZ(-150px);
}
.controller:nth-of-type(2):checked ~ .cube{
    transform: translateZ(-150px) rotateX(-180deg) ;
}
.controller:nth-of-type(3):checked ~ .cube{
    transform: translateZ(-150px) rotateY(90deg) ;
}
.controller:nth-of-type(4):checked ~ .cube{
    transform: translateZ(-150px) rotateY(-90deg) ;
}
.controller:nth-of-type(5):checked ~ .cube{
    transform: translateZ(-150px) rotateX(-90deg) ;
}
.controller:nth-of-type(6):checked ~ .cube{
    transform: translateZ(-150px) rotateX(90deg) ;
}
Copy the code

Either clicking on the left and right buttons or clicking on the bottom button triggers the for property of the label label to link the checked property of the corresponding input tag.

How to invert the corresponding side to the side facing the screen is as simple as inverting the symbols in the transformation of each side of the cube.

Note that the CSS selector we use here is also a trick :nth-of-type(n) selects the NTH tag of the same type, and the ~ symbol selects the tag of the same class.

Thoroughly understand the difference between nTH-child and NTH-of-type

Now looking back at the HTML structure at the beginning, the for in the label tag of indicators seems to understand the logic that clicking on any label triggers the CHECKED attribute of any input tag for the corresponding 3D conversion. Why does the “for” sequence in the label tag look wrong?

I’ve been thinking a lot about this myself, and I had a lot of trouble figuring out that the six corresponding labels in dot cube_left or dot cube_right are superimposed on each other, and they’re all display: None, and that’s interesting, so let’s look at the code.

.container:hover .controller:nth-of-type(1):checked ~ .cube_left .cube_action:nth-of-type(1)..container:hover .controller:nth-of-type(1):checked ~ .cube_right .cube_action:nth-of-type(1){
    display: block;
}
.container:hover .controller:nth-of-type(2):checked ~ .cube_left .cube_action:nth-of-type(2)..container:hover .controller:nth-of-type(2):checked ~ .cube_right .cube_action:nth-of-type(2){
    display: block; }... . ..container:hover .controller:nth-of-type(6):checked ~ .cube_left .cube_action:nth-of-type(6)..container:hover .controller:nth-of-type(6):checked ~ .cube_right .cube_action:nth-of-type(6){
    display: block;
}
Copy the code

Now we default that the first element in the Controller is checked, with its checked property true. So the first label in the left and right buttons is displayed as display:block. If we now click on the left button, we want the bottom of the cube to appear on the front of the screen, so for should be set to 6. If you click the button on the right, the for of the first label should be set to 2. Following this logic, we can see why the for attribute in.cube_left or.cube_right is out of order.

So far, we have explained how to achieve a rotating rubik’s cube round play required the main content and knowledge points, the rest is some piecemeal CSS style to improve the interface, here will not show. After writing this article, I really feel familiar with CSS. But the front end of the main force or JavaScript, may have to continue to in-depth study of JS knowledge,……

PS: Reference for this article

Detailed explanation of Transform (Zhang Xinxu)

Animation,

Thoroughly understand the difference between nTH-child and NTH-of-type

Original source of demo