CSS 布局实践
常见的 CSS 布局单位
-
像素 px:
- CSS像素:为web开发者提供,在 CSS 中使用的一个抽象单位
- 物理像素:与硬件密度有关
- 一个CSS像素可对应多个物理像素
-
百分比 %:相对于直接父元素
-
相对长度单位
- em:相对于父元素的 font-size,默认 16 px
- rem:相对于根元素的 font-size
-
视口相关单位
- vw:视窗宽度的百分之一
- vh:视窗高度的百分之一
- vmin:vw 和 vh 中的最小值
- vmax:vw 和 vh 中的最大值
应用场景:
- 使用 px:适配少部分移动设备,且分辨率对页面影响不大
- 使用 rem:适配各种移动设备(例如 iPhone 和 iPad等分辨率差别比较大的设备)
两栏布局
一般的两栏布局:左边一栏宽度固定,右边一栏宽度自适应
实现:
- 浮动法
- 左边元素宽度固定设置为 200px,并且设置左浮动
- 右边元素的 margin-left 设置为 200px,宽度设置为 auto(撑满整个父元素)
-
.outer { height: 100px; } .left { float: left; width: 200px; } .right { margin-left: 200px; width: auto; }
- BFC法
-
左边元素同上
-
右边元素设置 overflow:hidden; 触发BFC,不会与浮动元素发生重叠
-
.outer { height: 100px; } .left { float: left; width: 200px; } .right { margin-left: 200px; overflow: hidden; }
-
BFC,Block Formmatting Context,块级格式化上下文,形成一个完全独立的布局环境
-
触发 BFC 的 CSS 属性
-
overflow: hidden
-
display: inline-block
-
position: absolute
-
position: fixed
-
display: table-cell
-
display: flex
-
BFC 解决的问题:
- float 脱离文档流,高度塌陷
- margin 边距重叠
- 两栏布局
-
3. 利用 flex
- 左边设置固定宽度
- 右边设置 flex1
-
.outer { display: flex; height: 100px; } .left { width: 200px; } .right { flex: 1; }
4. 利用绝对定位,父级元素设置为相对定位
- 左边元素绝对定位,并且宽度设置为 200 px
- 右边元素 margin-left 设置为 200px
-
.outer { position: relative; height: 100px; } .left { position: absolute; width: 200px; height: 100px; } .right { margin-left: 200px; }
5. 利用绝对定位,父级元素设置为相对定位
- 左边元素设置宽度 200px
- 右边元素使用绝对定位,左边定位为 200px,其余定位为0
-
.outer { position: relative; height: 100px; } .left { width: 200px; } .right { position: absolute; left: 200px; top: 0; right: 0; bottom: 0; }
6. grid 布局
- 父元素设置 grid 布局,然后设置每列元素的宽度
-
.outer { display: grid; grid-template-columns: 200px 1fr; /* fr 是比例系数, 如果只有一个设置了 fr, 则占满剩余空间 */ }
三栏布局
三栏布局一般指:页面左右两栏宽度固定,中间自适应
实现:
-
利用绝对定位
- 左右两栏设置为绝对定位,中间设置对应方向的 margin 值
-
.outer { position: relative; height: 100px; } .left { position: absolute; width: 100px; height: 100px; } .right { position: absolute; top: 0; right: 0; width: 200px; height: 100px; } .center { margin-left: 100px; margin-right: 200px; height: 100px; }
-
利用 flex 局部
- 左右固定大小,中间设置 flex:1
-
.outer { display: flex; height: 100px; } .left { width: 100px; height: 100px; } .right { width: 200px; height: 100px; } .center { flex: 1; }
-
利用浮动
-
左右两栏设置固定大小,并设置对应方向的浮动
-
中间一栏在 html 中应该放在左右元素之后,中间一栏设置左右方向的 margin
-
.outer { height: 100px; } .left { float: left; width: 100px; height: 100px; } .right { float: right; width: 200px; height: 100px; } .center { margin-left: 100px; margin-right: 200px; height: 100px; }
-
如果 html 顺序为
原因:浮动的定位元素是上一个未浮动的元素
-
-
圣杯布局,利用浮动和负边距实现
-
父级元素设置左右的 padding
-
三列均设置向左浮动,html 中间一列放在最前面,可以先将主要内容渲染
-
宽度设置未父级元素的宽度,因此后面两列都被挤到了下一行,通过设置 margin 赋值将其移动到上一行,再利用相对定位,定位到两边
-
<div class="outer"> <div class="center">C</div> <div class="left">L</div> <div class="right">R</div> </div> <style> .outer { height: 100px; padding-left: 100px; padding-right: 200px; } .left { float: left; /* 负margin 让元素的左边外框移动到 center 的左边*/ margin-left: -100%; /* 百分比的参考是center(上一个元素)的宽度 */ /* 相对定位 让元素向左移自身的宽度 */ position: relative; left: -100px; width: 100px; height: 100px; } .right { float: left; /* 此处也可以右浮动,结果不变 */ margin-left: -200px; /* 自身的宽度 */ position: relative; left: 200px; /* 向右移自身的宽度 */ width: 200px; height: 100px; } .center { float: left; width: 100%; height: 100px; } </style>
-
右元素也可以设置为右浮动,解释如下:
首先,float 是元素会根据设置的属性值向左或者向右浮动,直到它的外边缘碰到包含框或另一个浮动框的边框为止。
本来 outer 的 width 就已经被 center 完全占满(右元素相对于父元素 outer 浮动,无法待在outer那一行)了,元素会溢出,下移一行;margin-left 负值让 float 浮动的起点向左移动,让其可以相对于另一个浮动元素 center 进行浮动,不再溢出,从而可以移到上一行(center 所在的行)
-
-
双飞翼布局
- 相对于圣杯布局来说,左右位置的保留是通过中间列(需要增加一个 wrapper 包裹)的 margin 值来实现的,而不是父元素的 padding。本质上来说,也是通过浮动和外边距负值来实现的
-
<div class="outer"> <div class="wrapper"> <div class="center">C</div> </div> <div class="left">L</div> <div class="right">R</div> </div> <style> .outer { height: 100px; } .left { float: left; margin-left: -100%; width: 100px; height: 100px; } .right { float: left; margin-left: 200px; width: 200px; height: 100px; } /* 中间列的外包裹 */ .wrapper { float: left; width: 100%; height: 100px; } .center { margin-left: 100px; margin-right: 200px; height: 100px; } </style>
margin 负值的原理
margin的值(正值)是根据参考线向下或向右计算的
- top 和 left 的参考线是上(左)一个元素的下(右)margin 外框
- bottom 和 right 的参考线是本元素的下(右)content 外框
当一个元素的 margin 值是负值时,会向左(上)移动
- left 和 top 本质是改变了参考线(向左移或向上移)
- 不同于 position: absolute 的是,其后的元素会跟随移动
margin 负值的用途:
-
实现水平垂直居中
<div class="absolute"></div> <style> .absolute { position: absolute; top: 50%; left: 50%; /* 通过绝对定位,将元素左上角的点移动到父元素中心点 */ width: 200px; height: 100px; margin-left: -100px; margin-top: -50px; /* 通过负margin,移动本元素宽度或高度的一半 */ /* 对于不确定本元素宽高的情况,可以用以下代替负 margin transform: translate3d(-50%, -50%, 0); */ background-color: #ccc; } </style>
-
圣杯布局
-
双飞翼布局
水平垂直居中的实现
-
自身位移法
利用绝对定位,先将元素的左上角通过 top:50%; left:50%; 定位到父元素的中心,再通过 tanslate 调整元素的中心点到父元素的中心。需要考虑浏览器兼容问题
.parent { position: relative; } .child { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
-
margin 拉开法
利用绝对定位,设置四个方向的值都是0,然后将 margin 设置为 auto,由于宽高固定,因此可以实现对应方向平分,即水平垂直居中。该方法适合盒子有宽高的情况
.parent { position: relative; } .child { position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; }
-
负 margin 位移法
利用绝对定位,将元素左上角调整到父元素中心,然后通过 负 margin 值调整元素中心到父元素中心。需要已知盒子宽高
.parent { position: relative; } .child { position: absolute; top: 50%; left: 50%; width: 100px; height: 200px; margin-top: -100px; /* 自身高度的一半 */ margin-left: -50px; /* 自身宽度的一半 */ }
-
flex 布局法
通过
align-items: center;
justify-content: center;
设置水平垂直居中。需要考虑兼容问题,多用于移动端.parent { display: flex; align-items: center; justify-content: center; }
flex 布局
部分图片来源:阮一峰的 flex 笔记
任何一个容器都可以指定 flex 布局,包括行内元素
设置 flex 布局后,
- 本元素被称为 flex 容器 container,
- 子元素自动成为容器成员,即项目 item,子元素的
float
、clear
和vertical-align
属性将失效。 - 容器默认存在两根轴,水平的主轴(main axis)和垂直的交叉轴(cross axis),项目默认沿水平主轴排列
设置在容器上的属性
-
flex-direction
决定主轴的方向(交叉轴始终与主轴垂直) -
flex-wrap
定义如果一条轴线排不下,是否换行 -
flex-flow
是 前两个属性 flex-direction 和 flex-wrap 的简写形式,默认值为 row nowrap; -
justify-content
定义项目在主轴上的对齐方式 -
align-items
定义项目在交叉轴的对齐方式 -
align-content
定义多跟轴线的对齐方式,如果项目只有一根轴线,则该属性不起作用
设置在项目上的属性
-
order
定义项目的排列顺序,数值越小,排列越靠前,默认为0 -
flex-grow
定义项目的占用剩余空间(如果有)的放大比例- 默认为0,即如果存在剩余空间也不放大
- 如果所有项目的 flex-grow 属性都为1,则它们等分剩余空间
- 如果某一个项目为1,其余项目为2,则前者占用剩余空间是其他的2倍
-
flex-shrink
定义项目的在空间不足时的缩小比例- 默认值为 1,即如果空间不足,该项目将缩小
- 如果所有项目的值都为1,则等比例缩小
- 如果有某个项目值为0,则其他项目缩小,该项目不缩小
-
flex-basis
定义在分配多余空间之前,项目占据的主轴空间- 浏览器根据这个属性,计算主轴是否有空余空间
- 默认值为 auto,即项目本来的大小
- 可以设置跟 width 或 height 属性一样的值(比 width 和 height 优先级更高),则项目将占据固定空间
-
flex
是 flex-grow flex-shrink 和 flex-basis 的缩写- 默认值为 0 1 auto,后两个属性可选
- 快捷值:
auto
(1 1 auto) 和none
(0 0 auto) - 优先使用该属性,而不是单独写三个属性,因为浏览器会推算相关值
-
align-self
允许单个项目于其他项目有不一样的对齐方式,覆盖 align-items 属性- 默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch
-
justify-self
允许单个项目不同于其他项目的对齐方式,覆盖 justify-content 属性
flex: 1
意味着
- flex-grow:1 存在剩余空间,则放大比例为1
- flex-shrink:1 空间不足,项目缩小比例为1
- flex-basis: 0% 计算项目是否有空余空间时,项目本身的大小为 0%(相对于容器主轴尺寸)
可以用来自动填充剩余空间(多余的或不足的)
流式布局
百分比布局,常用于移动端开发。
元素可以设置宽高的最值,然后给元素设置百分比宽度。
瀑布流布局
视觉表现为参差不齐的多栏布局。
瀑布流布局的优点
- 节省空间,外表美观,更有艺术性。
- 对于触屏设备非常友好,通过向上滑动浏览
- 用户浏览时的观赏和思维不容易被打断,留存更容易。
瀑布流布局的缺点
- 用户无法了解内容总长度,对内容没有宏观掌控。
- 用户无法了解现在所处的具体位置,不知道离终点还有多远。
- 回溯时不容易定位到之前看到的内容。
- 容易造成页面加载的负荷。
- 容易造成用户浏览的疲劳,没有短暂的休息时间。