【慕课网】一课全面掌握主流CSS布局

警告
本文最后更新于 2020-04-15,文中内容可能已过时。

讲师:KingJ 课程:https://www.imooc.com/learn/1189

指当前元素在父级元素容器中,水平方向是居中显示的

<div id="parent">
  <div id="child">子级元素</div>
</div>
#parent{ text-align:center; } #child{ display:inline-block; }
  • text-align 属性:是为文本内容设置对齐方式
    • left:左对齐
    • center:居中对齐
    • right:右对齐
  • display 属性:
    • block:块级元素
    • inline:内联元素(text-align 属性有效) 当 display 设置为 inline 时,css 中的 width 和 height 属性是无效的
    • inline-block:行内块级元素(块级+内联) width 和 height 属性值是有效的
  • 优点:浏览器兼容性比较好
  • 缺点:text-align 属性具有继承性,导致子级元素的文本也是居中显示的
    • 解决方式:可以在子级元素中设置 text-align 为想要的效果,这样会覆盖父级元素设置的效果
<div class="parent">
  <div class="child">子级元素</div>
</div>
.child{ display:table; margin:0 auto; }
  • margin 属性:外边距
    • 一个值——上右下左四个方向
    • 两个值——第一个表示上下,第二个表示左右
    • 三个值——第一个值表示上,第二个值表示左右,第三个值表示下
      • auto:表示浏览器自动分配,浏览器会等分左右外边距
    • 四个值——分别代表上右下左
  • display
    • 设置为 block 和 table 都可水平居中
    • 设置为 inline 并且在块中添加文字,不会水平居中,
    • 设置为 inline-block 也不会水平居中
  • 优点:只需要对子级元素进行设置就可以实现水平方向居中效果
  • 缺点:如果子级元素脱离文档流,导致 margin 属性的值无效 css 中脱离文档流的方式
    • 设置 float
    • 设置 position 为 absolute
    • 设置 position 为 fixed
<div class="parent">
  <div class="child">居中</div>
</div>
.parent{ position:relative; } .child{ position:absolute; left:50%; transform:translateX(-50%); }
  • 当把当前元素设置为绝对定位之后:
    • 如果父级元素没有开启定位的话,当前元素是相对于页面定位的
    • 如果父级元素开启了定位的话,当前元素是相对于父级元素定位的
    • 除了 position 的默认值 static,其它值都是开启定位
  • left:50%——子级元素的左边相对于父级元素左边的距离是 50%
  • transform:translateX(-50%)——子级元素向左平移自己宽度的 50%单位,这样正好就居中了,这个 50%也可以写成子级元素宽度的一半,但是写 50%更好一些
  • 优点:父级元素是否脱离文档流,不影响子级元素水平居中效果
  • 缺点:transform 属性是 css3 中新增属性,浏览器支持情况不好

不仅仅只有这三种解决方案,但是这三种是比较常见的

垂直居中布局就是指当前元素在父级元素容器中,垂直方向是居中显示的

<div class="parent">
  <div class="child">居中</div>
</div>
.parent{ display:table-cell; vertical-align:middle; }
  • vertical-align 属性:用于设置文本内容的垂直方向对齐方式
    • top:顶部对齐
    • middle:居中对齐
    • bottom:底部对齐
  • display 属性:
    • table:设置当前元素为<table>元素效果
    • table-cell:设置当前元素为<td>元素(单元格)效果
      • 这样就使得 vertical-align 设置居中对齐有效了
  • 优点:浏览器兼容性比较好
  • 缺点:vertical-align 属性具有继承性,导致父级元素的文本也是居中显示的
<div class="parent>
    <div class="child">居中</div>
</div>
.parent{ position:relative; } .child{ position:absolute; top:50%; transform:translateY(-50%); }

参照水平居中的第三种解决方案

  • 优点:无论父级元素是否脱离文档流,不影响子级元素垂直居中效果
  • 缺点:transform 属性是 CSS3 中新增属性,浏览器支持情况不好

居中布局实际上就是既要水平方向居中,也要垂直方向居中

去上文找,子级元素的 display 最好设置为 block(即默认值)

如果不考虑浏览器兼容性,是优于上一种方法的

简单来说,多列布局就是几个元素呈现水平方式排列的效果

两列布局一般情况下是指定宽+自适应布局,两列中左列是确定的宽度,右列是自动填满剩余所有空间的一种布局效果

<div class="parent">
  <div class="left">左:定宽</div>
  <div class="right">右:自适应</div>
</div>
.left{ width:100px; float:left; } .right{ margin-left:100px; }
  • 如果只给左列设置 float:left,视觉上是实现了两列布局,但是实际上是左列把右列的一部分给覆盖了,所以要给右列设置 margin-left:(左列的宽度)
  • 优点:实现方式简单
  • 缺点:
    • 自适应元素的 margin 属性值需要与定宽元素的属性值保持一致
    • 定宽元素浮动与自适应元素不浮动导致浏览器兼容性不好(老版本浏览器中会有空白)
    • 若在自适应这列中存在子级元素或后代元素,并且使用了清除浮动(clear),显示是有问题的
<div class="parent">
  <div class="left">左:定宽</div>
  <div class="right-fix">
    <div class="right">右:自适应</div>
  </div>
