Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

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

-Давид

Скорее всего, это относится к прокручиваемому контенту в поле, которое может возникнуть вне родителя 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:

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

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

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

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

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

-Boris

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

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

Опять же, обратите внимание, что содержимое должно быть переписано, чтобы избежать затенения с помощью float.

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


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

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

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

Обратите внимание, что нет разрешения; если второй блок имел clear: left или clear: both, он был бы сдвинут вниз, а не в сторону, независимо от того, установил ли он свой собственный BFC.

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

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

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

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

Ответ 2

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

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

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