Jack Averill
Jack Averill

Reputation: 841

Transitions won't work when transform:translate3d combined with opacity

On my website I have a second header that drifts down from the top when the user scrolls down the page. The original header remains absolutely positioned at the top and is scrolled out of sight as the second slides down.

Due to the Google Chrome bounce scroll effect, if the user scrolls up when the browser is already at the top of the page, they're able to see the second header hanging around outside the document. This looks very strange, and it only happens in Chrome.

I've been trying to make the second header invisible when the user scrolls back to the top and it slides back out of view. I have been attempting to do this with an opacity value of 0 set with an ease value. The problem is, I am using transform:translate3d to animate the slide-up / slide-down effect, and I can't get both opacity and transform to work in the same transition rule.

Ideally I'd like the following to work, but it won't for some reason.

.hidden-header {
  position:fixed;
  transform:translate3d(0,-100%,0);
  background-color:red;
  width:100%;
  height:55px;
  opacity:0;
  transition: translate 0.3s, opacity 0s ease .3s;
}

body.header-dropdown .hidden-header {
  transform:translate3d(0,0,0);
  opacity:1;
  transition: translate .5s, opacity 0s;
}

Here is a jsFiddle to show you what I mean – https://jsfiddle.net/wbmm0kL7/2/

At the moment I have had to set it to transition: all .3s which means that the opacity fades in and out as well, which I want to avoid.

Here is a picture of my website with the problem on Chrome I am trying to solve. Notice that the second header and the nav menu are visible when scrolling against the edge of the viewport/document.

enter image description here

Here is the rest of my code:

HTML

  <header class="header">REGULAR HEADER</header>
  <div class="transform-container">
      <div class="hidden-header">HIDDEN HEADER (SLIDES DOWN ON SCROLL)</div>
  </div>

  <div class="content"></div>

</div>

CSS html, body { height:100%; width:100%; margin:0; padding:0; }

.wrapper {
  background-color:orange;
  min-height:100%;
}

.header {
  position:absolute;
  width:100%;
  height:55px;
  background-color:pink;
}

.hidden-header {
  position:fixed;
  transform:translate3d(0,-100%,0);
  background-color:red;
  width:100%;
  height:55px;
  opacity:0;
  transition: all .3s;
}

body.header-dropdown .hidden-header {
  transform:translate3d(0,0,0);
  opacity:1;
  transition: all .5s;
}

.content {
  height:2000px;
}

jQuery jQuery(document).ready(function($) {

   $(window).scroll(function() {

        if ($(this).scrollTop() > 200) {

            $('body').addClass('header-dropdown');

        } else {

            $('body').removeClass('header-dropdown');

        }       

    });     

});

Upvotes: 1

Views: 2147

Answers (1)

Terry
Terry

Reputation: 66123

As per my comment, you have a typo in your CSS transitions rule. You cannot transition individual transform components. Instead, use transition: transform 0.5s; for example.

To achieve the effect of the hidden header appearing immediately, you set the transition duration of opacity to 0s when .header-dropdown is added. To achieve the effect of the hidden header hiding after the transform is done transitioning, you set the transition delay of opacity to the transition duration used:

.hidden-header {
  position:fixed;
  transform:translate3d(0,-100%,0);
  background-color:red;
  width:100%;
  height:55px;
  /* Delay opacity transition when returning to ground state */
  transition: transform 0.5s, opacity 0s 0.5s;
  opacity: 0;
}

body.header-dropdown .hidden-header {
  transform:translate3d(0,0,0);
  opacity: 1;
  transition: transform 0.5s 0s, opacity 0s;
}

See your fixed fiddle here: https://jsfiddle.net/teddyrised/wbmm0kL7/3/

Note that the first numeric value of the transition shorthand is always the transition-duration, while the second numeric value is the transition-delay

Upvotes: 1

Related Questions