Kevin M
Kevin M

Reputation: 1312

CSS shake/jitter bug in chrome? transition of width on centered div

I have a centered div layer using margin: 0 auto, with a fixed width of width: 1000px, which will go width: 100% when starting to scroll down, along with a transition to make it look nice.

The problem is, that some of the content starts to shake and jitter during the transition. I say some of the content, because for example images shake, while H1 texts does not This only happens in Chrome and Edge. (tested on windows 10).

Doing some research, I found Chrome had known issues in the past with transitions when not using hardware acceleration, resulting in flickering. From what I understand, this has been solved by Google over 2 years ago.

I tried implementing all sorts of workarounds, trying to trigger a hardware acceleration, but nothing worked.

From what I learned so far, this jittering / shaking issue only happens when a div layer is centered using margin: 0 auto with a fixed width and that element is then transitioned into width: 100%.

A strange issue, when re-creating the demo code inside of JSFiddle, I can’t seem to always reproduce it on my system.

Here is the JSFiddle: https://jsfiddle.net/aobrien/vc4n8ecy/

Just scroll down and notice how the chrome logo shakes. You might have to scroll up and down to noticed it, depending on your screen size.

Note: This only seems to be visible when you have a screen width of around 1700px or higher, so make sure your browser is in full width. Scaling the browser window to 80% also triggers the issue.

//jQuery to add sticky class when scrolling

$(window).scroll(function() {
  if ($(this).scrollTop() > 1) {
    $('.header').addClass("sticky");
  } else {
    $('.header').removeClass("sticky");
  }

});
body {
  height: 2000px;
}

.header {
  background: #335C7D;
  margin: 0 auto;
  width: 1000px;
  transition: width .6s ease;
  height: 200px;
}

.sticky {
  position: fixed;
  width: 100%;
  left: 0;
  right: 0;
  will-change: width;
}

.wrap {
  width: 1000px;
  margin: 0 auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="header">
    <div class="wrap">
      <img src="https://i.sstatic.net/iaYsc.png" />
      <h1> Hello World.</h1>
    </div>
  </div>
</div>

This seems to be very easy and straight forward way of achieving a full width sticky menu with transition.

Could it be that using margin: 0 auto along with a width change, results in problems to recalculate the centered div layer?

So far, all my attempts to solve this or find a workaround, have failed.

Upvotes: 4

Views: 4343

Answers (1)

Kevin M
Kevin M

Reputation: 1312

It seems I found one solution.

Adding display: table; to the element that uses the transition property, seems to remove the shaking.

//jQuery to add sticky class when scrolling

$(window).scroll(function() {
  if ($(this).scrollTop() > 1) {
    $('.header').addClass("sticky");
  } else {
    $('.header').removeClass("sticky");
  }

});
body {
  height: 2000px;
}

.header {
  background: #335C7D;
  margin: 0 auto;
  width: 1000px;
  transition: width .6s ease;
  height: 200px;
  display: table; /* this seems to fix it */
}

.sticky {
  position: fixed;
  width: 100%;
  left: 0;
  right: 0;
  will-change: width;
}

.wrap {
  width: 1000px;
  margin: 0 auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="header">
    <div class="wrap">
      <img src="https://i.sstatic.net/iaYsc.png" />
      <h1> Hello World.</h1>
    </div>
  </div>
</div>

Upvotes: 3

Related Questions