Маржа на дочернем элементе перемещает родительский элемент

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

.child
{
    margin-top: 10px;
}

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

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

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

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

изменить 2
Это поведение одинаково для FF, IE, а также для CR.


person Robert Koritnik    schedule 19.11.2009    source источник
comment
В нескольких браузерах или только в одном конкретном?   -  person o.k.w    schedule 19.11.2009
comment
это поведение не имеет никакого смысла. Предполагается, что маржа останется внутри родителя. Не двигай родителя. Кто пишет эти правила.   -  person Muhammad Umer    schedule 14.03.2013
comment
+2 за последний комментарий. серьезно меня беспокоит это правило. В 60% случаев он работает каждый раз - это маржа.   -  person Casey Dwayne    schedule 11.03.2014
comment
Я полностью согласен с двумя последними комментаторами. Это безумие. Интересно то, что добавление границы 1px к родительскому элементу заставляет его работать правильно, однако это означает, что у вас есть граница ... если это ожидаемое поведение, то это смешно   -  person erdomester    schedule 26.09.2014
comment
Пожалуйста, предоставьте дополнительную информацию о применяемой спецификации. Спасибо.   -  person actimel    schedule 17.06.2015
comment
Это также может вам помочь :) stackoverflow.com/questions/35337043/   -  person Bhojendra Rauniyar    schedule 12.02.2016
comment
Это напоминает мне правило размера коробки по умолчанию: Мы должны отправить коробку. Коробка не должна быть больше 100 см. Внутри коробки нам понадобится 10 см прокладки, чтобы контент не сломался во время транспортировки. Сделаем коробку 120см! Что за шутка.   -  person Nolonar    schedule 15.12.2016
comment
Это связано с падением маржи. Вот еще одна иллюстрация: stackoverflow.com/q/38679945/3597276   -  person Michael Benjamin    schedule 24.06.2018
comment
Спасибо, ребята, за комментарии. Сейчас я изучаю CSS только для себя и наблюдаю то же поведение с полем внутри родительского элемента. Теперь я вижу, что правильно понимаю и не сумасшедший;)   -  person Paweł Nowak    schedule 29.03.2020


Ответы (14)


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

.parent { overflow: auto; }

or:

.parent { overflow: hidden; }

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

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

Обновление 2021 года: если вы хотите отказаться от поддержки IE11, вы также можете использовать новую конструкцию CSS display: flow-root. См. веб-документы MDN для получения полной информации о блоке. контексты форматирования.


Обновление по многочисленным просьбам. Весь смысл сворачивания полей заключается в обработке текстового содержания. Например:

h1, h2, p, ul {
  margin-top: 1em;
  margin-bottom: 1em;
  outline: 1px dashed blue;
}

div { outline: 1px solid red; }
<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 или маржи даст вам это.

person vdboor    schedule 21.12.2009
comment
@Tom Fitton: без него многие сайты не работали бы. Это действительно важный краеугольный камень стандарта CSS, поэтому вы можете ожидать, что он будет работать. - person vdboor; 19.11.2011
comment
Я хочу знать, почему это происходит? Что это хорошего для кого-то. В какой ситуации должна была быть эта «особенность». - person Muhammad Umer; 14.03.2013
comment
@MuhammadUmer, ну это связано с текстовым контентом. Например, в серии <h2>, <p>, <ul> не появятся странные пробелы или двойные поля. - person vdboor; 17.03.2013
comment
Не могли бы вы привести какой-нибудь пример. Скажем, у меня есть div в качестве фона. С h1, h2 и p в нем. Теперь я хочу переместить h1 немного вниз, чтобы он не был так близко к вышеуказанному краю фонового div, но не расширял сам элемент h1. Я бы подумал добавить верхний край. Что очевидно. но когда я это делаю, великолепный фон решает сойтись вместе с ним. Как это особенность. Как это помогает в интервале между h1, h2 и p. Помогите мне понять, что вы говорите. - person Muhammad Umer; 17.03.2013
comment
Я добавил вам пример - person vdboor; 02.09.2015
comment
видите, даже на вашем примере это не имеет для меня никакого смысла. какая польза от перемещения родителя в этом примере? я хочу, чтобы h1 находился дальше от верха моего поля, поэтому я добавляю margin-top: 3em; какого черта я хочу, чтобы родитель переместился на 3em, приземлившись на h1 именно там, где я все еще не хочу, вместо того, чтобы просто переместить h1 вниз? ваш пример ничего не делает для объяснения этой концепции! - person JL Griffin; 27.10.2015
comment
@JLGriffin: у вас не может быть и того, и другого. В большинстве случаев он делает то, что вам нужно, даже не будучи замеченным. Иногда это не так, и вам нужно отменить это. Да, это раздражает, но рассмотрите альтернативу. Если бы браузеры сохраняли все поля внутри контейнеров, в Интернете возникло бы множество вопросов, например, почему вставка ‹div› в мой текст увеличивает поля ?. Теперь вы можете делать это без каких-либо побочных эффектов. - person vdboor; 28.10.2015
comment
Я ожидал, что это добавит больше маржи. Падение рентабельности - это, безусловно, самая неприятная вещь в моей карьере разработчика. если я поставлю 2 div рядом друг с другом с margin: 5px 10px; id, ожидайте 2 div на 5 пикселей сверху и 20 пикселей между ними, а не на 5 пикселей сверху и 10 пикселей между ними. если бы я хотел, чтобы между ними было 10 пикселей, идентификатор указал margin: 5px 5px;. Честно говоря, мне бы хотелось, чтобы у меня было какое-то корневое правило, которое остановило бы падение всех полей. Я ненавижу то, что мне приходится вдвое увеличивать размер полей на бумаге, чтобы заставить их делать то, что я, черт возьми, хочу на экране. и это главное ... какая катастрофа - person JL Griffin; 28.10.2015
comment
плюс в соответствии с вашим примером, почему вставка div в мой текст добавляет поле, это так просто, как: .div-in-text{ margin: 0;} и <div class="div-in-text"></div> - person JL Griffin; 28.10.2015
comment
безопасно ли устанавливать overflow:auto на всех div страницах html? Конфликтует ли это со сторонними плагинами, например. Карты Гугл? - person Ali Sheikhpour; 05.06.2018
comment
@AliSheikhpour нет, потому что overflow:auto добавляет полосы прокрутки всякий раз, когда контент не подходит. Это наверняка ломает третью сторону. Используйте его только там, где это действительно необходимо. - person vdboor; 11.06.2018
comment
Это заняло у меня половину дня. Вот, на мой взгляд, хорошее объяснение smashingmagazine.com/2019/07/margins-in-css/. display: flow-root выглядит как другой вариант. - person peterc; 24.04.2021

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

