Search code examples
cssdelaytransition

How to prevent a transition delay


I have been playing with a CSS transition for a nav menu found at jsfiddle. The same code can be found below:

EDIT: Updated jsfiddle link

CSS:

nav {
    background-color: #337AB7;
    position: relative;
}

nav:after {
    display: table;
    content: '';
    clear: both;
}

nav h1 {
    float: left;
    margin: 0;
}

nav #nav-toggle {
    display: none;
}

nav label[for='nav-toggle']:after {
    float: right;
    display: block;
    padding: .5em;
    margin: .5em;
    width: 4em;
    content: 'Menu';
    text-align: center;
    color: #fff;
    border: 1px solid #fff;
    border-radius: 3px;
}

nav ul {
    float: left;
    display: block;
    margin: 0;
    padding: 0;

    list-style: none;
    width: 100%;
    max-height: 0;
    overflow: hidden;



    transition: max-height 1s ease;
}

nav #nav-toggle:checked ~ ul {
    max-height: 1000px;

    transition: max-height 1s ease;
}

nav #nav-toggle:checked ~ label:after {
    content: 'Close';
    background-color: #fff;
    color: #337AB7;
}

nav li {
    margin: .5em 0;
}

nav a {
    display: block;
    padding: .5em;
    text-decoration: none;
    color: #fff;
}

nav a:hover,
nav a:active,
nav a:focus {
    background-color: #fff;
    color: #337AB7;
}

HTML:

<nav>
   <h1><a href="#">Title</a></h1>
   <input type="checkbox" id="nav-toggle">
   <label for="nav-toggle"></label>
   <ul>
      <li><a href="#">Home</a></li>
      <li><a href="#">About</a></li>
      <li><a href="#">Contact</a></li>
   </ul>
</nav>

The opening transition is working correctly, but when closing the menu there is some kind of delay before the transition actually happens. How do I stop this delay?


Solution

  • The reason your animation is taking so long is because you are transitioning max-height. Even though your end height is only 134px, you're not transitioning that. It's doing the transition for the full 1000px you have max-height set to. This doesn't look like anything is wrong when it expands, but when it closes it is starting at 1000 and counting down. Which looks like it's being delayed, even though it's not. It's just not having an effect on the actual height until it gets to about 134px. If you change it to height and transition that instead the issue is fixed. Just lower your height to a more manageable level.

    You can see the issue when you use height instead of max-height:

    nav {
      background-color: #337AB7;
      position: relative;
    }
    nav:after {
      display: table;
      content: '';
      clear: both;
    }
    nav h1 {
      float: left;
      margin: 0;
    }
    nav #nav-toggle {
      display: none;
    }
    nav label[for='nav-toggle']:after {
      float: right;
      display: block;
      padding: .5em;
      margin: .5em;
      width: 4em;
      content: 'Menu';
      text-align: center;
      color: #fff;
      border: 1px solid #fff;
      border-radius: 3px;
    }
    nav ul {
      float: left;
      display: block;
      margin: 0;
      padding: 0;
      list-style: none;
      width: 100%;
      height: 0;
      overflow: hidden;
      transition: height 1s ease;
    }
    nav #nav-toggle:checked ~ ul {
      height: 1000px;
      transition: height 1s ease;
    }
    nav #nav-toggle:checked ~ label:after {
      content: 'Close';
      background-color: #fff;
      color: #337AB7;
    }
    nav li {
      margin: .5em 0;
    }
    nav a {
      display: block;
      padding: .5em;
      text-decoration: none;
      color: #fff;
    }
    nav a:hover,
    nav a:active,
    nav a:focus {
      background-color: #fff;
      color: #337AB7;
    }
    <nav>
      <h1><a href="#">Title</a></h1>
      <input type="checkbox" id="nav-toggle">
      <label for="nav-toggle"></label>
      <ul>
        <li><a href="#">Home</a>
        </li>
        <li><a href="#">About</a>
        </li>
        <li><a href="#">Contact</a>
        </li>
      </ul>
    </nav>