13

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.

Etheryte
  • 24,589
  • 11
  • 71
  • 116
  • what about setting the parent element to overflow: hidden on click? I'm on the same version of Chrome on OS X and am unable to reproduce the issue in your jsfiddle. – Aweary Dec 14 '14 at 22:37
  • @Aweary That's something I'm looking to avoid since my content will be placed in DOM I don't control. While that would probably work as a workaround, it doesn't practically solve nor explain the issue. – Etheryte Dec 14 '14 at 22:38
  • I'm unable to reproduce the issue in Chrome 39.0.2171.95 on OS X 10.10. Do you possibly have any extensions that may be interfering? – Aweary Dec 14 '14 at 22:40
  • I'm running a default Chrome installation with no extensions. – Etheryte Dec 14 '14 at 22:41
  • Does the issue occur in the Jsfiddle for you as well? – Aweary Dec 14 '14 at 22:42
  • The issue occurs both in Jsfiddle and the Stack snippet. – Etheryte Dec 14 '14 at 22:43
  • I've updated the question with some further browser tests. The issue is present in Chrome both on Windows and OS X. – Etheryte Dec 14 '14 at 23:11
  • 1
    I was able to reproduce it on my lab Mac (OS X 10.10) running Chrome (same version) as well as Safari 8. Not sure why my portable isn't having the issue. – Aweary Dec 14 '14 at 23:19
  • 1
    Tested in Firefox 34.0.1 on Windows and the problem does not occur. Tested in Opera 26.0.1656.32 on Windows and the problem occurs. Tested in Safari 5.1.7 on Windows and the problem occurs. Judging from all this testing, it looks like it is specific to Webkit. Non-Webkit browsers don't have the problem. – TylerH Dec 14 '14 at 23:26
  • Another workaround could be to resize your content to something smaller (180x80) and then resize it back up to 200x100. At least that way you don't need to touch the parent div. – ippi Dec 15 '14 at 05:44
  • @ippi That won't work for reasons similar to hiding/showing not solving the problem, a redraw is not triggered since the browser optimizes such operations. However, being reminded of this fact offered a possible solution for me, I'll write an answer in a moment, thanks. – Etheryte Dec 15 '14 at 06:26
  • I'm able to reproduce it on chrome V39.0.2171.65 Ubuntu – maioman Dec 25 '14 at 23:45

4 Answers4

5

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.

Etheryte
  • 24,589
  • 11
  • 71
  • 116
  • 1
    This is correct. You need to [trigger a reflow](http://stackoverflow.com/q/510213/87015). You can use jQuery hide/offset/show functions. – Salman A Dec 23 '14 at 11:19
  • @SalmanA Thanks for the link, it explains exactly _why_ the workaround works. – Etheryte Dec 23 '14 at 11:54
2

Below are three solutions that work around this problem in Chrome.

Solution 1

$('.i').on('click', function() {
    var t = $(this);
    t.css({
        width: '100%',
        height: '100%'
   });
});

Solution 2

$('.i').on('click', function() {
    var t = $(this);
    t.css({
        width : '200px',
        height : '100px',
        zoom : 0.5
   });
    setTimeout(function(){
    t.css({
        zoom : 1
    })}, 1);    
});

Solution 3

Works using animation

$('.i').on('click', function() {
    var t = $(this);
    t.css({
        width: '100%',
        height: '100%',
        '-webkit-animation': 'animate 0.01s, linear'
   });
});

Add to CSS:

/* Chrome, Safari, Opera */
@-webkit-keyframes animate {
    from {width: 180px; height: 100px;}
    to {width: 200px; height: 100px;}
}
Mouser
  • 13,132
  • 3
  • 28
  • 54
  • Nice find. While this is certainly useful, I don't think using percentages is always an option (as this bug can occur in a variety of settings). – Etheryte Dec 21 '14 at 01:03
  • 1
    I believe as others do that this is indeed a bug within Webkit (should be reproducible in Safari too maybe?). When you scale down on of the dimensions by 20 pixels (about the size of one scrollbar) it suddenly fits and both scrollbars disappear. Leaving in one dimension a gap of 20px of course. I've added `box-sizing: border-box` to both div and the problem still occurred. Looks like a bug, displays like a bug, must be a bug. – Mouser Dec 21 '14 at 10:16
  • The problem is reproducible in Safari, that's already documented in the question. – Etheryte Dec 21 '14 at 22:39
  • This doesn't solve the problem as it ends up with the child element being smaller than the parent. – Etheryte Dec 21 '14 at 22:54
  • This is an option I tried myself as well. It works - most of the time - but sometimes the small timeout is not long enough and it takes two clicks to work. This means that on some other systems it might take a lot of iterations to work. I'm looking for something that _always_ works. I don't think increasing the delay arbitrarily is a good solution. – Etheryte Dec 22 '14 at 01:23
  • Bummer I just thought it was brilliant :-). Maybe we could add a JavaScript that rechecks until it detects that it's fitting inside the box. Will try to fiddle this. – Mouser Dec 22 '14 at 01:30
  • @Nit tried another approach. Used the animation CSS3 technique. It's only doing this on Webkit installations. I have not tested this thoroughly, but it looks promising. – Mouser Dec 22 '14 at 02:20
-1

To remove scrollbar, you need to redraw parent $('.c') element. But simple hide (style="display:none;"), and then show (style="display:block;") has no effect at all. By updating property of overflow, you need to check everytime what width and hight you are updating and as based on conditions, you have to change value of overflow property.

Try Below Code

$('.i').on('click', function() {
    var t = $(this);
    t.css({
        width: 200,
        height: 100
    })

    $('.c').slideUp(0).slideDown(0); // added
});

I tried jquery slideUp() and slideDown() methods with value 0. Its working fine on windows chrome and safari. I hope it will also work on Mac's browser. FYI : It is also working fine with jquery hide() and show() methods with value 0.

Shyam
  • 782
  • 5
  • 12
  • Please read the question in full before answering. I'm looking for a solution that doesn't address the parent. – Etheryte Dec 26 '14 at 12:11
-3

From all the browser testing it seems that this issue is reproducible and isolated to webkit-based browsers.

I recommend seeing if there is an open ticket with webkit, or filing a bug report: https://bugs.webkit.org/

This old ticket seems to be related to your issue. Outside of manipulating the parent element (which you stated was not practical), I'm not sure there are any workarounds.

Aweary
  • 2,302
  • 17
  • 26