129

垂直定位元素的一个常见技巧是使用以下 CSS:

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

当在 Chrome 中的度量视图中看到时,您会看到以下内容:

在此处输入图像描述

但是,当您将鼠标悬停在元素上时,没有显示可视边距,即边距在边界“外部”并且可以可视化。但负边距不会出现。它们看起来如何,是什么让它与众不同?

为什么margin-top:-8px 不一样 margin-bottom:8px

那么负边距是如何工作的,它们背后的直觉是什么。他们如何“撞上”(如果是margin-top < 0)一个项目?

4

8 回答 8

107

负边距在 css 中是有效的,理解它们的(合规)行为主要基于盒子模型和边距折叠。虽然某些场景更复杂,但在研究规范后可以避免许多常见错误。

例如,示例代码的呈现由 css 规范指导,如为绝对定位的非替换元素计算高度和边距中所述。

如果我要进行图形表示,我可能会使用这样的东西(不按比例):

负上边距

顶部的边距框丢失8px,但这不会影响内容和填充框。因为您的元素是绝对定位的,所以将元素向上移动 8px 不会对布局造成任何进一步的干扰;静态流入内容并非总是如此。

奖金:

仍然需要说服阅读规范是要走的路(而不是像这样的文章)?我看到您正在尝试将元素垂直居中,那么为什么必须设置margin-top:-8px;而不是margin-top:-50%;

好吧,CSS 中的垂直居中比它应该的要难。当以 % 为单位设置边距或边距时,该值始终以相对于包含块的宽度的百分比计算。这是一个相当常见的陷阱,并且在 w3 docos 之外很少描述这个怪癖

于 2012-07-16T06:20:18.037 回答
95

我将尝试直观地解释它:

/**
 * 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>…&lt;/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>

于 2012-07-15T22:09:19.197 回答
40

边距是元素外部的间距,就像填充是元素内部的间距一样。

设置下边距表示您希望在当前块下方的距离。设置负上边距表示您希望块上方有负间距。负间距本身可能是一个令人困惑的概念,但就像正上边距将内容向下推一样,负上边距将内容向上拉。

于 2012-07-15T20:12:09.583 回答
31

-8px 的 margin-top 意味着它将比它具有 0 边距时高 8px。

8px 的 margin-bottom 意味着它下面的东西将比它有 0 边距的情况更向下 8px。

于 2012-07-15T20:09:25.747 回答
28

这里已经提出了很好的观点,但是虽然有很多关于浏览器如何完成边距渲染的信息,但为什么还没有完全回答:

“为什么 margin-top:-8px 与 margin-bottom:8px 不一样?”

我们还可以问的是:

为什么正的下边距不会“向上”在元素之前,而正的上边距“向下”在元素之后?

所以我们看到的是,边距的呈现会有所不同,这取决于它们应用到的一侧——顶部(和左侧)边距与底部(和右侧)边距不同。

当(简化)查看浏览器如何应用样式时,事情变得更加清晰:元素在视口中自上而下呈现,从左上角开始(现在让我们坚持垂直渲染,请记住水平的也一样)。

考虑以下html:

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

类似于它们在代码中的位置,这三个盒子在浏览器中“自上而下”地堆叠在一起(为了简单起见,我们不会在这里考虑ordercss3 'flex-box' 模块的属性)。因此,每当样式应用于框 3 时,前面元素的位置(对于框 1 和 2)已经确定,并且为了渲染速度不应再更改。

现在,想象框 3 的上边距为 -10px。浏览器不会向上移动所有前面的元素以收集一些空间,而是将框 3 向上推,因此它呈现在顶部(或底部,具体取决于 z-index ) 任何前面的元素。即使性能不是问题,向上移动所有元素也可能意味着将它们移出视口,因此必须更改当前滚动位置才能使所有内容再次可见。

这同样适用于框 3 的底部边距,无论是负的还是正的:不是影响已经评估的元素,而是为即将到来的元素确定一个新的“起点”。因此,设置一个正的底部边距会将以下元素向下推;消极的人会把他们推高。

于 2012-07-16T09:06:13.537 回答
3

因为您使用了绝对定位,并指定了顶部百分比,所以只有 margin-top 会影响 .item 对象的位置。相反,如果您使用底部:50% 定位它,那么您需要 margin-bottom -8px 将其居中,而 margin-top 将无效。

边距会在定位元素方面影响元素的边界,无论是绝对像您的情况,还是相对于相邻元素。想象一下,margin 是它所在元素的基础。它们通常与它的大小相同,但可以在四个边缘中的任何一个或所有边缘上做得更大或更小。

您的 CSS 告诉浏览器将元素顶部的边距定位在页面下方 50% 的位置。然而,由于所有元素都不是一个像素,浏览器需要知道它的哪一部分在页面下方排成 50%。为了对齐元素的顶部,它使用上边距。默认情况下,这与元素的顶部一致,但您可以使用 CSS 对其进行更改。

在您的情况下,前 50% 将导致元素的顶部从页面中间开始。通过应用负上边距,浏览器使用从顶部到元素 8px 的点(即穿过它中间的线)作为定位 50% 的位置。

如果您对底部应用正边距,这会扩展浏览器用于将底部定位到远离元素本身的线,从而在底部与下面的任何相邻元素之间产生间隙,或者如果定位基于底端。

于 2012-07-15T20:38:38.873 回答
3

我想知道这个问题是否得到了很好的回答:css margins 是如何工作的,为什么它是 margin-top:-5; 与 margin-bottom:5; 不一样?

边距是与元素周围的距离。margin-top 表示“......当我们从元素的'box'的顶部'side'测量时与周围环境的距离,margin-bottom 是与'box'底部'side'的距离”。然后 margin-top:5; 与顶部“侧面”周长有关,在这种情况下为-5;从顶部“边”接近的任何东西都可以与元素的顶部“边”重叠 5,并且 margin-bottom: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/

我接受纠正。

于 2014-01-16T02:17:02.447 回答
1

只是为了与上面的好答案有所不同,因为这有助于我对负边距有一个直观的理解:

元素上的负边距允许它占用其父容器的空间。

在底部添加(正)边距不允许元素这样做 - 它只会推回下方的任何元素。

于 2021-01-13T22:15:44.190 回答