CSS: чистое решение проблемы с крахом поля при перемещении элемента
Пример HTML + CSS:
<html>
<body style="padding: 0; margin: 0;">
<div style="float: right;">first</div>
<div style="margin-top: 2em;">second</div>
</body>
</html>
Желаемое поведение: div first
плавает в верхнем правом углу окна. Фактическое поведение: он плавает на 2 метка ниже желаемой позиции. Причина: разворот маржи.
Несмотря на выявление проблемы, решения, которые я могу придумать, выглядят как хаки:
- измените стиль
body
на margin: -1px 0 0 0; border-top: 1px solid;
.
- вставить
<div style="height: 1px; margin-bottom: -1px;"></div>
до first
- вставьте выше
<div>
между first
и second
Есть ли чистый, идиоматический способ избежать этой проблемы?
Ответы
Ответ 1
Добавление overflow: hidden;
в body
должно решить вашу проблему. Он определяет новый контекст форматирования блоков, как описано в этой статье: Магия переполнения: скрытая.
jsFiddle Demo (тег body
автоматически добавляется jsFiddle, поэтому я не включил его в разметку HTML)
UPDATE (спасибо to @clairesuzy): Это решение не работает, если body
имеет padding: 0
. Пока я не смогу найти лучший способ, я могу предложить только добавить обертку вокруг двух div (по крайней мере, я заслуживаю теперь @Marcel downwote:)), который, как я считаю, более чист, чем решения, размещенные OP. Я обычно добавляю обертку вокруг плавающего материала в любом случае (упрощает обработку старых браузеров большую часть времени), большую часть времени его не нужно добавлять намеренно, потому что это логически и семантически требуется.
Итак, теперь я могу придумать это:
<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
В родительском div
добавьте это #parent {padding 1px 0; }
, это было огромной проблемой для меня, и навсегда потребовалось найти решение. Я видел на почте, как 2 года, и это устраняет крах.
Ответ 3
Решение
добавить overflow: auto;
или overflow: hidden;
или overflow: scroll;
в теги html
и body
.
ЕСЛИ ВЫ ХОТИТЕ ЗНАТЬ ПОЧЕМУ
Создание контекста форматирования блока (BFC) в теге body
.
Почему это не работает, если я добавляю overflow: hidden;
только к body
?
Вот почему:
W3С# блочное форматирование
Поплавки, абсолютно позиционированные элементы, блокировать контейнеры (например, встроенные блоки, таблицы-ячейки и заголовки таблиц), которые не являются блочными блоками, и блокировать блоки с "переполнением", отличным от "видимого" (исключая когда это значение было распространено в окне просмотра), создайте контексты форматирования блоков для их содержимого.
Переполнение W3С#:
UA должны применять свойство переполнения в корневом элементе к окну просмотра.
Когда корневой элемент является элементом HTML "HTML" или элементом "html" XHTML, и этот элемент имеет элемент HTML "BODY" или элемент "тело" XHTML в качестве дочернего элемента, пользовательские агенты должны вместо этого применять ' overflow 'из первого такого дочернего элемента в окне просмотра, если значение в корневом элементе "видимо" .
"Видимое" значение, используемое для окна просмотра, должно интерпретироваться как "авто".
Элемент, из которого распространяется значение, должен иметь использованное значение для "переполнения" "видимого" .
the first such child element
и The element from which the value is propagated
относятся к тегу body
в этом случае.
Другими словами, если вы добавляете overflow: hidden;
или overflow: auto;
или overflow: scroll;
в body
, а значение свойства html
overflow
остается неизменным, значение свойства body
overflow
hidden
или auto
или scroll
) будут переданы в окно просмотра. Таким образом, согласно первой цитате W3C, body
не будет устанавливать новый контекст форматирования блока.
Однако, если вы добавите overflow: hidden;
или overflow: auto;
или overflow: scroll;
в html
, значение overflow
'body' не будет распространено и, следовательно, создаст новый контекст форматирования блока.
Ответ 4
Добавьте float: left;
во второй div.
fiddle
Ответ 5
Спецификации 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 transparent;
в основном любая граница или заполнение сверху или снизу прекращают сбрасывать поля, когда они у вас выше друг друга, или даже когда у вас есть элементы, вложенные внутри друг друга, которые имеют развал маржи
Хорошая ссылка:
http://reference.sitepoint.com/css/collapsingmargins
..
Ответ 6
Другой трюк, который вы можете использовать, когда overflow:hidden
не подходит:
.clr:before, .clr:after {
display: table;
content: " ";
clear: both;
font-size: 0;
}
Этот фрагмент имеет побочный эффект, содержащий все поплавки.
Ответ 7
Это может быть странно, но в новых версиях 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>