</div>
.left{ position:relative; } .right-fix{ float:right; width:100%; margin-left:-100px; }
<div class="parent">
  <div class="left">左:定宽</div>
  <div class="right">右:自适应</div>
</div>
.left{ width:100px; float:left; } .right{ overflow:hidden; }
  • overflow:hidden 在此处的作用是开启 BFC 模式
    • 当前元素的内部环境与外界完全隔离
  • 优点:
    • 上述解决方案中的问题在此处解决方案中都没有
    • 因为开启了 BFC 模式,所以不存在老版本中出现空白的情况
  • 缺点:
    • overflow 属性不不仅解决了两列布局问题,同时设置了内容溢出的情况,比如这时一旦右列出现内容,就会被隐藏
<div class="parent">
  <div class="left">左:定宽</div>
  <div class="right">右:自适应</div>
</div>
.parent{ display:table; table-layout:fixed; } .left,.right{ display:table-cell; } .left{ width:100px; }
  • parent 的属性设置为 display:table;会使表格的单元格自动分配,默认是等分,如果一列设置为定宽,那么另一列会自适应
  • 表格会出现双边框,所以 table-layout:fixed 可以解决该问题
  • 优点:浏览器兼容性比较好
  • 缺点:将所有元素的 display 属性设置为 table 相关值,受到相应制约

三列布局一般情况下是指三列中左边两列是确定的宽度,右边一列是自动填满剩余所有空间的一种布局效果。

  • 定宽+定宽+自适应
  • 定宽+自适应+定宽

同两列布局没有差异

又称三行三列布局,是一个完整页面的布局。圣杯布局注意实现中间主题部分中的左右定宽+中间自适应的布局效果。

#left{ float:left; } #center{ margin-left:400px; margin-right:400px; } #right{ float:right; }
  • 如果 center 只设置 margin-left 和 margin-right,那么会出现问题如下:

  • 问题出现的原因是:当兄弟元素中,前面的没有浮动,而后面的浮动了,那么浮动的元素是不允许超过前面的元素的,所以这两个还得是垂直方向排列
  • 解决方法,将浮动的元素与不浮动的元素调换位置,但是实际显示的还是浮动的元素在后面
  • center 作为页面的核心,数据(主要内容)被放在最后面,不利于搜索引擎抓取
#parent{ /* 解决高度坍塌 */ height: 300px; /* left元素的宽度 */ margin-left: 400px; /* right元素的宽度 */ margin-right:
400px; } #left, #center, #right { height: 300px; float: left; } #left, #right { width: 400px; } #left {
background-color: #c9394a; /* 将当前元素从当前行移动到上一行同一位置,刚好父级宽度的百分之百*/ margin-left: -100%; /*
开启定位,这样可以使用left属性 */ position: relative; /* 再移动到自己的宽度值*/ left: -400px; } #center { /*
为父级元素宽度的百分之百 */ width: 100%; background-color: green; } #right { background-color: #cccccc; /*
刚好移动到上一行最右边的位置 */ margin-left: -400px; position: relative; /* 再往右移动自己的定宽 */ right: -400px; }
<div id="parent">
  <div id="center"></div>
  <div id="left"></div>
  <div id="right"></div>
</div>
  • 优点:center 放在前面,有利于搜索引擎抓取
  • 缺点:稍稍有点复杂

双飞翼布局最早是淘宝团队提出,是针对圣杯布局的优化解决方案。主要是优化了圣杯布局中开启定位的问题

#parent { /* 解决高度坍塌 */ height: 300px; } #left, #center, #right { height: 300px; float: left; } #left, #right {
width: 400px; } #left { background-color: #c9394a; /* 将当前元素从当前行移动到上一行同一位置,刚好父级宽度的百分之百*/
margin-left: -100%; } #center { /* 为父级元素宽度的百分之百 */ width: 100%; background-color: green; } #right {
background-color: #cccccc; /* 刚好移动到上一行最右边的位置 */ margin-left: -400px; } #inner{ /*
解决center与两边块重合的问题 */ height: 300px; background-color: pink; /* left元素的宽度 */ margin-left: 400px; /*
right元素的宽度 */ margin-right: 400px; }
<div id="parent">
  <div id="center">
    <!-- 解决position问题 -->
    <div id="inner"></div>
  </div>
  <div id="left"></div>
  <div id="right"></div>
</div>

等分布局就是指一行被分为若干列,每一列的宽度是相同的值

.col1,.col2,.col3,.col4{ float: left; width: 25%; box-sizing: border-box; height: 300px; } .col1{ background-color:
pink; } .col2{ background-color: blue; } .col3{ background-color: orange; } .col4{ background-color: green; }
<div id="parent">
  <div class="col1"><p>1</p></div>
  <div class="col2"><p>2</p></div>
  <div class="col3"><p>3</p></div>
  <div class="col4"><p>4</p></div>
</div>
<div id="parent">
  <div class="col">
    <p>1</p>
  </div>
  <div class="col">
    <p>2</p>
  </div>
  <div class="col">
    <p>3</p>
  </div>
  <div class="col">
    <p>4</p>
  </div>
</div>
#parent{ width: 100%; display: table; table-layout: fixed; } .col1{ display: table-cell; }