CSS 中的负边距如何工作,为啥是 (margin-top:-5 != margin-bottom:5)?
Posted
技术标签:
【中文标题】CSS 中的负边距如何工作,为啥是 (margin-top:-5 != margin-bottom:5)?【英文标题】:How do negative margins in CSS work and why is (margin-top:-5 != margin-bottom:5)?CSS 中的负边距如何工作,为什么是 (margin-top:-5 != margin-bottom:5)? 【发布时间】:2012-07-14 18:18:48 【问题描述】:垂直定位元素的一个常见技巧是使用以下 CSS:
.item
position:absolute;
top:50%;
margin-top:-8px; /* half of height */
height: 16px;
当您在 Chrome 中的度量视图中看到时,您会看到:
但是,当您将鼠标悬停在元素上时,没有显示可视边距,即边距位于边框“外部”并且可以可视化。但负边距不会出现。它们的外观如何?是什么让它与众不同?
为什么margin-top:-8px
和margin-bottom:8px
不一样?
那么负边距是如何工作的以及它们背后的直觉是什么。他们如何“提升”(在margin-top < 0
的情况下)一个项目?
【问题讨论】:
【参考方案1】:只是为了与上面的好答案有所不同,因为这有助于我对负边距有一个直观的理解:
元素上的负边距允许它占用其父容器的空间。
在底部添加(正)边距不允许元素这样做 - 它只会推回下方的任何元素。
【讨论】:
【参考方案2】:我将尝试直观地解释它:
/**
* 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>
【讨论】:
【参考方案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/
我会被纠正。
【讨论】:
【参考方案4】:这里已经提出了很好的观点,但是虽然有很多关于边距渲染是由浏览器完成的信息,为什么 还没有完全回答:
“为什么margin-top:-8px和margin-bottom:8px不一样?”
我们还可以问的是:
为什么正的下边距不会“向上”在元素前面,而正的上边距“向下”在元素后面?
所以我们看到的是,边距的呈现存在差异,具体取决于它们应用到的一侧 - 顶部(和左侧)边距与底部(和右侧)边距不同。
当(简化的)浏览器如何应用样式时,事情变得更加清晰:元素在视口中自上而下呈现,从左上角开始(现在让我们坚持垂直呈现,保持请记住,水平方向的处理方式相同)。
考虑以下 html:
<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>
类似于它们在代码中的位置,这三个框在浏览器中“自上而下”堆叠显示(为了简单起见,我们不会在这里考虑 css3 'flex-box' 的 order
属性模块)。因此,每当样式应用于框 3 时,前面元素的位置(对于框 1 和 2)已经确定,并且为了渲染速度不应再更改。
现在,想象一下框 3 的上边距为 -10px。浏览器不会向上移动所有前面的元素以收集一些空间,而是将框 3 向上推,因此它呈现在顶部(或底部,具体取决于z-index) 任何前面的元素。即使性能不是问题,向上移动所有元素也可能意味着将它们移出视口,因此必须更改当前滚动位置才能使所有内容再次可见。
同样适用于框 3 的底部边距,包括负值和正值:不会影响已评估的元素,只会确定即将到来的元素的新“起点”。因此,设置一个正的底部边距会将 以下 元素向下推;一个消极的人会把他们推高。
【讨论】:
最佳答案。这一个也解释了“为什么”,而其他答案只解释了“如何”。 这个答案帮助我更好地理解了为什么。谢谢@schellmax【参考方案5】:负边距在 css 中有效,理解其(合规)行为主要基于 box model 和边距折叠。虽然某些场景比较复杂,但在研究规范后可以避免很多常见错误。
例如,示例代码的呈现由 calculating heights and margins for absolutely positioned non-replaced elements 中所述的 css 规范指导。
如果我要进行图形表示,我可能会采用这样的方式(不按比例):
边距框在顶部丢失了8px
,但这不会影响内容和填充框。因为您的元素是绝对定位的,所以将元素向上移动 8px 不会对布局造成任何进一步的干扰;静态流入内容并非总是如此。
奖励:
仍然需要说服阅读规范是的方法(而不是articles like this)?我看到您正在尝试将元素垂直居中,那么为什么必须设置 margin-top:-8px;
而不是 margin-top:-50%;
?
嗯,CSS 中的垂直居中是harder than it should be。当以 % 为单位设置 top 或 bottom 边距时,该值计算为 a percentage always relative to the width of the containing block。这是一个相当常见的陷阱,并且在 w3 docos 之外很少描述这个怪癖
【讨论】:
尝试设置 margin-top: -50% 并且元素走出屏幕【参考方案6】:因为您使用了绝对定位,并指定了顶部百分比,所以只有 margin-top 会影响 .item 对象的位置。如果改为使用底部:50% 定位它,则需要 margin-bottom -8px 使其居中,而 margin-top 将不起作用。
边距会影响元素的边界,无论是绝对的,还是相对于相邻元素的定位。想象一下,margin 是它所在元素的基础。它们通常与它的大小相同,但可以在四个边缘中的任何一个或全部上变大或变小。
您的 CSS 告诉浏览器将元素顶部的边距定位在页面下方 50% 的位置。然而,由于所有元素都不是一个像素,浏览器需要知道它的哪一部分在页面下方排成 50%。为了对齐元素的顶部,它使用上边距。默认情况下,这与元素的顶部一致,但您可以使用 CSS 进行更改。
在您的情况下,前 50% 将导致元素的顶部从页面中间开始。通过应用负上边距,浏览器使用距元素顶部 8px 的点(即穿过元素中间的线)作为定位 50% 的位置。
如果您在底部应用正边距,这会扩展浏览器用来将底部定位到远离元素本身的线,从而在底部与下面的任何相邻元素之间产生间隙,或者影响绝对放置的位置基于底部的定位。
【讨论】:
+1。有道理...用视觉提示来增强它会很棒,以完成可视化。【参考方案7】:Margin 是元素外部的间距,就像 padding 是元素内部的间距一样。
设置下边距表示您希望在当前块下方的距离。设置负上边距表示您希望块上方有负间距。负间距本身可能是一个令人困惑的概念,但就像正上边距将内容向下推一样,负上边距将内容拉上。
【讨论】:
+1 我喜欢你的回答。可以通过注入单词onset
和offset
来改进它。的确,很多人总是使用 offset
(negative) 这个词来表示 onset
(positive)。如果您更新答案,此消息将自毁。干杯!
margin-bottom: -8px;
怎么样?为什么margin-bottom:-8px
和margin-top:-8px
不一样?
如果同时使用负上边距和负下边距怎么办?它会被推下还是拉起来?
@Hector Ricardo 上边距和左边距将您的项目向上或向左移动。右侧和底部边距不会将您的项目移动到右侧或底部,而是将项目右侧的内容向左拉入其中,并将项目下方的内容从底部向上拉入其中。应用负的上边距会使项目向上移动,并将其与负的下边距一起应用,然后将下面的内容拉到项目中。【参考方案8】:
-8px 的 margin-top 意味着它将比它具有 0 边距时高 8px。
margin-bottom 为 8px 意味着它下面的东西将比它有 0 边距的情况更向下 8px。
【讨论】:
我只是想让事情变得简单,但我同意,这可能是我写的最糟糕的答案! 我觉得答案很好。不要使用我们一半人都没有得到的高度技术性的答案。margin-bottom: -8px;
怎么样?为什么margin-bottom:-8px
和margin-top:-8px
不一样?
如果同时使用负上边距和负下边距怎么办?它会被推下还是拉起来?以上是关于CSS 中的负边距如何工作,为啥是 (margin-top:-5 != margin-bottom:5)?的主要内容,如果未能解决你的问题,请参考以下文章