Чтобы добиться желаемого поведения, вам необходимо:

.child {
    margin-top: 0;
}

.parent {
    padding-top: 10px;
}
person Ben James    schedule 19.11.2009
comment
Добавление границы к родительскому элементу также повлияет на поле дочернего элемента, попробуйте .parent {border: solid 1px;} - person o.k.w; 19.11.2009
comment
Маржа не добавляется к отступу ... применяется отдельно. Но визуальный эффект такой же. - person Brilliand; 27.05.2011
comment
Что, если вам нужна верхняя маржа…? Не совсем решение. - person feeela; 16.06.2011
comment
Как сказала Фила - это не совсем решение, если требуется максимальная маржа. Ответ vdboor подходит лучше. - person Joey Morani; 08.04.2012
comment
Есть множество решений, вам просто нужно проявить достаточно творчества. Ваше здоровье. :-) - person Slavik Meltser; 09.03.2014
comment
Это отличный ответ. И в наши дни (по крайней мере, в Firefox - не тестировал другие) вам даже не нужно удалять дочерний margin-top. Простая установка any padding для родительского элемента позволит дочернему полю перемещать его относительно родительского элемента. - person kevlarr; 16.03.2019

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

  • 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/

person Ejaz    schedule 15.06.2015
comment
margin-top: -1px кажется ненужным. Но мне это нравится. - person Flimm; 23.12.2015
comment
На самом деле и margin-top: -1px, и height: 0 кажутся ненужными. Проверено в Chrome. Но лучшее решение. - person NinjaFart; 11.11.2016
comment
Этот метод в основном работает, но не учитывает нижнее поле для последнего элемента в контейнере. Это не равнозначное исправление для overflow: hidden; Например. - person Michael Giovanni Pumo; 13.11.2017
comment
@MichaelGiovanniPumo ответ можно изменить для работы с нижним полем последнего элемента, используя .parent:after... - person Ejaz; 13.11.2017
comment
Это определенно правильный ответ в настоящее время. Работает безупречно (ставить и после, и до), надеюсь люди осмелятся пролистать мимо других! - person fgblomqvist; 18.10.2018

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

person Атанас Димитров    schedule 08.04.2015

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

person George SEDRA    schedule 23.07.2013
comment
да, иногда только это может помочь ... или, лучше сказать, что-то вроде этого: ‹div style = 'width: 0; height: 0'› ‹/div› - person Pigalev Pavel; 06.10.2013

Это то, что сработало для меня

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

.child {
margin-top:260px;
}

http://jsfiddle.net/97fzwuxh/

person erdomester    schedule 26.09.2014

Чтобы предотвратить «родительский элемент Div», используйте поле «дочерний элемент div»:
В родительском элементе используйте следующие css:

  • Плавать
  • Обивка
  • Граница
  • Переполнение
person bingo    schedule 11.03.2018

Аккуратное решение только для 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>
person Yeti    schedule 13.11.2017
comment
Используйте это решение только в том случае, если вы в отчаянии и не можете установить какой-либо собственный CSS для существующих элементов - в противном случае используйте реальное решение: установите overflow: hidden; для родительского элемента. - person Yeti; 12.09.2018

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

person vincent thorpe    schedule 13.05.2016

margin элементов, содержащихся в .child, разрушаются.

<html>
<style type="text/css" media="screen">
    #parent {background:#dadada;}
    #child {background:red; margin-top:17px;}
</style>
<body>
<div id="parent">

    <p>&amp;</p>

    <div id="child">
        <p>&amp;</p>    
    </div>

</div>
</body>
</html>

В этом примере p получает margin из стилей браузера по умолчанию. Браузер по умолчанию font-size обычно составляет 16 пикселей. Имея margin-top более 16 пикселей на #child, вы начинаете замечать смещение его позиции.

person 25thhour    schedule 19.11.2009

У меня тоже была эта проблема, но я предпочел предотвратить взломы с отрицательными полями, поэтому я поставил

<div class="supercontainer"></div>

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

person Zyl    schedule 07.04.2013

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

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;

person schellmax    schedule 14.07.2014

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

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

.parent {
    border:1px solid transparent;
}
person SandRock    schedule 08.01.2015

Если возможно, другое возможное решение - использовать top вместо margin-top.

person lamplightdev    schedule 20.11.2014