Почему CSS2. 1 определяет значения переполнения, отличные от "видимых", чтобы установить новый контекст форматирования блока?


в спецификации CSS2.1 спецификаций мандатов, что overflow кроме visible установите новый "контекст форматирования блока". Это кажется мне странным, что свойство, очевидная цель которого-скрыть переполнение, не влияя на макет, на самом деле влияет на макет в значительной степени.

похоже, что значения переполнения, отличные от visible объедините две совершенно несвязанные функции: создается ли BFC и скрыто ли переполнение. Это не похоже на " overflow: hidden совершенно бессмысленно без BFC, потому что поплавки исторически могут переполнять их родительский элемент,скрытие переполнения без изменения макета кажется разумным.

каковы причины этого решения, предполагая, что они известны? Люди, которые работали над спецификацией, описали, почему это было решено?

2 56

2 ответа:

я спросил об этом в списке рассылки от вашего имени; нить можно найти здесь. В общем,это связано с прокруткой контента по большей части:

принципиально, потому что если спецификация этого не сказала, то наличие поплавков пересекается с чем-то, что прокручивается, потребует от браузера перематывать (вокруг вторгающихся поплавков) содержимое прокручиваемого элемента каждый раз, когда он прокручивается. Это технически то, что УСБ 2.0 требуется, но он никогда не был реализован, и это было бы огромной проблемой для скорости прокрутки.

-Дэвид

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

наконец-то это имеет смысл для меня. На самом деле, я собираюсь привести пример здесь, так что надеюсь, что это имеет смысл для вас и всех остальных, кто может быть интересно. Рассмотрим сценарий, включающий два ящика с одинаковой фиксированной высотой и overflow: visible (по умолчанию), из которых первый содержит поплавок, который выходит за пределы высоты своего родителя:

<div>
    <p>...</p>
</div>
<div>
    <p>...</p>
    <p>...</p>
</div>
/* Presentational properties omitted */
div {
    height: 80px;
}

div:first-child:before {
    float: left;
    height: 100px;
    margin: 10px;
    content: 'Float';
}

обратите внимание на сходство один из примеров приведен в 9.5. Второе поле здесь просто показано, что оно переполнено контентом для целей этого ответа.

это нормально, так как контент никогда не будет прокручиваться, но когда overflow имеет значение, отличное от visible, что приводит к тому, что содержимое не только обрезается по границам окна, но и становится прокручиваемым. Если второе поле имеет overflow: auto, вот как это выглядело бы, если бы браузер реализовал оригинал CSS2 spec:

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

загвоздка здесь в том, что браузер должен перемотать содержимое каждый раз, когда он перекрашивает ее в прокрутка. Для браузеров, которые способны к плавной прокрутке на основе пикселей - то есть, все они - я могу понять, почему это будет катастрофой производительности! (И пользовательский опыт тоже.)

но это для того, когда пользователь может прокручивать содержимое, верно? Это имело бы смысл для overflow: auto и overflow: scroll, а как насчет overflow: hidden?

Ну, распространенным заблуждением является то, что контейнер с overflow: hidden просто скрывает содержимое путем отсечения и не может быть прокручен. это не совсем так:

в то время как прокрутка пользовательского интерфейса не предусмотрена, содержимое по-прежнему прокручивается программно, и ряд страниц выполняют именно такую прокрутку (например, установив scrollTop на соответствующем элементе).

Борис

действительно, это то, что было бы похоже, если бы второй ящик был установлен в overflow: hidden а затем прокрутил вниз со следующим JavaScript:

var div = document.getElementsByTagName('div')[1];
div.scrollTop = div.scrollHeight;

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

хотя это было бы не так болезненно для производительности, как если бы прокрутка пользовательского интерфейса была доступна, Я думаю, что они сделали коробки с любойoverflow значение visible генерировать новый BFC в основном для обеспечения согласованности.


и так, это изменение было вызвано в CSS2.1, документально здесь. Теперь, если вы применяете overflow значение visible только для второго окна, что браузер делает, это нажать поле в сторону, чтобы освободить место для поплавка, потому что поле теперь создает новый контекст форматирования блока, который заключает его содержимое, а не течет вокруг поплавка. Это конкретное поведение указано в следующем абзац:

поле границы таблицы, уровень блока замененный элемент или элемент в обычном потоке, который устанавливает новый контекст форматирования блока (например, элемент с "переполнением", отличным от "видимого"), не должен перекрывать поле полей любых поплавков в том же контексте форматирования блока, что и сам элемент. При необходимости реализации должны очистить указанный элемент, поместив его ниже любых предшествующих поплавков, но могут разместить его рядом с такими поплавками, если есть достаточное пространство. Они могут даже сделать поле границы указанного элемента более узким чем определяется раздел 10.3.3. CSS2 не определяет, когда UA может поместить указанный элемент рядом с поплавком или на сколько указанный элемент может стать более узким.

вот как это выглядит с overflow: auto например:

обратите внимание, что нет никакого зазора; если второй ящик имел clear: left или clear: both его бы толкнули вниз, не в сторону, независимо от того, установил ли он свой собственный БФК.

если вы примените overflow: auto к первой коробке вместо этого поплавок обрезается в содержащей его коробке с остальной частью содержимого из-за его фиксированной высоты, которая установлена в 80px в приведенном выше примере кода:

если вы вернете первое поле в height: auto (значение по умолчанию), либо путем переопределения или удалении height: 80px объявление сверху, это потом тянется к высоте поплавок:

это новое в CSS2. 1 также, в том, что элемент height: auto который генерирует новый контекст форматирования блока (т. е. a блокировать форматирование корневого контекста) протянет вертикально к высоте своих поплавков, и не как раз достаточно для того чтобы содержать свое содержание в-потока не похож на регулярную коробку. Изменения задокументированы здесь и здесь. Изменение, приводящее к побочному эффекту о сжатии коробки так, чтобы она не пересекала поплавок, задокументировано здесь.

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

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

в разделе 9.4.1 речь идет о любом элементе блока, который не полностью содержит или не заполняет пространство сдерживания. Например, когда вы плаваете элемент, он больше не заполняет 100% родительского элемента, как это делают элементы in-flow. Встроенные блоки, ячейки таблицы и заголовки таблиц также являются элементами, которые можно изменять по высоте и ширине, но которые не обязательно 100% родителя (да таблица>tr>td-это тот, который заполнит 100% его родителя, но он предназначен для обеспечения нескольких td, поэтому td не учитывается, поскольку он автоматически сжимается для размещения дополнительных td) это также относится к любому переполнению, кроме видимого, потому что он нарушает сдерживание элемента блока.

Так что, если я читаю это правильно, как это работает, раздел 9.4.1 ссылается на элементы блока, которые нарушают сдерживание по умолчанию правила элементов блока, указанные в разделе 9.2.1