Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webkit bug: Overflow auto triggered after resizing a child element to matching size

I have the following simple set-up:

document.getElementById('inner').addEventListener('click', ({ target }) => {
  target.classList.add('match');
});
#container {
  background: green;
  overflow: auto;
  width: 200px;
  height: 100px;
}

#inner {
  width: 210px;
  height: 110px;
}

#inner.match {
  width: 200px;
  height: 100px;
}
<div id="container">
  <div id="inner"></div>
</div>

Upon clicking the inner element, I'd expect the scrollbars on the parent to disappear since the two elements now have matching sizes. This works as expected in Firefox.
However the container element doesn't lose scrollbars in Chrome as can be seen in the below screenshot:

Sample image

The scrollbars themselves create an offset large enough to create overflowing.
Is this a webkit-specific issue? Is there a cross-browser, reliable solution to this (seemingly trivial) issue?

I'm looking for a solution that doesn't change the parent's properties as my content (#inner) will be placed in DOM I don't have control over.

So far I've tried hiding/showing and/or detaching/reinserting the element at different points of execution, but the problem persists, likely because the operations are simply optimized away.

The issue occurs both in Jsfiddle and in the Stack snippet.

The bug has been filed on Webkit Bugzilla.

like image 955
Etheryte Avatar asked Dec 14 '14 22:12

Etheryte


1 Answers

Update: This issue seems to be fixed in the latest version, I haven't kept track which release specifically though.


A workaround that doesn't involve addressing the parent is to force a browser redraw after the styles are applied.

document.getElementById('inner').addEventListener('click', ({ target }) => {
  target.classList.add('match');
  //Force redraw
  target.style.display='none';
  target.offsetHeight; //Won't work without this
  target.style.display='';
});
#container {
  background: green;
  overflow: auto;
  width: 200px;
  height: 100px;
}

#inner {
  width: 210px;
  height: 110px;
}

#inner.match {
  width: 200px;
  height: 100px;
}
<div id="container">
  <div id="inner"></div>
</div>

I can't guarantee that this is a solution that works consistently (see the linked thread regarding forcing a redraw for possible issues), but at least in this specific case this seems to work through my initial testing.
I've filed a bug with Webkit describing all the above behavior, but until then, this is a viable option.

like image 126
Etheryte Avatar answered Oct 24 '22 12:10

Etheryte