Как работают отрицательные поля в CSS и почему (margin-top: -5! = Margin-bottom: 5)?

108

Распространенный прием для вертикального позиционирования элементов - использовать следующий CSS:

.item {
    position:absolute;
    top:50%;
    margin-top:-8px; /* half of height */
    height: 16px;
}

Если смотреть в метрическом представлении, как в Chrome, вы видите следующее:

введите описание изображения здесь

Однако при наведении курсора на элемент визуальное поле не отображается, т.е. поле находится «за пределами» границы и может быть визуализировано. Но отрицательная маржа не отображается. Как они выглядят и чем они отличаются?

Почему margin-top:-8px не то же самое margin-bottom:8px ?

Итак, как работают отрицательные поля и что за ними стоит интуиция. Как они «поднимают» (в случае margin-top < 0) предмет?

кандидат наук
источник

Ответы:

89

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

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

Если бы мне пришлось сделать графическое представление, я бы, вероятно, использовал что-то вроде этого (не в масштабе):

отрицательная верхняя маржа

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

Бонус:

Тем не менее нужно убедить , что читать спецификации является путь (в отличие от статей , как это )? Я вижу, вы пытаетесь центрировать элемент по вертикали, так почему вы должны установить, а не ?margin-top:-8px;margin-top:-50%;

Ну, вертикальное центрирование в CSS сложнее, чем должно быть . При установке даже верхнего или нижнего поля в%, значение всегда рассчитывается в процентах относительно ширины содержащего блока . Это довольно распространенная ошибка, и причуда редко описывается за пределами w3 docos.

ов
источник
84

Попробую пояснить наглядно:

/**
 * explaining margins
 */

body {
  padding: 3em 15%
}

.parent {
  width: 50%;
  width: 400px;
  height: 400px;
  position: relative;
  background: lemonchiffon;
}

.parent:before,
.parent:after {
  position: absolute;
  content: "";
}

.parent:before {
  top: 0;
  bottom: 0;
  left: 50%;
  border-left: dashed 1px #ccc;
}

.parent:after {
  left: 0;
  right: 0;
  top: 50%;
  border-top: dashed 1px #ccc;
}

.child {
  width: 200px;
  height: 200px;
  background: rgba(200, 198, 133, .5);
}

ul {
  padding: 5% 20px;
}

.set1 .child {
  margin: 0;
  position: relative;
}

.set2 .child {
  margin-left: 75px;
  position: relative;
}

.set3 .child {
  margin-left: -75px;
  position: relative;
}


/* position absolute */

.set4 .child {
  top: 50%;
  left: 50%;
  margin: 0;
  position: absolute;
}

.set5 .child {
  top: 50%;
  left: 50%;
  margin-left: 75px;
  position: absolute;
}

.set6 .child {
  top: 50%; /* level from which margin-top starts 
	- downwards, in the case of a positive margin
	- upwards, in the case of a negative margin	
	*/
  left: 50%; /* level from which margin-left starts 
	- towards right, in the case of a positive margin
	- towards left, in the case of a negative margin	
	*/
  margin: -75px;
  position: absolute;
}
<!-- content to be placed inside <body>…</body> -->
<h2><code>position: relative;</code></h2>
<h3>Set 1</h3>
<div class="parent set 1">
  <div class="child">
    <pre>
.set1 .child {
  margin: 0;
  position: relative;
}
		</pre>
  </div>
</div>

<h3>Set 2</h3>
<div class="parent set2">
  <div class="child">
    <pre>
.set2 .child {
  margin-left: 75px;
  position: relative;
}
		</pre>
  </div>
</div>

<h3>Set 3</h3>
<div class="parent set3">
  <div class="child">
    <pre>
.set3 .child {
  margin-left: -75px;
  position: relative;
}
		</pre>
  </div>
</div>

<h2><code>position: absolute;</code></h2>

<h3>Set 4</h3>
<div class="parent set4">
  <div class="child">
    <pre>
.set4 .child {
  top: 50%;
  left: 50%;
  margin: 0;
  position: absolute;
}
		</pre>
  </div>
</div>

<h3>Set 5</h3>
<div class="parent set5">
  <div class="child">
    <pre>
.set5 .child {
  top: 50%;
  left: 50%;
  margin-left: 75px;
  position: absolute;
}
		</pre>
  </div>
</div>

<h3>Set 6</h3>
<div class="parent set6">
  <div class="child">
    <pre>
.set6 .child {
  top: 50%;
  left: 50%;
  margin: -75px;
  position: absolute;
}
		</pre>
  </div>
</div>

Ана
источник
33

