Как отключить маржинальное свертывание?

203

Можно ли вообще отключить коллапс маржи? Единственные решения, которые я нашел (под названием «uncollapsing»), влекут за собой использование 1px border или 1px padding. Я считаю это неприемлемым: посторонний пиксель усложняет вычисления без веской причины. Есть ли более разумный способ отключить это сокращение полей?

KJo
источник
4
Используйте макет Flex или Grid, где не существует
Майкл Бенджамин,
Просто margin-bottommargin-top
Дэн Брей
Я сделал пакет, чтобы сделать расчет проще: npmjs.com/package/collapsed-margin
Оуэн М

Ответы:

255

Существует два основных типа обрушения маржи:

  • Свертывание полей между соседними элементами
  • Свертывание полей между родительскими и дочерними элементами

Использование отступов или бордюров предотвратит коллапс только в последнем случае. Кроме того, любое значение, overflowотличное от его default ( visible), примененного к родителю, предотвратит коллапс. Таким образом, оба overflow: autoи overflow: hiddenбудут иметь одинаковый эффект. Возможно, единственное отличие при использовании hidden- это непреднамеренное последствие скрытия контента, если родитель имеет фиксированную высоту.

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

  • float: left / right
  • position: absolute
  • display: inline-block / flex

Вы можете проверить их все здесь: http://jsfiddle.net/XB9wX/1/ .

Я должен добавить, что, как обычно, Internet Explorer является исключением. В частности, в IE 7 поля не сворачиваются, когда для родительского элемента указана какая-то компоновка, например width.

Источники: статья Sitepoint, Свертывание полей

hqcasanova
источник
1
обратите внимание, что заполнение также может повлиять на это, если оно не равно нулю
Младен Янджетович
3
Обратите внимание, что это overflow: autoможет привести к появлению полос прокрутки в родительском элементе, а не к переполнению содержимого в соответствии с overflow: visible.
Лев
«переполнение: авто» не работает в Chrome v44.
tkane2000
3
Спасибо за показ: встроенный блок, это спасло меня :)
alexcasalboni
3
Любое значение, flexотличное от значения по умолчанию, также отключит коллапс маржи
Oly
60

Для этого вы также можете использовать старый добрый микрофиксон.

#container:before, #container:after{
    content: ' ';
    display: table;
}

Смотрите обновленную скрипку: http://jsfiddle.net/XB9wX/97/

Blackgrid
источник
Превратили мой ответ в вики сообщества. Пожалуйста, не стесняйтесь расширять его своим ответом. Спасибо.
hqcasanova
3
Я не понимаю, когда я смотрю на этот пример, поля рушатся (только 10px вертикальное пространство между div вместо 20px)
Энди
1
Это помогает только в устранении коллапса между братьями и сестрами, к которым применен этот clearfix. Я разработал пример, чтобы продемонстрировать это: jsfiddle.net/dpyuyg07 - и даже это еще не все. Он только удаляет коллапс полей из дочерних элементов элементов, к которым вы применили это исправление. Если вы добавите поле для самого контейнера, поля все равно будут сжиматься
NicBright
4
Я могу выразить это еще точнее: метод clearfix предотвращает только разрыв между родителями и детьми. Это не влияет на коллапс между соседними братьями и сестрами.
NicBright
Я думаю , теперь я понимаю тенденцию Bootstrap, чтобы заполнить DOM с :beforeи :afterэлементами. Теперь я добавил это правило к моей таблице стилей: div:before, div:after{content: ' '; display: table;}. Фантастика. Внезапно вещи начинают вести себя как ожидалось.
Стейн де Витт
60

Насколько мне известно, одним из хитрых приемов отключения сворачивания полей, который не оказывает визуального воздействия, является установка отступа родительского элемента в 0.05px:

.parentClass {
    padding: 0.05px;
}

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

Если требуется какое-то другое заполнение, тогда применяют заполнение только к «направлению», в котором, например, не требуется сворачивание полей padding-top: 0.05px;.

Рабочий пример:

.noCollapse {
  padding: 0.05px;
}

.parent {
  background-color: red;
  width: 150px;
}

.children {
  margin-top: 50px;

  background-color: lime;      
  width: 100px;
  height: 100px;
}
<h3>Border collapsing</h3>
<div class="parent">
  <div class="children">
  </div>
</div>

<h3>No border collapsing</h3>
<div class="parent noCollapse">
  <div class="children">
  </div>
</div>

Изменить: изменил значение с 0.1на 0.05. Как отметил Крис Морган в комментарии ниже, и из этого небольшого теста кажется, что действительно Firefox принимает во внимание 0.1pxотступы. Хотя, 0.05pxпохоже , делает свое дело.

