Маржа на дочернем элементе перемещает родительский элемент - PullRequest
362 голосов
/ 19 ноября 2009

У меня есть div ( родитель ), который содержит еще div ( дочерний элемент ). Родитель - это первый элемент в body без определенного стиля CSS. Когда я установил

.child
{
    margin-top: 10px;
}

Конечным результатом является то, что вершина моего ребенка все еще выровнена с родителем. Вместо того, чтобы переместить ребенка на 10px вниз, мой родитель переместился на 10px вниз.

Мой DOCTYPE установлен на XHTML Transitional.

Что мне здесь не хватает?

редактировать 1
У моего родителя должны быть строго определенные размеры, потому что у него есть фон, который должен отображаться под ним сверху вниз (в идеальном пикселе). Таким образом, установка вертикальных полей для него - это без движения .

редактировать 2
Это поведение одинаково на FF, IE и CR.

Ответы [ 14 ]

431 голосов
/ 21 декабря 2009

Найдена альтернатива в Дочерние элементы с полями в DIV Вы также можете добавить:

.parent { overflow: auto; }

или

.parent { overflow: hidden; }

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

.parent {
    padding-top: 1px;
    margin-top: -1px;
}

Обновление по популярному запросу: Весь смысл сокращения полей - обработка текстового контента. Например:

<style type="text/css">
    h1, h2, p, ul {
        margin-top: 1em;
        margin-bottom: 1em;
    }
</style>

<h1>Title!</h1>
<div class="text">
    <h2>Title!</h2>
    <p>Paragraph</p>
</div>
<div class="text">
    <h2>Title!</h2>
    <p>Paragraph</p>
    <ul>
        <li>list item</li>
    </ul>
</div>

Поскольку браузер сворачивает поля, текст будет отображаться так, как вы ожидаете, а теги-оболочки <div> не влияют на поля. Каждый элемент гарантирует, что он имеет интервал вокруг него, но интервал не будет удвоен. Поля <h2> и <p> не складываются, а скользят друг в друга (они сворачиваются). То же самое происходит для элементов <p> и <ul>.

К сожалению, с современным дизайном эта идея может укусить вас, когда вы явно хотите контейнер. Это называется новым контекстом блочного форматирования на языке CSS. overflow или трюк на марже даст вам это.

46 голосов
/ 19 ноября 2009

Это нормальное поведение (по крайней мере, среди реализаций браузера). Поля не влияют на позицию дочернего элемента по отношению к его родителю, если только у родительского элемента нет отступов, и в этом случае большинство браузеров добавят поле дочернего элемента к отступам родителя.

Чтобы получить желаемое поведение, вам необходимо:

.child {
    margin-top: 0;
}

.parent {
    padding-top: 10px;
}
19 голосов
/ 15 июня 2015

Хотя все ответы решают проблему, но они идут с компромиссами / корректировками / компромиссами, такими как

  • floats, у вас есть для всплытия элементов
  • border-top, это толкает родительский элемент не менее чем на 1 пиксель вниз, что затем должно быть скорректировано путем введения поля -1px для самого родительского элемента. Это может создать проблемы, когда у родителя уже есть margin-top в относительных единицах.
  • padding-top, тот же эффект, что и при использовании border-top
  • overflow: hidden, не может использоваться, когда родительский элемент должен отображать переполненный контент, например выпадающее меню
  • overflow: auto, вводит полосы прокрутки для родительского элемента, который имеет (намеренно) переполненное содержимое (например, тени или треугольник подсказки)

Проблема может быть решена с помощью псевдоэлементов CSS3 следующим образом

.parent::before {
  clear: both;
  content: "";
  display: table;
  margin-top: -1px;
  height: 0;
}

https://jsfiddle.net/hLgbyax5/1/

12 голосов
/ 08 апреля 2015

добавить стиль display:inline-block к дочернему элементу

7 голосов
/ 23 июля 2013

родительский элемент не должен быть пустым, по крайней мере, поместите &nbsp; перед дочерним элементом.