Margin - это интервал за пределами вашего элемента, так же как padding - это интервал внутри вашего элемента.

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

Дэвид Хедлунд
источник
2
+1 Мне нравится ваш ответ. Его можно улучшить, вставив слова onsetи offset. Это правда, что многие люди всегда используют слово offset( отрицательный ), когда имеют в виду onset( положительный ). Это сообщение самоуничтожится, если вы обновите свой ответ. Ура!
arttronics
1
О чем margin-bottom: -8px;? Почему margin-bottom:-8pxне то же самое margin-top:-8px?
Рик
27

Верхнее поле -8 пикселей означает, что оно будет на 8 пикселей выше, чем при нулевом поле.

Нижнее поле в 8 пикселей означает, что объект под ним будет на 8 пикселей ниже, чем если бы у него было 0 полей.

Рич Брэдшоу
источник
1
Я просто пытался упростить, но я согласен, это, возможно, худший из моих ответов!
Rich Bradshaw
2
Думаю, ответ неплохой. Никаких технических ответов, которых не понимает половина из нас.
Number945
1
О чем margin-bottom: -8px;? Почему margin-bottom:-8pxне то же самое margin-top:-8px?
Рик
22

здесь уже упоминались хорошие моменты, но хотя есть много информации о том, как браузер выполняет рендеринг полей, ответ на вопрос « почему» еще не получен:

«Почему margin-top: -8px не то же самое, что margin-bottom: 8px?»

мы также можем спросить:

Почему положительное нижнее поле не «увеличивает» предыдущие элементы, тогда как положительное верхнее поле «подталкивает» следующие элементы?

Итак, мы видим разницу в визуализации полей в зависимости от стороны, к которой они применяются - верхние (и левые) поля отличаются от нижних (и правых).

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

рассмотрим следующий html:

<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>

аналогично их положению в коде, эти три блока отображаются в браузере сгруппированными «сверху вниз» ( для простоты мы не будем рассматривать здесь orderсвойство модуля css3 «flex-box» ). Итак, всякий раз, когда стили применяются к блоку 3, позиции предшествующих элементов (для блоков 1 и 2) уже определены, и их больше не следует изменять ради скорости рендеринга.

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

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

Schellmax
источник
ЛУЧШИЙ ответ. Этот ответ также объясняет «почему», тогда как другие ответы объясняют только «как».
Амир Хоссейн Ахмади
1
Этот ответ помог мне лучше понять, почему. Спасибо @schellmax
iRamesh
3

Поскольку вы использовали абсолютное позиционирование и указали верхний процент, только margin-top будет влиять на расположение вашего объекта .item. Если вместо этого вы разместите его с помощью bottom: 50%, тогда вам понадобится margin-bottom -8px для его центрирования, а margin-top не будет иметь никакого эффекта.

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

Ваш CSS сообщает браузеру, что верхняя часть вашего элемента должна располагаться на полях на 50% длины страницы. Однако, поскольку все элементы не являются одним пикселем, браузеру необходимо знать, какая его часть должна выровняться на 50% вниз по странице. Для выравнивания верхней части элемента используется верхнее поле. По умолчанию это соответствует верхней части элемента, но вы можете изменить это с помощью CSS.

В вашем случае верхние 50% приведут к тому, что верх элемента начнется в середине страницы. Применяя отрицательное верхнее поле, браузер использует точку 8 пикселей в элементе сверху (т. Е. Линию через его середину) в качестве места для размещения на 50%.

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

Роб Трики
источник
+1. Имеет смысл ... было бы здорово дополнить его визуальными подсказками, чтобы завершить визуализацию .
PhD
3

Интересно, хорошо ли дан ответ на этот вопрос: как работают поля css и почему это margin-top: -5; не то же самое, что margin-bottom: 5 ;?

Маржа - это расстояние от окружения элемента. margin-top говорит: «... расстояние от окружающей среды, когда мы измеряем от верхней« стороны »элемента« box », а margin-bottom - это расстояние от нижней« стороны »« коробки »». Затем margin-top: 5; относится к периметру верхней «стороны», в данном случае -5; все, что приближается к верхней «стороне», может перекрывать верхнюю «сторону» элемента на 5, а нижняя граница: 5; означает, что расстояние между нижней «стороной» элемента и окружением равно 5.

В основном это, но на это влияют элементы с плавающей точкой и тому подобное: http://www.w3.org/TR/CSS2/box.html#margin-properties .

http://coding.smashingmagazine.com/2009/07/27/the-definitive-guide-to-using-negative-margins/

Меня поправят.

Может быть
источник