CSS3 Transition: Different transition for *IN* and *OUT* (or returning from transitioned state)

44,347

Here is a simplified test case:

div {
    background: blue;
    opacity: 0;
    transition: opacity 2s ease-in-out;
}

div.loading {
    opacity: 1;
    background: red;
    transition: opacity 2s ease-in-out, background 1s ease-in;
}

Notice how the opacity fades the same in and out, but the background only fades in, and immediately turns blue on fade out.

I used :hover as an example, but it should work the same when adding and removing classes with JavaScript.

Demo

If you'd like a more specific example please provide a reduced test case on dabblet or Jsfiddle.

Share:
44,347

Related videos on Youtube

HandiworkNYC.com
Author by

HandiworkNYC.com

I make custom WordPress themes http://handiworknyc.com

Updated on April 29, 2020

Comments

  • HandiworkNYC.com
    HandiworkNYC.com about 4 years

    Original Question... updated working code below:

    I have a loading image which comes up during an ajax load event. The image shows/hides by adding or removing a "loading" class to the body element. Currently, the loading image animates background-size from 0 to 100%, and fades in the opacity (vice versa for the 'return' transition).

    What I want to accomplish, though, is to have the background-size transition happen instantly (not transition) on the fade out, so:

    • Fade in: opacity from 0 to 1 in .2s, background size from 0 to 100% in .2s
    • Fade out: opacity from 1 to 0 in .2s, background size from 100% to 0 should happen instantly

      #loader {
          width: 100%;
          height: 100%;
          position: fixed;
          top: 0;
          left: 0;
          z-index: -1;
          opacity: 0;
          -moz-opacity: 0;
          transition: all .2s ease-in-out
      }
      
      
      #loader .image {
          width: 400px;
          height: 138px;
          display: block;
          position: absolute;
          z-index: 2000; 
          top: 50%; 
          left: 50%; 
          margin: 0;
          background: url(assets/images/loading.png) no-repeat;
          background-size: 0 0;
          transition: all .2s ease-in-out;
          -webkit-animation: pulse 400ms ease-out infinite alternate;
          -moz-animation: pulse 400ms ease-out infinite alternate;
          -o-animation: pulse 400ms ease-out infinite alternate;
          animation: pulse 400ms ease-out infinite alternate
      }
      
      .loading #loader {z-index: 1000; background-color: rgba(255,255,255,.7)}
      
      .loading #loader .image {
          background-size: 100% 100%; 
          margin: -69px 0 0 -200px;
          transition: opacity .2s ease-in-out
      }
      

    I've changed transition property for this selector .loading #loader .image to "opacity" rather than "all", but it still performs the background-size transition.

    Does anyone know how to achieve the different fade in and fade out transitions described above with css3? Thanks!


    Updated Working Code

    The issue was breaking out the individual properties (margin, background) into a comma separated list. I believe using transition: all will prevent you from being able to do different IN and OUT transitions.

    #loader {
        width: 100%;
        height: 100%;
        position: fixed;
        top: 0;
        left: 0;
        z-index: -1;
        opacity: 0;
        -moz-opacity: 0;
        .transition(opacity,.4s);
    }
    
    #loader .image {
        width: 400px;
        height: 138px;
        display: block;
        position: absolute;
        z-index: 2000; 
        top: 50%; 
        left: 50%; 
        margin: 0;
        background: url(assets/images/loading.png) no-repeat;
        background-size: 0 0;
    
        -webkit-transition: margin .4s ease-in-out;
        -moz-transition: margin .4s ease-in-out;
        -o-transition: margin .4s ease-in-out;
        -ms-transition: margin .4s ease-in-out;
        transition: margin .4s ease-in-out;
    
        -webkit-animation: pulse 400ms ease-out infinite alternate;
        -moz-animation: pulse 400ms ease-out infinite alternate;
        -o-animation: pulse 400ms ease-out infinite alternate;
        animation: pulse 400ms ease-out infinite alternate
    }
    
    .loading #loader {z-index: 1000; background-color: rgba(255,255,255,.7)}
    
    .loading #loader .image {
        background-size: 100% 100%; 
        margin: -69px 0 0 -200px;
    
        -webkit-transition: background .4s ease-in-out, margin .4s ease-in-out;
        -moz-transition: background .4s ease-in-out, margin .4s ease-in-out;
        -o-transition: background .4s ease-in-out, margin .4s ease-in-out;
        -ms-transition: background .4s ease-in-out, margin .4s ease-in-out;
        transition: background .4s ease-in-out, margin .4s ease-in-out;
    }
    
  • ThinkingStiff
    ThinkingStiff over 12 years
    +1 Yes. This is the right way. Break out into classes and add/remove as needed. There are some issues with adding classes in Javascript with transitions that I go over here: stackoverflow.com/a/8213003/918414
  • HandiworkNYC.com
    HandiworkNYC.com over 12 years
    Thanks! using transition: all was the issue. I had to break out the transition properties separated by commas like you had. I've updated my working code in the answer.
  • Mark
    Mark over 2 years
    Just to be clear - the "ease-in" transition is not what is causing a fade in and snap out. It's that the transition on background only applies on hover. Once the hover is removed there is no longer a transition on the background property at all.