Search code examples
javascriptwebkitreflow

WebKit Rendering Issue when using overflow: hidden;


I've run into what seems to be a rendering issue in webkit when using overflow: hidden; on a child div and then increasing the height of a parent div using javascript. I've boiled my issue down to the following sample code.

Create a page from this source and then render in a WebKit browser (Safari, Chrome). Click on the "Expand" button and you will see that the divs that have overflow: hidden; set and should now be displayed based on the expanded parent div height don't show up. In Gecko (Firefox) and Trident (ID) browsers this works fine.

Any ideas or suggestions for work arounds? Basically, I want to hand build a table of divs that contain text within a parent div and I don't want the text to wrap or extend beyond the div boundaries. I need to be able to adjust the height of the parent div based on other things happening on the page.

Thanks! Bart

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Language" content="en-us" />

<style type="text/css">

    #test_container {
        width: 540px;
    }

    .column_allow_overflow {
        float: left;
        width: 100px;
        height: 16px;
        margin-left: 4px;
        padding: 3px;
    }

    .column_no_overflow {
        float: left;
        width: 100px;
        height: 16px;
        margin-left: 4px;
        padding: 3px;
        overflow: hidden;
    }

    .background {
        background-color: #444444;
        color: #e5e5e5;
    }

    .data_row {
        height: 22px;
        width: 100%;
        padding-bottom: 22px;
        background-color: #cccccc;
    }

    #expand_container {
        overflow:scroll;
        overflow-x: hidden;
        -ms-overflow-x: hidden;
        height: 100px;
        width: 100%;
        background-color: #cccccc;
    }



</style>

</head>
<body>

<div id="test_container">
<div class="data_row background">
    <button type="button" id="expand_button" onclick="expand();">Expand</button>
</div>
<div id="expand_container">
    <div class="data_row background">
        <div class="column_allow_overflow background">
            Overflow allowed
        </div>
        <div class="column_no_overflow background">
            Overflow NOT allowed
        </div>
        <div class="column_allow_overflow background">
            Overflow allowed
        </div>
        <div class="column_no_overflow background">
            Overflow NOT allowed
        </div>
    </div>
    <div class="data_row background">
        <div class="column_allow_overflow background">
            Overflow allowed
        </div>
        <div class="column_no_overflow background">
            Overflow NOT allowed
        </div>
        <div class="column_allow_overflow background">
            Overflow allowed
        </div>
        <div class="column_no_overflow background">
            Overflow NOT allowed
        </div>
    </div>
    <div class="data_row background">
        <div class="column_allow_overflow background">
            Overflow allowed
        </div>
        <div class="column_no_overflow background">
            Overflow NOT allowed
        </div>
        <div class="column_allow_overflow background">
            Overflow allowed
        </div>
        <div class="column_no_overflow background">
            Overflow NOT allowed
        </div>
    </div>
    <div class="data_row background">
        <div class="column_allow_overflow background">
            Overflow allowed
        </div>
        <div class="column_no_overflow background">
            Overflow NOT allowed
        </div>
        <div class="column_allow_overflow background">
            Overflow allowed
        </div>
        <div class="column_no_overflow background">
            Overflow NOT allowed
        </div>
    </div>
    <div class="data_row background">
        <div class="column_allow_overflow background">
            Overflow allowed
        </div>
        <div class="column_no_overflow background">
            Overflow NOT allowed
        </div>
        <div class="column_allow_overflow background">
            Overflow allowed
        </div>
        <div class="column_no_overflow background">
            Overflow NOT allowed
        </div>
    </div>
</div>  
</div>  

<script>

var expand = function (e) {
    var button = document.getElementById('expand_button');
    var expand_container = document.getElementById('expand_container');

    button.onclick = contract;

    expand_container.style.height = '160px';
    button.innerHTML = "Contract";
};

var contract = function (e) {
    var button = document.getElementById('expand_button');
    var expand_container = document.getElementById('expand_container');

    button.onclick = expand;

    expand_container.style.height = '100px';

    button.innerHTML = "Expand";
};                  

</script>

</body>
</html>

Solution

  • Edit: Now that I had a bit of time to think about this again, I realized that the stuff I was saying in the original answer is true and all, but this is a reflow issue in the nutshell, since it's only showing up when you increase the height. And since it's a reflow issue, the solution is very simple, add position: relative:

    .data_row { 
        position: relative;
        height: 22px; 
        width: 100%; 
        padding-bottom: 22px; 
        background-color: #cccccc; 
    }
    

    Verified that this works now just fine. I'm going to leave the original answer in tacked for educational purposes.

    I don't really have a good solution for you, but I think your issue is about more than just overflow: hidden. This is a combination of float + overflow: hidden. If you remove floats and, for example, position elements absolutely on the page, your script works fine in WebKit browsers. No issues with overflow. I'm not sure if that's something you want to do though. The problem is that overflow actually, doesn't only control whether your content is going to show if the container is too small, but in conjunction with floats, it also can set the sizes of the containers themselves.

    Here's a very simple example of it:

    <div style="width: 500px; overflow: hidden;">
      <div style="width: 200px; float: left; height: 100%; background-color: red;"></div>
      <div style="width: 200px; float: right; height: 100%; background-color: orange;"></div>
      <div style="background-color: green; overflow: hidden;">aaa</div>
    <div>
    

    Setting overflow, strangely enough, is working as float clearing. It doesn’t clear the float at the element, it self-clears. This means that the element with overflow applied (auto or hidden), will extend as large as it needs to encompass child elements inside that are floated (instead of collapsing), assuming that the height isn’t declared.

    I think because of that, you are having issues with your design.

    I suggest you use display: table-cell, if all of the items are supposed to be equal height, table layout if you are not div purist, or absolute positioning.

    P.S. Sorry, it probably should've been a comment instead of the answer, since I don't really provide a good solution, but it was too long for a comment.