CSS: чистое решение проблемы коллапса поля при перемещении элемента - PullRequest
22 голосов
/ 01 июня 2011

Пример HTML + CSS:

<html>
  <body style="padding: 0; margin: 0;">
    <div style="float: right;">first</div>
    <div style="margin-top: 2em;">second</div>
  </body>
</html>

Желаемое поведение: first div плавает в правом верхнем углу окна. Фактическое поведение: оно плавает на 2 пункта ниже желаемой позиции. Причина: поле сжимается .

Несмотря на выявление проблемы, решения, которые я могу придумать, похожи на хаки:

  • изменить стиль body на margin: -1px 0 0 0; border-top: 1px solid;.
  • вставить <div style="height: 1px; margin-bottom: -1px;"></div> до first
  • вставить выше <div> между first и second

Существует ли чистый идиоматический способ избежать этой проблемы?

Ответы [ 7 ]

22 голосов
/ 01 июня 2011

Добавление overflow: hidden; к body должно решить вашу проблему.Он определяет новый контекст форматирования блока, как описано в этой статье: Магия переполнения: скрыто .

jsFiddle Demo (тег body автоматически добавляется jsFiddle, поэтому я не включил его в разметку HTML)

UPDATE (спасибо @clairesuzy): это решение не работает, если body имеет padding: 0.Пока я не найду лучшего способа, я могу только предложить добавить обертку вокруг двух элементов (по крайней мере, я заслуживаю сейчас @ Марселя внизу :)), который я все еще считаю чище, чем решения, опубликованные ОП.Обычно я в любом случае добавляю обертку к плавающим объектам (большую часть времени облегчает работу со старыми браузерами), в большинстве случаев ее не нужно добавлять намеренно, поскольку это логически и семантически необходимо.

Итак, на данный момент я могу придумать следующее:

<body style="padding: 0; margin: 0;">
   <div id="container" style="overflow: hidden;">
       <div style="float: right;">first</div>
       <div style="margin-top: 2em;">second</div>
   </div>
</body>

jsFiddle Demo

ОБНОВЛЕНИЕ 2 : после обдумывания и чтениякомментарии, я действительно думаю, что overflow: hidden (или что-то кроме overflow: visible) на контейнере является правильным решением.Единственное исключение, где он не работал для меня, это установка его на элемент body, что в любом случае является очень редкой ситуацией.В этих редких ситуациях вы можете попробовать использовать position: absolute; top: 0; right: 0; вместо плавающего.

Другой возможный обходной путь: я также обнаружил, что настройка display: inline-block; width: 100%; на body действительно работает.

jsFiddle Demo

2 голосов
/ 26 января 2016

РЕШЕНИЕ

добавьте overflow: auto; или overflow: hidden; или overflow: scroll; к тегам html и body.

ЕСЛИ ВЫ ХОТИТЕ ЗНАТЬ ПОЧЕМУ

Создание контекста форматирования блока (BFC) для тега body.

Почему это не работает, если я добавляю overflow: hidden; только к body?

Вот почему:

W3C # блок-форматирования

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

W3C # перелива

UA должны применить свойство overflow, установленное в корневом элементе, к области просмотра.

Если корневой элемент является элементом HTML «HTML» или элементом HTML «HTML» XHTML, и этот элемент имеет элемент «BODY» HTML или элемент «body» XHTML в качестве дочернего, пользовательские агенты должны вместо этого применить ' свойство overflow 'из первого такого дочернего элемента в область просмотра, если значение корневого элемента' visible '.

Значение 'visible' при использовании для окна просмотра должно интерпретироваться как 'auto'.

Элемент, из которого распространяется значение , должен иметь используемое значение для 'overflow' из 'visible' .

the first such child element и The element from which the value is propagated относятся к тегу body в этом случае.

Другими словами, если вы добавите overflow: hidden; или overflow: auto; или overflow: scroll; к body, в то время как значение html 's overflow свойство равно visible, значение body' Свойство s overflow (hidden или auto или scroll) будет передано в область просмотра. Таким образом, согласно первой цитате W3C, body не установит новый контекст форматирования блока.

Однако, если вы добавите overflow: hidden; или overflow: auto; или overflow: scroll; к html, значение 'body' overflow не будет распространяться и, следовательно, будет установлен новый контекст форматирования блока.

2 голосов
/ 02 марта 2013

На родителя div добавить это #parent {padding 1px 0; } это была огромная проблема для меня, и мне понадобилось навсегда, чтобы найти решение.Я видел на посту, как 2 года, и это исправляет крах.

1 голос
/ 24 февраля 2014

Еще один трюк, который вы можете использовать, когда overflow:hidden не подходит:

.clr:before, .clr:after {
    display: table;
    content: " ";
    clear: both;
    font-size: 0;
}

Этот фрагмент имеет побочный эффект и содержит все поплавки.

1 голос
/ 19 октября 2013

Спецификации W3C описывают это о сокращающихся полях:

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

http://www.w3.org/TR/CSS21/box.html#collapsing-margins

Лучший способ справиться со сворачивающимися полями - просто добавить один пиксель к верхнему или нижнему отступу элемента, у которого есть свернутое поле.

если маржа рухнула сверху .. тогда:

#element-with-collapsed-margin {
   padding-top:1px;
}

или border-top это тоже исправит

#element-with-collapsed-margin {
   border-top:1px solid transparent;
}

если ваше нижнее поле свернуто, вы добавите padding-bottom: 1px; или border-top: 1px solid прозрачный;

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

хорошая ссылка:

http://reference.sitepoint.com/css/collapsingmargins

..

1 голос
/ 01 июня 2011

Добавьте float: left; ко второму делению.

скрипка

0 голосов
/ 11 апреля 2017

Это может показаться странным, но в новых версиях Chrome и Mozilla вы можете добиться желаемого поведения (первый div находится вверху справа), добавив div-обертку с рамкой

<html>
  <body style="padding: 0; margin: 0;">
    <div style="border: 1px solid black">
        <div style="float: right;">first</div>
        <div style="margin-top: 2em;">second</div>
    </div>
  </body>
</html>
...