欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

深入 CSS 负边距

程序员文章站 2022-06-14 14:55:14
...

老实说,个人从来没有重视过 CSS,觉得很简单,没有可学之处。但随着使用和认识的深入,才发现 CSS 也博大精深。加上 CSS3 的出现,以前需要 JavaScript 的地方,现在用 CSS 亦可以轻松实现。相信未来,CSS 一定能大放异彩!这次一起和大家聊一聊 CSS 中的负边距。

负边距的特点

在正式介绍负边距之前,我们先回顾一下文档流。所谓的文档流,指的是元素排版布局过程中,元素会自动从左往右,从上往下的流式排列。并最终窗体自上而下分成一行行, 并在每行中按从左至右的顺序排放元素。脱离文档流即是元素打乱了这个排列,或是从排版中拿走。

脱离文档流

要使一个元素脱离文档流有两种方式:

  1. 使用浮动(float):值为 left、right 均会使元素脱离文档流
  2. 使用定位(position):值为 absolute、fixed 的元素脱离文档流,其它不脱离文档流

未脱离文档流元素

<div class="box1">A</div>
<div class="box2">B</div>
<div class="box3">C</div>

深入 CSS 负边距
我们先来看一看正边距,当我们给三个 div 分别设置上边距时,自然而然,三个元素都会隔开一定间隙。

深入 CSS 负边距
当我们给三个 div 分别设置负上边距时,这时我们看到元素将被拉进指定的方向。

我们可以这样来思考,既然正边距是相隔距离;那值为负,自然就反过来了,就是相叠距离。

当我们设置某个元素的 margin-rightmargin-bottom 为负值,而非 margin-leftmargin-top 时,这时元素并不会如你所想的那样向右或下移动,而是将后续的元素拖拉进来,覆盖本来的元素。

造成这两种不同现象的原因时文档流只会向左和向上,不可能向右和向下

如果没有设定 width 属性,设定负 margin-leftmargin-right 会将元素拖向对应的方向,并增加宽度,此时的 margin 的作用就像 padding 一样。没有设置width 的元素的宽度值是由包围元素的宽度来计算出来的,然后减去 margin,所以就会得到实际上比原始元素更宽的值。

总结

  • margin-leftmargin-top:影响自身元素,将向指定方向偏移
  • margin-rightmargin-bottom:影响相邻元素,将其拖入指定方向

已脱离文档流元素

绝对定位元素(absolute)

设置的 margin 的方向为 top 或者 left

当设置负值的 margin 的方向为 top 或者 left 的时候,元素也会按照设置的方向移动相应的距离。

设置的 margin 的方向为 bottom 或者 right

由于设置绝对定位的元素已经脱离了标准文档流,所以,设置 margin-right/bottom 对后面的元素并没有影响。

浮动元素(float)

其实浮动元素和未脱离文档流的元素在负边距上表现类似,只不过浮动有左和右两种浮动。对应文档流,我们可以称浮动元素为浮动流。

当负值的 margin 的方向与浮动流方向一直时,则元素会往对应的方向移动对应的距离。

当负值的 margin 的方向与浮动流方向相反时,则元素本身不动,元素之前或者之后的元素会向该元素的方向移动相应的距离。

总结
浮动流不像文档流只是向上和向左,它是可以向左和向右的。除了这点外,其实和未脱离文档流元素表现差不多。

负边距的应用

三列布局(static 元素)

li {
    line-height: 1.5em;
}
.col2 {
    margin-left: 200px;
}
.col3 {
    margin-left: 400px;
}
.top {
    margin-top: -3em;
}
<ul>
    <li class="col1">第一列第一排</li>
    <li class="col1">第一列第二排</li>
    <li class="col2 top">第二列第一排</li>
    <li class="col2">第二列第二排</li>
    <li class="col3 top">第三列第一排</li>
    <li class="col3">第三列第二排</li>
</ul>

深入 CSS 负边距

这种例子主要利用了负上边距会将元素上移,同时不会像 relative 元素仍然占据之前的位置的特点。

多列布局之清除最后一列右边距(static 元素)

深入 CSS 负边距

