Как работает контекст блочного форматирования CSS?

Как работает контекст блочного форматирования CSS?

Спецификации CSS2.1 говорят о том, что в контексте форматирования блоков блоки располагаются вертикально, начиная сверху. Это происходит, даже если на пути присутствуют плавающие элементы, кроме случаев, когда блок-блок устанавливает новый контекст форматирования блока. Как мы знаем, когда браузеры отображают блоки блоков в контексте форматирования блоков, плавающий элемент опускается, почему работает создание нового контекста форматирования блоков?

Как блоки (блоки блоков и встроенные блоки) расположены в нормальном потоке?

Я где-то читал, что блочные элементы генерируют блочные блоки, но плавающие элементы игнорируются, когда пользовательский агент рисует блок, и учитывают их при заполнении контента. Хотя плавающие элементы будут перекрывать границы других элементов блоков, решение заключается в создании нового контекста форматирования блоков для перекрывающихся элементов с использованием overflow:hidden,

"Новый контекст форматирования блока по-прежнему является блочным форматированием", поэтому при рисовании блока он также будет обрабатывать плавающий элемент, как если бы он не выходил. Это правильно или я неправильно понял "новый контекст форматирования блока?"

Обновление: больше вопросов

Говоря: "Именно это поведение полезно для макетов столбчатых стилей. Однако основное его использование - это прекращение операций с плавающей точкой, скажем, в div с" основным содержимым ", на самом деле очищение столбцов с плавающей стороной, то есть операций с плавающей точкой, которые появляются ранее в исходном коде".

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

.content {
  background: #eee;
  color #000;
  border: 3px solid #444;
  width: 500px;
  height: 200px;
}
.float {
  background: rgba(0, 0, 255, 0.5);
  border: 1px solid #00f;
  width: 150px;
  height: 150px;
  float: right;
}
p {
  background: #444;
  color: #fff;
}
<div class="content">
  <h3>This is a content box</h3>
  <p>It contains a left floated box, you can see the actual content div does go under the float, but that it is the &lt;h3&gt; and &lt;p&gt; <b>line boxes</b> that are shortened to make room for the float. This is normal behaviour.</p>
  <div class="float">floated box</div>
</div>

Я думал, что плавающая коробка должна всплывать наверх связующего блока - div с классом content, Кроме того, если всплывающее окно появляется ранее в разметке, то оно будет отображать то, что я думаю, должно быть.

.content {
  background: #eee;
  color #000;
  border: 3px solid #444;
  width: 500px;
  height: 200px;
}
.float {
  background: rgba(0, 0, 255, 0.5);
  border: 1px solid #00f;
  width: 150px;
  height: 150px;
  float: right;
}
p {
  background: #444;
  color: #fff;
}
<div class="content">
  <div class="float">floated box</div>
  <h3>This is a content box</h3>
  <p>it contains a left floated box, you can see the actual content div does go under the float, but that it is the &lt;h3&gt; and &lt;p&gt; <b>line boxes</b> that are shortened to make room for the float, this is normal behaviour</p>
</div>

Как мы можем это объяснить? Можем ли мы использовать "блочный контекст форматирования и встроенный контекст форматирования", чтобы объяснить это?

1 ответ

Решение

Контексты блочного форматирования

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

С моим жирным шрифтом, это установить бит, который важен

Это означает, что элемент, который вы используете overflow (что-либо кроме видимого) или float или же inline-block..etc on становится ответственным за расположение дочерних элементов. Это дочерние элементы, которые затем "содержатся", независимо от того, являются ли они плавающими или разрушающимися полями, они должны полностью содержаться ограничивающим их родителем.

В контексте форматирования блока левый внешний край каждого блока касается левого края содержащего блока (для форматирования справа налево касание правого края)

Что означает вышеуказанная строка:

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


Распродажа

В обычных обстоятельствах float должен очистить все предыдущие плавающие элементы, которые ранее плавали во всем исходном коде, а не только в отображаемом вами "столбце".

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

Допустим, у вас есть макет из трех столбцов, в котором левый и правый столбцы смещены влево и вправо соответственно, боковые столбцы теперь находятся в новых контекстах форматирования блоков, потому что они перемещаются (помните, что float также является одним из свойств, устанавливающих новый BFC).), так что вы можете свободно перемещать элементы списка внутри них, и они очищают только те float, которые уже находятся внутри боковых столбцов, которые больше не заботятся о плавающих ранее в исходном коде


Сделать основной контент новым контекстом блочного форматирования или нет?

Теперь этот средний столбец, вы можете просто разметить его с обеих сторон, чтобы он аккуратно сидел между двумя боковыми плавающими столбцами и занимал оставшуюся ширину, обычным способом получить желаемую ширину, если центральный столбец "жидкий" - что будет все будет хорошо, пока вам не понадобится использовать float / просвет внутри вашего содержимого div (обычное явление для тех, кто использует хаки "clearfix" или шаблоны, включая их)

Возьмите этот очень простой код:

#left-col {
  border: 1px solid #000;
  width: 180px;
  float: left;
}
#right-col {
  border: 1px solid #000;
  width: 180px;
  float: right;
  height: 200px;
}
#content {
  background: #eee;
  margin: 0 200px;
}
.floated {
  float: right;
  width: 180px;
  height: 100px;
  background: #dad;
}
<div id="left-col">left column</div>
<div id="right-col">right column</div>

