Margin-Top сдвинуть внешний div вниз

126

У меня есть div заголовка в качестве первого элемента в моем div-оболочке, но когда я добавляю верхнее поле к h1 внутри 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>

Дэнни
источник

Ответы:

194

вставьте overflow:autoродителя, div
подробнее в этой ссылке

Хуан Пабло
источник
29
overflow:hiddenлучше в 90% случаев.
vsync
1
Почему лучше overflow: hidden?
peterchon
5
@peterchon - потому что auto может вызывать полосы прокрутки
vsync
3
больше не работает, ответ @ SW4 в этой ссылке лучше
am05mhz
1
overflow: hiddenили overflow: autoможет вызвать нежелательные побочные эффекты, некоторые из которых вы можете не заметить с первого взгляда. Я обнаружил, что изменение marginна paddingпомогает, как следует из ответа ниже. Однако до сих пор не понимаю, почему происходит вся проблема.
Гилад Барнер
34

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

РЕДАКТИРОВАТЬ: это моя теория

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

из W3C Collapsing Margins :

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

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

Бывают ситуации, когда поля не сжимаются, с которыми, возможно, стоит поиграть (из 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
digitaldreamer
источник
3
Кроме того, отступ или граница на элементе со свернутым полем (внутренним) не сворачивают его.
Anonymous
Это сработало для меня - в моем контейнере были абсолютные элементы (раскрывающийся список), поэтому overflow: auto не работал.
mwilcox
17

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

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

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

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

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

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

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

Легко! Псевдо-элементы! Вы можете сделать это с помощью класса или предопределенного миксина. Добавьте :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) элемент в родительский контейнер перед вашим первым элементом.

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

A. Высота требуется, чтобы браузер подтолкнул элемент поля вниз. Эта высота фактически равна нулю, но она по-прежнему позволяет добавлять отступы к самому родительскому контейнеру. Поскольку он фактически равен нулю, он также не повлияет на макет контейнера. Прекрасный.

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

dudewad
источник
2
.0000001em действительно округляется до нуля в IE11, что нарушает ваше исправление. Когда я меняю его на .01em, он работает.
Esger 05
1
Я полагаю, что .01em будет достаточно, чтобы по-прежнему эффективно равняться нулю. Хорошая точка зрения. С другой стороны, теперь, когда наступил 2018 год, многие из нас скоро откажутся от поддержки IE11, особенно с недавним объявлением о том, что MS снова будет создавать новый браузер (за исключением этого раза, на основе хрома, что означает, что теоретически - совсем не отстой). : D
dudewad 06
2

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

Bijay
источник
0

Столкнитесь с этой проблемой сегодня.

overflow: hidden не сработало, как ожидалось, когда за мной последовало больше элементов.

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

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

Либин
источник
0

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

.parent{
  padding-top: 0.01em;
}

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

adamspruijt
источник
0

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

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

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

Решения

  1. применить границу к родителю, которая разделяет родителя и ребенка.
  2. применить дополнение к родительскому элементу, которое разделяет родительский и дочерний элементы.
  3. применить переполнение, а не видимое для родителя.
  4. используйте before или after для создания виртуального элемента в родительском div, который может отличаться от дочернего и родительского полей.
  5. создать один элемент html между дочерним элементом и родительским элементом, который также может разделять их.
Ishu
источник