2010-11-11 3 views
2

Я столкнулся с тем, что кажется проблемой рендеринга в webkit при использовании overflow: hidden; на дочернем div, а затем увеличивая высоту родительского div с помощью javascript. Я отбросил свою проблему до следующего образца кода.WebKit Rendering Проблема при использовании переполнения: скрыта;

Создайте страницу из этого источника, а затем выполните рендеринг в браузере WebKit (Safari, Chrome). Нажмите кнопку «Развернуть», и вы увидите, что divs, которые имеют overflow: hidden; и теперь должны отображаться на основе расширенной родительской высоты div, которые не отображаются. В браузерах Gecko (Firefox) и Trident (ID) это отлично работает.

Любые идеи или предложения по работе вокруг? В принципе, я хочу создать таблицу divs, содержащую текст в родительском 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> 
+0

Вместо того, чтобы писать много кода. Используйте JQuery slideUp() и slideDown() или slideToggle() в вашем случае – zod

+1

Я действительно использую YUI3 для моего реального приложения, но я хотел снять все это для этого примера ванили. Такая же проблема возникает при использовании YUI, поэтому я не думаю, что это имеет какое-либо отношение к той библиотеке JS, которую я использую или не использую. Если вы можете создать пример jquery, который работает, это было бы здорово! –

+0

Что вы подразумеваете под «allow overflow»? –

ответ

1

Edit: Теперь, когда у меня было немного времени, чтобы снова думать об этом, я понял, что материал, который я говорил в первоначальном ответе верно и все, но это вопрос переформатирования в в двух словах, поскольку он появляется только при увеличении высоты. А так как это вопрос переформатирования, решение очень простое, добавить позицию: относительная:

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

Установка переполнения, как ни странно, работает в качестве поплавка очистки. Он не очищает float от элемента, он самоочищается. Это означает, что элемент с переполнением, примененный (автоматический или скрытый), будет расширяться настолько, насколько это необходимо, чтобы охватить дочерние элементы внутри, которые плавают (вместо свертывания), предполагая, что высота не объявлена.

Я думаю, из-за этого у вас возникли проблемы с вашим дизайном.

Я предлагаю вам использовать display: table-cell, если все элементы должны быть одинаковой высоты, расположение таблиц, если вы не div purist или абсолютное позиционирование.

P.S. Извините, скорее всего, это был комментарий вместо ответа, так как я действительно не предлагаю хорошее решение, но это слишком долго для комментария.

+0

Ilya, ваше предложение, чтобы добавить позицию: relative; к родительскому div отлично поработали. В результате этой проблемы я смотрел глубже в процесс оплавления для разных браузеров. Я не видел никакой другой информации, указывающей, что добавление позиции: relative; будет иметь этот эффект. Мне просто интересно, как вы это знаете? –

+0

По правде говоря, я никогда не читал его нигде, это просто опыт. Я работал над некоторыми действительно большими сайтами, и проблемы с оплатой часто встречаются в IE6/7. Поэтому, пробовав много разных вещей, я понял, что установочная позиция: относительная на одном из родительских элементов в большинстве случаев заставляет браузер полностью пересчитывать пересчеты детей. Это самый простой способ, другие способы включают JS-код для изменения одного из атрибутов, вызывающих оплату (например, ширина, высота, отображение, положение, hasLayout и т. Д.). –

0

Мне удалось найти немного уродливое обходное решение, которое исправляет его (примечание: возможно, пропустить и на дно .... я придумал лучшее решение). Внутри элемента expand_container я добавил еще один div, содержащий другие элементы.В функциях расширения и контракта я удаляю этот элемент из его родителя (expand_container), размер expand_container и затем добавляю его обратно. Этот вопрос больше не возникает.

<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"; 
}; 

и т.д ...

Edit:

FYI, если вы не хотите, чтобы изменить структуру 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 равно нулю):

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); 
+0

Rob, спасибо за ваше предложение. Я иду с решением Илья, потому что он чище. Но еще раз спасибо за то, что нашли время для работы над этой проблемой! –

+0

Прохладный, да, добавление позиции: относительный, конечно, проще ... было интересным упражнением для учебы в любом случае :) – rob

0

Я слишком близко к врезаться, чтобы скопировать-вставить-тестировать свой код в это время ночи (ну, это ночь, где я), но при условии, что ваша проблема в том, что потомки элементы данного элемента, содержащего не оплавления правильно, если вы измените соответствующий стиль, попробуйте также добавление:

expand_container.className = expand_container.className; 

сразу после изменения стиля. Похоже, он ничего не должен делать, но в каждом браузере, который я тестировал, он заставляет браузер оплатить контейнер и все его содержимое, что должно исправить.

Вы также можете сообщить об этом как об ошибке в http://bugs.webkit.org/, если это не a known bug.

+0

интересный .... но я попробовал, и он не работает в этом случае. – rob

+0

Это было первое, что я пробовал, но похоже, что это не проблема с оплатой в здравом смысле этого слова. Похоже, что это оптимизация в коде обновления WebKit, поэтому вытесняете незначительное исправление, например, добавление/удаление класса или отображение: нет и т. Д.не работает, он заставляет перерасчет пересчета, но он выходит точно так же. Позиция: относительная по родительской, тем не менее, вызывает пересчет пересчета с использованием другого алгоритма. –

Смежные вопросы