6 голосов
/ 26 сентября 2014

Вот что у меня сработало

.parent {
padding-top: 1px;
margin-top: -1px;
}

.child {
margin-top:260px;
}

http://jsfiddle.net/97fzwuxh/

2 голосов
/ 14 мая 2016

Я узнаю это, внутри вашего .css> если вы установите для свойства display элемента div значение inline-block , это устранит проблему. и маржа будет работать, как ожидается.

1 голос
/ 13 ноября 2017

Чистое решение только для CSS

Используйте следующий код для добавления незаполненного первого ребенка к непреднамеренно движущемуся div:

.parent:before
{content: '';position: relative;height: 0px;width: 0px;overflow: hidden;white-space: pre;}

Преимущество этого метода состоит в том, что вам не нужно изменять CSS любого существующего элемента, и, следовательно, он оказывает минимальное влияние на дизайн. Рядом с этим добавляемый элемент является псевдоэлементом, который не в DOM-дереве.

Широко распространена поддержка псевдоэлементов: Firefox 3+, Safari 3+, Chrome 3+, Opera 10+ и IE 8+. Это будет работать в любом современном браузере (будьте осторожны с более новым ::before, который не поддерживается в IE8).

Контекст

Если первый дочерний элемент имеет margin-top, родительский объект будет корректировать свое положение, чтобы уменьшить избыточные поля. Зачем? Это просто так.

Учитывая следующую проблему:

<style type="text/css">
div {position: relative;}
.parent {background-color: #ccc;}
.child {margin-top: 40px;}
</style>

<div class="parent"><!--This div moves 40px too-->
    <div class="child">Hello world!</div>
</div>

Вы можете исправить это, добавив дочерний элемент с содержимым, например простым пробелом. Но мы все ненавидим добавлять пробелы для решения проблемы, связанной только с дизайном. Поэтому используйте свойство white-space для фальсификации содержимого.

<style type="text/css">
div {position: relative;}
.parent {background-color: #ccc;}
.child {margin-top: 40px;}
.fix {position: relative;white-space: pre;height: 0px;width: 0px;overflow: hidden;}
</style>

<div class="parent"><!--This div won't move anymore-->
    <div class="fix"></div>
    <div class="child">Hello world!</div>
</div>

Где position: relative; обеспечивает правильное расположение исправления. И white-space: pre; избавляет вас от необходимости добавлять какой-либо контент - например, пробел - в исправление. И height: 0px;width: 0px;overflow: hidden; гарантирует, что вы никогда не увидите исправления.

Возможно, вам придется добавить line-height: 0px; или max-height: 0px;, чтобы гарантировать, что высота фактически равна нулю в древних браузерах IE (я не уверен). И при желании вы можете добавить <!--dummy--> к нему в старых браузерах IE, если он не работает.

Короче говоря, вы можете сделать все это только с помощью CSS (что устраняет необходимость добавления фактического потомка в HTML-дерево DOM):

<style type="text/css">
div {position: relative;}
.parent {background-color: #ccc;}
.child {margin-top: 40px;}

.parent:before {content: '';position: relative;height: 0px;width: 0px;overflow: hidden;white-space: pre;}
</style>

<div class="parent"><!--This div won't move anymore-->
    <div class="child">Hello world!</div>
</div>
1 голос
/ 08 января 2015

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

Хотя ваш ящик будет использовать дополнительные пиксели ...

.parent {
    border:1px solid transparent;
}
1 голос
/ 15 июля 2014

интересно, мое любимое решение этой проблемы здесь еще не упоминалось: использование поплавков.

HTML:

<div class="parent">
    <div class="child"></div>
</div>

CSS:

.parent{width:100px; height:100px;}
.child{float:left; margin-top:20px; width:50px; height:50px;}

см. Здесь: http://codepen.io/anon/pen/Iphol

обратите внимание, что в случае, если вам нужна динамическая высота для родителя, он также должен плавать, поэтому просто замените height:100px; на float:left;

...