There are many effects we can create with CSS transforms. In this guide I will show how to create illusion of 3D space with transform:translate()

Final result (hover over buttons):

Full video guide here: https://www.youtube.com/watch?v=gcFbqw-YLwA&feature=youtu.be

  1. 1) Create basic markup for button in HTML (we will use the <span> elements as layers in our animation) …
<div class="button">
            <span></span>
            <span></span>
            <span><i class="fab fa-html5"></i></span>
            <span></span>
</div>

… and style it with CSS

.button {
            display: block;
            position: relative;
            width: 50px;
            height: 50px;
            background-color: #f5b0d6;
            transition: .2s;
 }

Optional: use https://fontawesome.com/ for icon, to get it to work you need to dowload SVG locally or link CDN in the document head. Position it in the center with the usual absolute positioning trick and give it white color when the parent ‘.button’ <div> is hovered:

i {
            font-size: 25px;
            position: absolute;
            top: 50%; 
            left: 50%;
            transform: translate(-50%, -50%);
            color: black;
            z-index: 10;
            transition: .2s;
 }
.button:hover i {
            color: white;
}

Absolute positioning method only works if the parent element has been positioned as well.

2) Make the spans the same size as our button and hide them behind with position: absolute

.button span{
            position: absolute;
            top: 0; left: 0;
            width: 100%;
            height: 100%;
            transition: .2s;
            transform: translate(0, 0);
}
transform: translate(x, y) CSS function repositions an element in the horizontal and/or vertical directions. It’s much safer and more performant to use for animations as it doesn’t cause DOM reflow (which you be triggered if you animated top and left values insted). developer.mozilla.org//translate

All of that code and all we have so far is this:

3) Add translate on the button and give it :hover effect:

.button {
            display: block;
            position: relative;
            width: 50px;
            height: 50px;
            background-color: #f5b0d6;
            transform: translate(0, 0) 
                  rotate(0) skew(0);
            transition: .2s;
}
.button:hover {
            transform: translate(-15px, -5px)
                  rotateY(-15deg) skewY(-10deg);
}

rotateY() and skewY() with very specific values create illusion that our flat 2D square turned right in 3D space

4) Select 4th span element and give it border on top and left:

 .button span:nth-of-type(4){
            transform: translate(-4px, -4px);
            transition: .2s;
            z-index: 0;
            opacity: .5;
            border-top: 1px solid black;
            border-left: 1px solid black;
 }
:nth-of-type() CSS pseudo-class matches elements of a given type, based on their position among a group of siblings. It will work only for elements that are on the same level. developer.mozilla.org/:nth-of-type

Our element should like like this on hover:

5) Remember our <span> elements hiding behind the button? Now it’s time to show them. I gave each a different shade of pink and adjusted values of transform:translate to create 3D apprearance:

.button:hover span:nth-of-type(1){
            transform: translate(8px, 4px);
            background-color: #e08dbb;
}
.button:hover span:nth-of-type(2){
            transform: translate(16px, 8px);
            background-color: #bd6093;
}
 .button:hover span:nth-of-type(3){
            transform: translate(24px, 12px);
            background-color: #94386a;
}

6) The fourth <span> is used just for the border, let’s move it to the front but with a delay, after the rest of the elements have already moved:

.button:hover span:nth-of-type(4){
            transform: translate(30px, 16px);
            transition-delay: .2s;
}

7) And now the final trick, we need to make the border animate when it’s pushed forward. This is simple to say but requires a lot of code to do. There is another way to do this, my choice was to create ::before and ::after pseudo elements on the 4th <span>. Notice how the one with border-bottom has width: 0 and the one with border-right has height: 0:

.button span:nth-of-type(4)::before{
            content: '';
            position: absolute;
            width: 0; height: 100%;
            top: 0; left: 0;
            border-bottom: 1px solid black;
            transition: .2s;
}
.button span:nth-of-type(4)::after{
            content: '';
            position: absolute;
            width: 100%; height: 0;
            top: 100%; right: 0;
            border-right: 1px solid black;
            transition: .2s;
}

8) So all we have to do now is animate their width, height and top position. Important part is to start animating the second element after the first animation has finished.

We can use transition-delay to make one animation start right after another. This will look as if we have one border growing around the element.

.button:hover span:nth-of-type(4)::before{
            width: 100%;
            transition-delay: .4s;
        }
.button:hover span:nth-of-type(4)::after{
            height: 100%;
            transition-delay: .6s;
            top:0;
}

And that’s all for now, more animations coming soon. Thank you for reading.

Final HTML:

 <div class="button">
        <span></span>
        <span></span>
        <span><i class="fab fa-css3"></i></span>
        <span></span>
</div>

Final CSS:

.button {
    position: relative;
    width: 50px;
    height: 50px;
    background-color: #f5b0d6;
    transition: .2s;
    transform: translate(0, 0) 
               rotateY(0) skewY(0);
    transition: .2s;
    margin: 0 auto;
}
.button:hover {
    transform: translate(-15px, -5px) 
               rotateY(-15deg) skewY(-10deg);
}
i {
    font-size: 25px;
    position: absolute;
    top: 50%; 
    left: 50%;
    transform: translate(-50%, -50%);
    color: black;
    z-index: 10;
    transition: .2s;
}
.button:hover i {
    color: white;
}
.button span {
    position: absolute;
    top: 0; left: 0;
    width: 100%;
    height: 100%;
    transition: .2s;
    transform: translate(0, 0);
}
.button span:nth-of-type(4) {
    transform: translate(-4px, -4px);
    transition: .2s;
    z-index: 0;
    opacity: .5;
    border-top: 1px solid black;
    border-left: 1px solid black;
}
.button:hover span:nth-of-type(1) {
    transform: translate(8px, 4px);
    background-color: #e08dbb;
}
.button:hover span:nth-of-type(2) {
    transform: translate(16px, 8px);
    background-color: #bd6093;
}
.button:hover span:nth-of-type(3) {
    transform: translate(24px, 12px);
    background-color: #94386a;
}
.button span:nth-of-type(4)::before {
    content: '';
    position: absolute;
    width: 0; height: 100%;
    top: 0; left: 0;
    border-bottom: 1px solid black;
    transition: .2s;
}
.button span:nth-of-type(4)::after {
    content: '';
    position: absolute;
    width: 100%; height: 0;
    top: 100%; left: 0;
    border-right: 1px solid black;
    transition: .2s;
}
.button:hover span:nth-of-type(4)::before {
    width: 100%;
    transition-delay: .4s;
}
.button:hover span:nth-of-type(4)::after {
    height: 100%;
    transition-delay: .6s;
    top: 0;
}
.button:hover span:nth-of-type(4) {
    transform: translate(30px, 16px);
    transition-delay: .2s;
}

Leave a Reply

Your email address will not be published. Required fields are marked *