Вопрос

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.

Это было полезно?

Решение

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.

Другие советы

Wow so I thought that there surely had to be a way to do this without having to re-write the scale and translateY properties for every keyframe animation. I tried several different things but I wasn't able to get the results you wanted. It almost seems as though transform should be able to take on more parameters without overwriting the old ones if the parameters are new.

I know you said you don't want to use LESS/SASS as it isn't technically DRY but if you are looking to code in one place and have it update everywhere I would recommend that. I would consider it DRY since you aren't repeating yourself (even though the code is). I can't think of any other way to get what you want.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top