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

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

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

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

2 ответа

Решение

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

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

-Давид

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

Наконец это имеет смысл для меня. На самом деле, я собираюсь привести пример здесь, так что, надеюсь, это имеет смысл для вас и всех, кто, возможно, задается вопросом. Рассмотрим сценарий, включающий две коробки с одинаковой фиксированной высотой и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:

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

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

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

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

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

-Boris

Действительно, это то, на что это было бы похоже, если бы вторая коробка была установлена ​​в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он будет отброшен, а не в сторону, независимо от того, установил ли он свой собственный BFC.

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

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

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

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

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

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

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

Другие вопросы по тегам