使用overflow时隐藏的WebKit渲染问题

时间:2010-11-11 20:03:18

标签: javascript webkit reflow

当在子div上使用 overflow:hidden; 然后使用javascript增加父div的高度时,我遇到了似乎是webkit中的渲染问题。我已将问题归结为以下示例代码。

从此源创建页面,然后在WebKit浏览器(Safari,Chrome)中呈现。单击“展开”按钮,您将看到溢出:隐藏; 设置的div现在应该根据展开的父div高度显示而不显示。在Gecko(Firefox)和Trident(ID)浏览器中,这很好用。

有关解决方法的任何想法或建议吗?基本上,我想手工构建一个包含父div中文本的div表,我不希望文本包装或扩展到div边界之外。我需要能够根据页面上发生的其他事情调整父div的高度。

谢谢! 巴特

<!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>

3 个答案:

答案 0 :(得分:1)

编辑:现在我有一点时间再次考虑这个问题,我意识到我在原始答案中所说的内容是真实的,但这只是一个回流问题,因为它只显示当你增加高度时。由于这是一个回流问题,解决方案非常简单,添加位置:relative:

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

已验证此功能现在正常。我将把原来的答案留给教育目的。

我真的没有一个很好的解决方案,但我认为你的问题不仅仅是溢出:隐藏。这是float + overflow:hidden的组合。如果删除浮点数,例如,绝对在页面上定位元素,则您的脚本在WebKit浏览器中可以正常工作。没有溢出问题。我不确定你是否想要这样做。问题是实际上溢出,不仅控制你的内容是否会显示容器是否太小,而且与浮动一起,它也可以设置容器本身的大小。

以下是一个非常简单的例子:

<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>

设置溢出,奇怪的是,它正在作为浮动清除工作。它不会清除元素上的浮动,它会自行清除。这意味着应用溢出的元素(自动或隐藏)将扩展到需要包含浮动内部子元素(而不是折叠)的大小,假设未声明高度。

我认为正因为如此,你的设计存在问题。

我建议您使用display:table-cell,如果所有项目都应该是相等的高度,如果你不是div纯粹的表格布局,或者绝对定位。

P.S。对不起,它可能应该是一个评论而不是答案,因为我没有真正提供一个好的解决方案,但是评论太长了。

答案 1 :(得分:0)

我设法找到一个稍微丑陋的解决方法来修复它(注意:不妨跳到底部......我想出了一个更好的解决方案)。在expand_container元素中,我添加了另一个div,其中包含其他元素。在展开和收缩函数中,我从其父元素(expand_container)中删除该元素,调整expand_container的大小,然后再添加该div。问题不再发生。

<div id="expand_container" >
  <div id="inner_container" style="margin:0; padding:0">  <!-- new element! -->
    <div class="data_row background">
        <div class="column_allow_overflow background">
...

...然后

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

    var inner_container = document.getElementById('inner_container'); // new
    expand_container.removeChild(inner_container); // new
    button.onclick = contract;

    expand_container.style.height = '160px';

    expand_container.appendChild(inner_container); // new
    button.innerHTML = "Contract";
};

等...

编辑:

仅供参考,如果您不想通过添加内部元素来更改dom结构,而是可以将expand_container的所有子项拉出来,然后在调整大小后将它们全部添加回来。例如:

var len = expand_container.childNodes.length, i, a = [];
for (i=len-1; i>=0; i--) 
 a.push(expand_container.removeChild(
      expand_container.childNodes.item(i)));

button.onclick = contract;
expand_container.style.height = '160px';

for (i=len-1; i>=0; i--)
 expand_container.appendChild(a[i]);

如果你有很多元素可能会很慢,但在你的例子中,它就像一个魅力。

编辑2:好的,只想到更好用的东西....删除expand_container并将其添加回同一个地方。再次,工作正常(即使nextSibling为null):

var next = expand_container.nextSibling;
var parent = expand_container.parentNode;
parent.removeChild(expand_container);

button.onclick = contract;
expand_container.style.height = '160px';

parent.insertBefore (expand_container, next);

答案 2 :(得分:0)

我太接近于在晚上的这个时候崩溃复制粘贴测试你的代码(好吧,我现在的晚上),但假设你的问题是给定元素的后代元素不要更改相关样式时无法正确重排,请尝试添加:

expand_container.className = expand_container.className;
样式改变后立即

。看起来它不应该做任何事情,但在我测试的每个浏览器中都会导致浏览器重排容器及其所有内容,这应该可以解决问题。

如果不是http://bugs.webkit.org/,您可能还希望在a known bug上将此报告为错误。