我们常常会遇到如图所示的布局,他要求每一列距离右边一小段间隔,而最后一列没有间隔。最常见的解决方案就是给最后一列加上一个class,设置其右边距为零。但现在我们有一种更酷的解决方案,不需要增加一个新的class(尤其在循环时,不太容易确定元素给其加上class)。

.container {
    width: 860px;
    margin: 0 auto;
    margin-top: 80px;
    border: 1px solid #ccc;
    overflow: hidden;
}
ul {
    list-style-type: none;
    margin-right: -20px;
}
li {
    float: left;
    width: 200px;
    margin-top: 5px;
    margin-bottom: 5px;
    margin-right: 20px;
    background: #00f;
    color: #fff;
}
<div class="container">
    <ul>
        <li>子元素1</li>
        <li>子元素2</li>
        <li>子元素3</li>
        <li>子元素4</li>
        <li>子元素5</li>
        <li>子元素6</li>
        <li>子元素7</li>
        <li>子元素8</li>
    </ul>
</div>

这种例子主要利用了没有给定width的元素,设定负 margin-left/margin-right 会增加元素的宽度。

左边固定,右边自适应的两列布局(float 元素)

.container {
    float: left;
    width: 100%;
    margin-right: -300px;
    background: burlywood;
}
.container .content {
    margin-right: 310px;
}
.sidebar {
    float: left;
    width: 300px;
    background: #f00;
}
<div class="container">
    <div class="content">
        中间内容区域
    </div>
</div>
<div class="sidebar">侧边栏区域</div>

这种例子主要利用了给一个浮动元素加上相反的负边距时,另一浮动元素会认为前者的宽度减少相应的边距值。但有意思的是,前者的宽度并没有受影响,他还是占据了屏幕100%的宽度,另一元素就像是浮动在他右边的区域之上。

深入 CSS 负边距

圣杯布局(float 元素)

以前学习CSS的时候,就听说了圣杯布局。当时觉得特高大上,“圣杯”一词完全升华了布局本身,上升到了一个神话高度。事实上,他就是利用了本文的主题负边距来实现的。废话不多说了,直接上代码。

圣杯布局原文

.container {
    padding: 0 300px 0 200px;
}
.content {
    float: left;
    width: 100%;
    background: #f00;
}
.left {
    position: relative;
    left: -200px;
    float: left;
    width: 200px;
    margin-left: -100%;
    background: #0f0;
}
.right {
    position: relative;
    right: -300px;
    float: left;
    width: 300px;
    margin-left: -300px;
    background: #00f;
}
<div class="container">
    <div class="content">中间内容区域</div>
    <div class="left">左侧边栏区域</div>
    <div class="right">右侧边栏区域</div>
</div>

深入 CSS 负边距

注意点:

  • 中间内容放在最上面,保证先渲染
  • 精髓还是负边距

双飞翼布局(float 元素)

说完圣杯布局,我们再来聊一聊双飞翼布局。又是一个听起来高大上的布局名,由淘宝首创。两个布局实现的效果都是一样,只不过文档结构和样式略有区别,当然核心还是负边距的应用。

.container {
    float: left;
    width: 100%;
    background: #f00;
}
.content {
    margin-left: 200px;
    margin-right: 300px;
}
.left {
    float: left;
    width: 200px;
    margin-left: -100%;
    background: #0f0;
}
.right {
    float: left;
    width: 300px;
    margin-left: -300px;
    background: #00f;
}
<div class="container">
    <div class="content">中间内容区域</div>
</div>
<div class="left">左侧边栏区域</div>
<div class="right">右侧边栏区域</div>

深入 CSS 负边距

区别:

  • 圣杯布局是中间栏在添加相对定位,并配合 left 和 right 属性,效果上表现为三栏是单独分开的
  • 双飞翼布局是在中间栏的 div 中嵌套一个 div,内容写在嵌套的 div 里,然后对嵌套的 div 设置 margin-left 和 margin-right,效果上表现为左右两栏在中间栏的上面,中间栏还是 100% 宽度,只不过中间栏的内容通过 margin 的值显示在中间
  • 通过两者实现的截图红色区域可以很明显看到两者区别

参考