Margin-Top нажимает внешний div вниз

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

Вот пример фрагмента кода. Спасибо!

div#header{
	width: 100%;
	background-color: #eee;
	position: relative;
}

div#header h1{
	text-align: center;
	width: 375px;
	height: 50px;
	margin: 50px auto;
	font-size: 220%;
	background: url('../../images/name_logo.png') no-repeat;
}
<div id="header">
	<h1>Title</h1>
	<ul id="navbar"></ul>
</div>

Ответ 2

У меня нет четкого объяснения, почему это происходит, но я исправил это, изменив top-margin на top-padding или добавив display: inline-block к стилю элемента.

EDIT: Это моя теория

У меня есть ощущение, что это имеет какое-то отношение к тому, как поля рушится (объединены).

from W3C Collapsing Marginsing:

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

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

Бывают ситуации, когда поля не сжимаются, что может стоить играть с (от Collapsing Margins):

* floated elements
* absolutely positioned elements
* inline-block elements
* elements with overflow set to anything other than visible (They do not collapse margins with their children.)
* cleared elements (They do not collapse their top margins with their parent block’s bottom margin.)
* the root element

Ответ 3

Вот некоторые из способов избежать сжимания маржи между элементами parent-child. Используйте тот, который лучше подходит для остальной части вашего стиля:

  • Задайте display иначе, чем block.
  • Задайте float иначе, чем none.
  • Удалите поле и вместо этого используйте padding. Например, если у вас margin-top: 10px, замените на padding-top: 10px;.
  • Удалите поле и вместо этого используйте position (absolute или relative) с атрибутами top, bottom и т.д. Например, если у вас есть margin-top: 10px, замените на position: relative; top: 10px;.
  • Добавьте padding или border в сторону, где поля сворачиваются, в элемент parent. Граница может быть 1px и прозрачна.
  • Задайте overflow, кроме visible, элементу parent.

Ответ 4

display: flex будет работать в этом случае. Предоставьте родительский элемент display: flex;, а затем укажите маржу в соответствии с вашим требованием к тегу h1.

Ответ 5

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

Во-первых, есть легкое объяснение проблемы с корнем. Из-за того, как работает крах, если первый элемент внутри контейнера имеет верхний предел, то верхнее поле эффективно применяется к самому родительскому контейнеру. Вы можете проверить это самостоятельно, выполнив следующие действия:

<div>
    <h1>Test</h1>
</div>

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

Итак, там легко исправить это, не прибегая к странным хакам, так как большинство сообщений здесь (никаких оскорблений не предназначено, это просто правда) - просто вернитесь к оригинальному объяснению - ...if the first element inside a container has a top margin... - После этого, вам, следовательно, нужен первый элемент в контейнере, чтобы НЕ иметь верхний край. Хорошо, но как вы это делаете без добавления элементов, которые не влияют семантически на ваш документ?

Легко! Псевдо-элементы! Вы можете сделать это через класс или предварительно определенный mixin. Добавьте псевдо-элемент :before:

CSS через класс:

.top-margin-fix:before {   
    content: ' ';
    display: block;
    width: 100%;
    height: .0000001em;
}

При этом, следуя приведенному выше разметке, вы должны изменить свой div как таковой:

<div class="top-margin-fix">
    <h1>Test</h1>
</div>

Почему это работает?

Первый элемент в контейнере, если он не имеет верхнего поля, задает положение начала верхнего поля верхнего элемента. Добавляя псевдоэлемент :before, браузер фактически добавляет в родительский контейнер перед вашим первым элементом не семантический (другими словами, хороший для SEO) элемент.

Q. Почему высота:.0000001em?

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

Теперь вы можете добавить класс (или лучше, в SASS/LESS, mixin!), чтобы исправить эту проблему, вместо добавления странных стилей отображения, которые могут вызвать неожиданные последствия, когда вы хотите делать другие вещи с помощью своих элементов, целенаправленно устраняя поля на элементах и ​​/или заменяя его прокладкой или странные стили позиции/флота, которые на самом деле не предназначены для решения этой проблемы.

Ответ 6

Запустите этот вопрос сегодня.

overflow: hidden не работал должным образом, когда у меня было больше элементов.

Итак, я попытался изменить свойство отображения родительского div и display: flex работал.

Надеюсь, это поможет кому-то.:)

Ответ 7

Добавление небольшого бита дополнения к верхнему элементу родительского элемента может устранить эту проблему.

.parent{
  padding-top: 0.01em;
}

Ответ 8

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

  1. Наибольшая маржа выиграет (применяется).

  2. если у любого из них есть маржа, то оба будут иметь одинаковое значение.

Решения

  1. применить границу к родительскому элементу, который разделяет родительский и дочерний элементы.
  2. применить padding к parent, который разделяет parent и child.
  3. применить переполнение, а не видимый на родителя.
  4. используйте до или после, чтобы создать виртуальный элемент в родительском div, который может отличаться от дочернего и родительского полей.
  5. создать один HTML-элемент между полями применяется дочерний и родительский также может разделить их.