Zakalwe
Zakalwe

Reputation: 232

CSS transition: how to produce this effect (linking transitions)

https://jsfiddle.net/hak1e33n/1/

HTML

<a href="#">
        <div class="contact-button">
            <div class="contact-button-text">
                Linkedin
            </div>
           <div class="block-1b">L</div>
           <div class="block-2b">I</div>
           <div class="block-3b">N</div>
           <div class="block-4b">K</div>
           <div class="block-5b">E</div>
           <div class="block-6b">D</div>
           <div class="block-7b">I</div>
           <div class="block-8b">N</div>
        </div>
        </a>

CSS

.block-1b,
.block-2b,
.block-3b,
.block-4b,
.block-5b,
.block-6b,
.block-7b,
.block-8b {
    color: #fff;
    font-family: 'quicksand', sans-serif;
    text-align: center;
    line-height: 50px;
    width: 20%;
    height: 50px;
    z-index: 1;
    position: absolute;
    top: 0;
    left: 0;
    background-color: #506989;
    transform-origin: top;
    transform: rotateX(-90deg);
    transition: .5s;
}

.contact-button {
    width: 200px;
    height: 50px;
    border: 1px solid #333;
    margin: 0 auto;
    z-index: 2;
    position: relative;
    overflow: hidden;
}

.contact-button-text {
    color: #333;
    font-family: 'quicksand', sans-serif;
    text-align: center;
    line-height: 50px;
    width: 100%;
    height: 50px;
    position: absolute;
    top: 0;
    left: 0;
}




.block-1b {
    width: 25px;
}


.block-2b {
    width: 25px;
    left: 25px;
}


.block-3b {
    width: 25px;
    left: 50px;
}


.block-4b {
    width: 25px;
    left: 75px;
}


.block-5b {
    width: 25px;
    left: 100px;
}


.block-6b {
    width: 25px;
    left: 125px;
}


.block-7b {
    width: 25px;
    left: 150px;
}

.block-8b {
  width: 25px;
  left: 175px;
}
.contact-button:hover .block-1b {
    transform: translateY(0);
    background-color: #6b8fbb; 
}

.contact-button:hover .block-2b {
    transform: translateY(0);
    background-color: #6b8fbb; 
    transition-delay: .1s;
}

.contact-button:hover .block-3b {
     transform: translateY(0);
     background-color: #6b8fbb; 
     transition-delay: .2s;
}

.contact-button:hover .block-4b {
     transform: translateY(0);
     background-color: #6b8fbb; 
     transition-delay: .3s;
}

.contact-button:hover .block-5b {
     transform: translateY(0);
     background-color: #6b8fbb; 
     transition-delay: .4s;
}

.contact-button:hover .block-6b {
     transform: translateY(0);
     background-color: #6b8fbb; 
     transition-delay: .5s;
}

.contact-button:hover .block-7b {
     transform: translateY(0);
     background-color: #6b8fbb; 
     transition-delay: .6s;
}

.contact-button:hover .block-8b {
     transform: translateY(0);
     background-color: #6b8fbb; 
     transition-delay: .7s;
}

This is the animation I currently have for my button. I'd like the effect to swing like a catflap, so it swings forward, backwards, then forwards again to finally rest.

You can see the effect I want to produce here: https://jsfiddle.net/6e9jzhtw/


I'd like to produce this effect with transitions rather than animations. Is there anyway to link transitions together on a single element? So on hover one of the letter tiles swings:

-45deg 45deg 0deg

If not I know I can use jquery to reset the animation so I can hover on it again and see the effect after it's played once, but I'd really like to make this a transition effect if possible.

Thanks.

Upvotes: 1

Views: 253

Answers (1)

Rogier Spieker
Rogier Spieker

Reputation: 4187

Not sure why you say you wish to use only transitions instead of animations, as both do other things and as far as I understand your question correctly, you want both.

A transition is used to control the speed when changing (specific, not all) css properties.

This is what you seem to want for the :hover on/off to happen

An animation is merely a bunch of prepared transitions using a predefined pattern, thus allowing you more complex intermediate states.

Now, why did I say you need both? You seem to want be able to start/stop the effect on :hover of the main (button) element, usually this is the perfect candidate for a transition. The 'catflap' is a more complex sequence of states, so this (by design) qualifies as an animation.

In order to have these two cooperate, you need to define a "state as you want it with and without :hover", so you'd have something like

.contact-button [class*=block-] {
    /* .. removed style properties for clarity */
    transform: rotateX(-90deg);
    transition: transform .2s ease-in-out,
                background-color .3s ease-out;
}
.contact-button:hover [class*=block-] {
    transform: rotateX(0);
    background-color: #6b8fbb;
}

NOTE: I am a very lazy developer, and instead of defining .block-1b, .., .block-8b I simply said all elements with a like containing block-, this kind of attribute selectors is know to be slow (yet it is probably very low on the lists of concerns for this demo).

This will give a very basic transition enabling the basic "falling down" effect. So now we need to delay it a bit for each block-.

.contact-button [class*=block-]:nth-of-type(8n+1) {
   /* intentionally left "blank" */
}

.contact-button [class*=block-]:nth-of-type(8n+2) {
    transition-delay: .05s;
}

/* ...etc up to nth-of-type(8n+8) */

While leaving the transition-delay of the first element to be the default (which is no delay), we need to influence all the others, I like to use the nth-child and nth-of-type for this.

For clarity I've renamed the first element from <div> to <span> for the sole purpose of being able to use the nth-of-type (which matches the element type)

ok, so now the transition is done on :hover and each tile will "fall" slightly after the one before.

Then we need to address the 'catflap'. As I stated above, this is a candidate for an animation (as you already found out), so we need to add the animation. I'd like to start the animation once I know the transition is complete, unfortunately, this must be done by hand (or javascript, which I'm trying to keep out of the equation, as you threatened to use jQuery..).

We need to pick a delay which feels right, to me it felt like .15s (150ms) was a good value, you may feel differently about it.

So, we add animation-delay to all of the nth-of-type rules

.contact-button [class*=block-]:nth-of-type(8n+1) {
    animation-delay: .15s;
}

.contact-button [class*=block-]:nth-of-type(8n+2) {
    transition-delay: .05s;
    animation-delay: .2s;
}

/* ...etc up to nth-of-type(8n+8) */

This is getting close, except for the jerking effect when the :hover is off mid-animation. This can be fixed by having the animation paused by default and only running while hovering, like so

.contact-button [class*=block-] {
    /* .. removed style properties for clarity */
    transform: rotateX(-90deg);
    transition: transform .2s ease-in-out,
                background-color .3s ease-out;
    animation-play-state: paused;
}

.contact-button:hover [class*=block-] {
    transform: rotateX(0);
    background-color: #6b8fbb;
    animation: catflap 2s;
    animation-play-state: running;
}

All of this combined leads to the following demo. In which I've also taken the liberty to make the 'catflap' feel a little more natural by making it sway less each turn.


By now you probably wondering why I first claimed to be a lazy developer and yet wrote such elaborate css selectors. Well, truth be told, I'd use something like .contact-button:hover :nth-of-type(8n+3) and never bother with classes as I would not control the animation/transition in those rules. I'd still use a class to control these, but the same one for all, e.g. .contact-button:hover .block, which will suffice nicely.

Upvotes: 1

Related Questions