Нику Сурду
источник
2
Это мое любимое решение. Вы можете даже включить это как стиль по умолчанию. Почему нет? *{padding-top:0.1px}, Мы уверены, что он работает во всех браузерах?
Ник Мэннинг
До сих пор работал довольно хорошо для меня, но я не претендую на то, что тщательно протестировал его в большинстве браузеров.
Нику Сурду
2
Очень хорошее решение, похоже, работает как и ожидалось в большинстве браузеров. Спасибо, что поделились этим!
wiredolphin
1
Это хитроумное решение , как это делает добавить дополнительные пиксели в различных условиях, из - за высокий DPI дисплеев и расчеты субпикселей. (Firefox
Крис Морган,
0.05pxЯ бы предпочел, чтобы это был конкретный выбор, а не случайный номер обмана браузера 0.01px.
Фолькер Э.
22

overflow:hidden предотвращает разрушение полей, но не лишено побочных эффектов, а именно ... скрывает переполнение.

Помимо этого и того, что вы упомянули, вы просто должны научиться жить с этим и учиться на этот день, когда они действительно полезны (приходит каждые 3-5 лет).

Литек
источник
Превратили мой ответ в вики сообщества. Я думаю, что я рассмотрел побочный эффект, который вы упомянули в последних двух строках второго абзаца: возможно, единственное отличие при использовании скрытого - непреднамеренное последствие скрытия контента, если родительский объект имеет фиксированную высоту . Но если вы считаете, что это требует дальнейшего разъяснения, пожалуйста, не стесняйтесь вносить свой вклад. Спасибо.
hqcasanova
7
overflow: autoхорошо использовать, чтобы предотвратить скрытое переполнение и все же предотвратить падение полей.
Гэвин
@Gavin, overflow:auto;заставил мою область контента получить полосу прокрутки на некоторых страницах.
Рид
13

На самом деле, есть один, который работает безупречно:

дисплей: гибкий; flex-direction: столбец;

до тех пор, пока вы можете жить с поддержкой только IE10 и выше

.container {
  display: flex;
  flex-direction: column;
    background: #ddd;
    width: 15em;
}

.square {
    margin: 15px;
    height: 3em;
    background: yellow;
}
<div class="container">
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
</div>
<div class="container">
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
</div>

Даниэль Костер
источник
Для этого , чтобы работать в качестве универсального решения, необходимо добавить дополнительный <div>внутри .container, в противном случае .containerбудет контролировать бокс-модель своих детей. Например, встроенные элементы станут блочными элементами полной ширины; если у них есть маржа, они также будут обесценены.
Зуп
9

Каждый браузер на основе webkit должен поддерживать свойства -webkit-margin-collapse. Есть также подвойства, чтобы установить его только для верхнего или нижнего поля. Вы можете присвоить ему значения свернуть (по умолчанию), отбросить (устанавливает для поля значение 0, если есть соседнее поле) и разделить (предотвращает сжатие поля).

Я проверял, что это работает на версиях Chrome и Safari 2014 года. К сожалению, я не думаю, что это будет поддерживаться в IE, потому что он не основан на webkit.

Прочитайте Apple Safari CSS Reference для полного объяснения.

Если вы заглянете на страницу расширений CSS веб-набора Mozilla , они перечислят эти свойства как собственные и рекомендуют не использовать их. Это потому, что они, скорее всего, не собираются переходить на стандартный CSS в ближайшее время, и только браузеры на основе webkit будут поддерживать их.

Дэн Картер
источник
Это хорошо, потому что это помогает нам устранить несоответствие в том, как Safari и Chrome справляются с наценками.
Бьюдсон
8

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

Genzo
источник
Не только для своих дочерних элементов - он также предотвращает разрушение полей между родителем и первым и последним дочерним элементом.
Свен Марнах
2

У меня была похожая проблема с коллапсом полей из-за того, что родитель positionустановил относительное значение. Вот список команд, которые вы можете использовать, чтобы отключить сжатие полей.

ЗДЕСЬ ИГРА ДЛЯ ТЕСТИРОВАНИЯ

Просто попробуйте присвоить любой parent-fix*класс к div.containerэлементу, или любой класс children-fix*к div.margin. Выберите тот, который соответствует вашим потребностям лучше всего.

когда

  • Маржа коллапса является отключена , div.absoluteс красным фоном будет расположен в самом верху страницы.
  • поле сжимается div.absolute будет располагаться в той же координате Y, что иdiv.margin

html, body { margin: 0; padding: 0; }

.container {
  width: 100%;
  position: relative;
}

.absolute {
  position: absolute;
  top: 0;
  left: 50px;
  right: 50px;
  height: 100px;
  border: 5px solid #F00;
  background-color: rgba(255, 0, 0, 0.5);
}

.margin {
  width: 100%;
  height: 20px;
  background-color: #444;
  margin-top: 50px;
  color: #FFF;
}

/* Here are some examples on how to disable margin 
   collapsing from within parent (.container) */
.parent-fix1 { padding-top: 1px; }
.parent-fix2 { border: 1px solid rgba(0,0,0, 0);}
.parent-fix3 { overflow: auto;}
.parent-fix4 { float: left;}
.parent-fix5 { display: inline-block; }
.parent-fix6 { position: absolute; }
.parent-fix7 { display: flex; }
.parent-fix8 { -webkit-margin-collapse: separate; }
.parent-fix9:before {  content: ' '; display: table; }

/* Here are some examples on how to disable margin 
   collapsing from within children (.margin) */
.children-fix1 { float: left; }
.children-fix2 { display: inline-block; }
<div class="container parent-fix1">
  <div class="margin children-fix">margin</div>
  <div class="absolute"></div>
</div>

Вот jsFiddle с примером, который вы можете редактировать

Buksy
источник
1

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

ДЕМО (до)

.parent {
  background-color: grey;
}

.child {
  height: 16px;
  margin-top: 16px;
  margin-bottom: 16px;
  background-color: blue;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>

ДЕМО (после)

.parent {
  display: flow-root;
  background-color: grey;
}

.child {
  height: 16px;
  margin-top: 16px;
  margin-bottom: 16px;
  background-color: blue;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>

Chuanqi Sun
источник
0

Для вашей информации вы можете использовать сетку, но с побочными эффектами :)

.parent {
  display: grid
}
Whisher
источник