<div id="content">
  <h3>Main Content</h3>
  <p>Lorem ipsum etc..</p>
  <div class="floated">this a floated box</div>
  <div class="floated">this a floated box</div>
</div>

Это производит следующее:

В целом это нормально, особенно если у вас нет фоновых цветов или внутренних (в основном содержимом) плаваний - обратите внимание, что плавания в порядке (еще не очищены), они, вероятно, делают то, что вы, кроме них, но они, H3 верхний край а p Нижнее поле на самом деле не содержится в содержимом div (светло-серый фон).

Итак, к тому же простому маргинальному сценарию из приведенного выше кода добавьте

.clear-r {clear: right;}

в CSS, и измените второе всплывающее окно HTML на:

<div class="floated clear-r"> this a floated cleared box</div>

#left-col {
  border: 1px solid #000;
  width: 180px;
  float: left;
}
#right-col {
  border: 1px solid #000;
  width: 180px;
  float: right;
  height: 200px;
}
#content {
  background: #eee;
  margin: 0 200px;
}
.floated {
  float: right;
  width: 180px;
  height: 100px;
  background: #dad;
}
.clear-r {
  clear: right;
}
<div id="left-col">left column</div>
<div id="right-col">right column</div>

<div id="content">
  <h3>Main Content</h3>
  <p>Lorem ipsum etc..</p>
  <div class="floated">this a floated box</div>
  <div class="floated clear-r">this a floated cleared box</div>
</div>

На этот раз вы получите это:

Второй поплавок очищает правую сторону, но очищает всю высоту правой колонки. Правый столбец находится в исходном коде раньше, поэтому он очищается, как сказано! Вероятно, не желаемый эффект, хотя, также обратите внимание на h3 а также p поля все еще свернуты (не содержатся).


Заставь его установить контекст форматирования блока, ради детей!

и, наконец, заставить главный столбец содержимого взять на себя ответственность - стать контекстом блочного форматирования - для его содержимого: удалить margin: 0 200px; из основного контента CSS и ADD overflow: hidden; и вы получите это:

#left-col {
  border: 1px solid #000;
  width: 180px;
  float: left;
}
#right-col {
  border: 1px solid #000;
  width: 180px;
  float: right;
  height: 200px;
}
#content {
  background: #eee;
  overflow: hidden;
}
.floated {
  float: right;
  width: 180px;
  height: 100px;
  background: #dad;
}
.clear-r {
  clear: right;
}
<div id="left-col">left column</div>
<div id="right-col">right column</div>

<div id="content">
  <h3>Main Content</h3>
  <p>Lorem ipsum etc..</p>
  <div class="floated">this a floated box</div>
  <div class="floated clear-r">this a floated cleared box</div>
</div>

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

При широком использовании перезагрузок в наши дни поля становятся менее заметными (а IE до сих пор не совсем их понимает), однако то, что только что произошло с "основным контентом" центра, так это то, что он стал контекстом блочного форматирования и теперь отвечает за его собственные дочерние (потомковые) элементы. На самом деле это очень похоже на раннее представление Microsoft о hasLayout, оно использует те же свойства display: inline-block, float, а также overflow все что угодно, кроме видимого, и, конечно, ячейки таблицы всегда имеют разметку... однако без ошибок;)

Надеюсь, это поможет, любые вопросы не стесняйтесь задавать!


Обновление: больше информации в вопросе:

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

Да, плавающие элементы обычно перекрывают свои контейнеры, это то, что вы имеете в виду относительно родительских границ? Когда элемент блока нарисован и содержит плавающий элемент, родительский элемент самого блока рисуется в виде прямоугольника под плавающей точкой, и это "встроенные анонимные блоки" или просто "линейные блоки" других дочерних элементов, которые сокращаются, чтобы освободить место для поплавок

Возьми этот код:

#content {
  background: #eee;
  color #000;
  border: 3px solid #444;
}
.float {
  background: rgba(0, 0, 255, 0.5);
  border: 1px solid #00f;
  width: 150px;
  height: 150px;
  float: left;
  margin: 10px;
}
p {
  background: #444;
  color: #fff;
}
<div id="content">
  <div class="float">floated box</div>
  <h3>This is a content box</h3>
  <p>it contains a left floated box, you can see the actual content div does go under the float, but that it is the &lt;h3&gt; and &lt;p&gt; <b>line boxes</b> that are shortened to make room for the float, this is normal behaviour</p>
</div>

Который производит это:

как плавает работа

Вы видите, что родительский элемент на самом деле не содержит float, так как он не переносит его полностью... float просто плавает поверх содержимого - если бы вы продолжали добавлять содержимое в div, он в конечном итоге был бы перенесен под поплавком, потому что не было бы необходимости в (анонимных) "строчках" p Элемент, чтобы сократить себя больше.

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

Снова ссылаясь на рисунок выше, если вы должны были наделить левую сторону p элемент, да, он остановит перенос текста под дном поплавка, потому что "линейные блоки" (белый текст) будут касаться только левого края их контейнера, и вы принесете цветной фон p направо, подальше от поплавка, но вы не измените поведение p форматирование контекста. Как и в центре столбца на первом рисунке выше;)

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