Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create DRY CSS when using transform & keyframes

Tags:

css

keyframe

I'm trying to achieve DRY CSS code when using transform in combination with keyframes. Let's say I've got the following:

HTML

<div id="box"></div>

CSS

#box {
    width:300px;
    height:300px;
    background-color:red;

    animation: animate 5s;
    animation-iteration-count: infinite;
    animation-direction: alternate;
    animation-timing-function: ease-in-out;
}
@keyframes animate {
    from {
        transform: scale(0.8) translateY(100px) rotate(10deg);
    }
    to {
        transform: scale(0.8) translateY(100px) rotate(-10deg);
    }
}

JSFiddle example.

How can I prevent doing the scale(0.8) and translateY(100px) inside the animation? I only want it to be rotated back and forth, without having to apply these properties inside transform for each step. Here, only two steps are used (from and to), but if multiple steps are used (for example with 0%, 20%, 40%, 60%, 80%, 100%) it would mean a lot of repeated code. As you can imagine, this isn't very good when changes will appear later.

Ultimately, I'm looking for something like this (which isn't possible, since the transform property will get overridden):

#box {
    transform: scale(0.8) translateY(100px);
}

@keyframes animate {
    from {
        transform: rotate(10deg);
    }
    to {
        transform: rotate(-10deg);
    }
}

Is this even possible?

Ps. I'm not looking for an answer where you would change the width/height to scale and/or change the margin/top property to translate. Also nothing with LESS/SASS to make the values easy to change, since it would still result in duplicated code.

like image 517
MarcoK Avatar asked Jan 31 '26 04:01

MarcoK


1 Answers

I put together two options for you- jsFiddle

Option 1- Not DRY but a little more condensed:

 #box {
        width:300px;
        height:300px;
        background:red;
        animation: animate 1s ease-in-out 0s infinite alternate;
    }
    @keyframes animate {
        from {
            transform: scale(0.8) translateY(100px) rotate(10deg);
        }
        to {
            transform: scale(0.8) translateY(100px) rotate(-10deg);
        }
    }

Option 2- Technically DRY, but not necessarily "better"

<div id="option2">
    <div id="box2"></div>
</div>

#option2{
    transform: scale(0.8) translateY(100px);
}
#box2 {
    width:300px;
    height:300px;
    background-color:blue;
    animation: animate2 6s ease-in-out 0s infinite alternate;
}
@keyframes animate2 {
    0%, 40%, 80% {
        transform: rotate(10deg);
    }
    20%, 60%, 100% {
        transform: rotate(-10deg);
    }
}

I would guess that using Option 2 may be worth it, if you're using a much more complex animation, but I'm not sure if just wrapping it in a containing div and scaling / translating the containing div would offer any real benefit on a small scale.

like image 149
apaul Avatar answered Feb 03 '26 13:02

apaul



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!