前端知识网络

您所在的位置:网站首页 flex-shark 前端知识网络

前端知识网络

2024-03-03 00:50| 来源: 网络整理| 查看: 265

王志远,微医前端技术部

前言

​ 一篇文章的时间,让我们回到画页面的那个夏天,彻底搞懂前端页面布局。

本文期待 整合布局知识网络 整合最佳实现并整理样式片段(以 less 为例),拿走即用 高频面试题梳理回答 知识网络 常见布局

​ 对于 CSS 的布局,在应用层面,分为三类,居中布局、多列布局、全屏布局;

居中分为垂直、水平和平面; 多列分为两列、三列、圣杯、双飞翼; 全屏分为等分、等高、全屏;

image.png

graph TB A[常见布局] --> B1[居中布局] B1 --五种方案--> C11[水平居中] B1 --五种方案--> C12[垂直居中] B1 --五种方案--> C13[平面居中] A --> B3[全屏布局] A --> B2[多列布局] B2 --七种方案--> C21[两列右侧自适应布局] B2 --四种方案--> C22[三列右侧自适应布局] B2 --两种方案--> C23[三列中间自适应布局,圣杯-双飞翼]

每个布局类型都有他们对应的最佳实践,衡量标准主要是兼容性和组成场景,举栅格多列布局而言,移动端通用是 flex 新特性,而 PC 端则要更多的考虑兼容从而使用 margin 负值+盒模型 inline-block 技巧;

常见实现

这些布局的实现有六种常用实现:盒模型、浮动、定位、flex 布局、Grid 布局和 Shapes 布局。

graph TB B4[常见实现] --> C1[Float] B4 --> C2[盒模型] B4 --> C3[定位] B4 --> C4[Flex 和 grid] B4 --> C5[Columns 和 Shapes]

image.png

接下来,我们以应用层面为分析主线,梳理分别的最佳实现吧!

居中布局 使用 复制粘贴

链接:github.com/Sympath/duo…

垂直

需求可以分为四大类六种场景,从而衍生出对应的六种最佳处理

graph TB A[垂直居中] --> B1[内联场景] A --> B2[块元素场景] A --> B3[多元素场景] A --> B4[脱离文档流场景] B4 --> C1[定高] B4 --> C2[不定高] B4 --> C3[包裹性]

image.png

内联(inline)级别场景

采用父容器设置line-height即可

// 内联(inline)级别 父容器设置 .inline-mixin (@line-height) { line-height: @line-height; } 块(block)级别场景

采用子元素转为inline-block然后复用内联场景即可

// 块(block)级别 父容器设置 .block-mixin (@line-height) { .center-y-inline(@line-height); .item { display: inline-block; } } 多子容器场景

适合 flex 布局, 父容器设置

// flex 布局级别+多子容器 父容器设置 .flex { display: flex; justify-content: center; } 脱离文档流

这些类均需要自身设置,包含两种情况,定高、不定高,不定奥存在两种解决方案,transform 和包裹性 margin

// 定位级别+脱离文档流+不定高 .position { position: absolute; top: 50%; transform: translateY(-50%); // 存在多浏览器兼容性问题,所以需要写多套 } // 定位级别+脱离文档流+定高 自身设置 .position-mixin (@height : 100%) { position: absolute; top: 50%; margin-top: -@height/2; } // 定位级别+脱离文档流+包裹性 (最佳方案) 自身设置 .position-wrap { position: absolute; top: 0; bottom: 0; margin: auto 0; }

汇总记忆:汇总来说可以这么记忆,一共六种。

父级设置有三类,内联line-height,块级inline-block+line-height,多子容器flex+align-items: center; 自身设置有三类,脱离文档选定位,定高 margin-top 负值,不定高 translate,最佳包裹配置margin: auto 水平

需求同样是这六种场景

graph TB A[水平居中] --> B1[内联场景] A --> B2[块元素场景] A --> B3[多元素场景] A --> B4[脱离文档流场景] B4 --> C1[定高] B4 --> C2[不定高] B4 --> C3[包裹性]

image.png

内联(inline)级别场景

采用父容器设置line-height即可

// 内联(inline)级别 父容器设置 .inline-mixin () { text-align: center; } 块(block)级别场景

采用子元素转为inline-block然后复用内联场景即可

// 块(block)级别 自身设置 .block { margin-left: auto; margin-right: auto; } 多子容器场景

适合 flex 布局, 父容器设置

.flex { display: flex; align-items: center; } 脱离文档流

这些类均需要自身设置,包含两种情况,定高、不定高,不定奥存在两种解决方案,transform 和包裹性 margin

// 定位级别+脱离文档流+不定宽 自身设置 .position { position: absolute; left: 50%; transform: translateX(-50%); // 存在多浏览器兼容性问题,所以需要写多套 } // 定位级别+脱离文档流+定宽 自身设置 .position-mixin (@width:100%) { position: absolute; left: 50%; margin-left: -@width/2; } // 定位级别+脱离文档流+包裹性 (最佳方案) 自身设置 .position-wrap { position: absolute; left: 0; right: 0; margin: 0 auto; }

汇总记忆:汇总来说可以这么记忆,一共六种,父级设置有两类,内联text-align,多子容器display: flex+align-items: center;自身设置有 1+3,块级margin:auto;;脱离文档选定位,定宽 margin 负值,不定宽 translate,最佳包裹配置margin: auto

平面

综合下水平和垂直就好

#center { .inline-mixin(@line-height) { #center > #x > .inline; #center > #y > .inline-mixin(@line-height) } // 块(block)级别 父容器设置+注意需要把子容器设置 item 的类名 .block-mixin (@line-height) { .center-x-block; .center-y-block(@line-height) } // flex 布局级别 多子容器 父容器设置 .flex { #center > #x > .flex; #center > #y > .flex; } // 定位级别 脱离文档流+定宽高 自身设置 .position-mixin (@width, @height) { .center-x-position(@width); .center-y-position(@height); } // 定位级别+脱离文档流+不定宽 自身设置 .position { #center > #x > .position(); #center > #y > .position(); transform: translate(-50%, -50%); } // 定位级别+脱离文档流 自身设置 利用了包裹性(最佳方案) .position-wrap { #center > #x > .position-wrap(); #center > #y > .position-wrap(); margin: auto; } } 内容总结

综合如上我们可以得出一个超牛的代码模块,居中相关的拿走即用,这里说几条规定便于使用

命名规范:如果需要传参,则定义成 mixin,命名后缀也需要带上这个,便于区分 每个方案的使用说明都至少存在如下信息(面向场景 设置位置 特点(可无)) /** 居中相关 1. 命名规范:如果需要传参,则定义成 mixin,命名后缀也需要带上这个,便于区分 2. 每个方案的使用说明都至少存在如下信息 面向场景 设置位置 特点(可无) */ #center { //>>>>>>>>>>>>>>>>>> 垂直居中 #y { // 内联(inline)级别 父容器设置 .inline-mixin (@line-height) { line-height: @line-height; } // 块(block)级别 父容器设置 .block-mixin (@line-height) { .center-y-inline(@line-height); .item { display: inline-block; } } // flex 布局级别+多子容器 父容器设置 .flex { display: flex; align-items: center; } // 定位级别+脱离文档流+不定宽 自身设置 .position { position: absolute; top: 50%; transform: translateY(-50%); // 存在多浏览器兼容性问题,所以需要写多套 } // 定位级别+脱离文档流+定高 自身设置 .position-mixin (@height : 100%) { position: absolute; top: 50%; margin-top: -@height/2; } // 定位级别+脱离文档流+包裹性 (最佳方案) 自身设置 .position-wrap { position: absolute; top: 0; bottom: 0; margin: auto 0; } } //>>>>>>>>>>>>>>>>>> 水平居中 #x { // 内联(inline)级别 父容器设置 .inline { text-align: center; } // 块(block)级别 自身设置 .block { margin-left: auto; margin-right: auto; } // flex 布局级别+多子容器 父容器设置 .flex { display: flex; justify-content: center; } // 定位级别+脱离文档流+不定宽 自身设置 .position { position: absolute; left: 50%; transform: translateX(-50%); // 存在多浏览器兼容性问题,所以需要写多套 } // 定位级别+脱离文档流+定宽 自身设置 .position-mixin (@width:100%) { position: absolute; left: 50%; margin-left: -@width/2; } // 定位级别+脱离文档流+包裹性 (最佳方案) 自身设置 .position-wrap { position: absolute; left: 0; right: 0; margin: 0 auto; } } .inline-mixin(@line-height) { #center > #x > .inline; #center > #y > .inline-mixin(@line-height) } // 块(block)级别 父容器设置+注意需要把子容器设置 item 的类名 .block-mixin (@line-height) { .center-x-block; .center-y-block(@line-height) } // flex 布局级别 多子容器 父容器设置 .flex { #center > #x > .flex; #center > #y > .flex; } // 定位级别 脱离文档流+定宽高 自身设置 .position-mixin (@width, @height) { .center-x-position(@width); .center-y-position(@height); } // 定位级别+脱离文档流+不定宽 自身设置 .position { #center > #x > .position(); #center > #y > .position(); transform: translate(-50%, -50%); } // 定位级别+脱离文档流 自身设置 利用了包裹性(最佳方案) .position-wrap { #center > #x > .position-wrap(); #center > #y > .position-wrap(); margin: auto; } } 多列布局之两列布局

在线预览 Demo: http://82.157.62.28:3000/#/index

**需求:**左列定宽,右列自适应

Vue 版组件复制粘贴

链接:github.com/Sympath/duo…

存在七种解决方案,选出四种根据场景的最佳方案,另外三种扩展思路

浮动:组合清浮动(非等高布局推荐) 表格(等高-pc 端推荐) flex 布局(等高-移动端推荐) 定位(需要脱离文档流) 浮动:组合 margin 负值 浮动:组合 BFC(可以overflow或display: flex;都会有副作用,需要考虑场景使用) gird 布局 浮动:组合 margin 负值

结构

这种适合右侧比左侧高的情况,如果右侧比左侧高就凉了,因为浮动形成 bfc 从而会导致高度塌陷

// 适合 PC 端 父容器 存在【右侧比左侧高,浮动导致塌陷】问题 .float-margin-mixin (@leftWidth: 0) { .left { float: left; width: @leftWidth; } .right { margin-left: @leftWidth; } } 浮动:组合清浮动

处理【右侧比左侧高,浮动导致塌陷】的情况

改写 html 结构,在自适应模块外层进行包裹 样式设置:左右均浮动,然后在右侧外层下清除浮动 // 浮动:组合清浮动 // 适合 PC 端 父容器 需要在右边自适应模块的 html 外层再包裹一层 right-fix 类名元素 .float-clear-mixin (@leftWidth: 0) { .left, .right-fix { float: left; } .left { width: @leftWidth; } .right { } } 浮动:组合 BFC

浮动元素不会和 BFC 重叠

// 浮动:组合 BFC flex // 适合 PC 端 父容器 均浮动(最佳方案) .float-bfc-mixin (@leftWidth: 0) { .left, .right-fix { float: left; } .left { width: @leftWidth; } .right { display: flex; // 或 overflow: hidden; } } 表格

table 布局默认是等高布局

// 表格 // 适合需要等高的布局 父容器 table 布局默认是等高布局 .table-mixin (@leftWidth: 0) { display: table; width: 100%; .left { display: table-cell; width: @leftWidth; } .right { display: table-cell; } } 定位 // 定位 // 适合需要脱离文档流的布局 父容器 .position-mixin (@leftWidth: 0) { position: relative; .left { position: absolute; width: @leftWidth; } .right { position: absolute; left: @leftWidth; right: 0; } } flex 布局 // flex 布局 // 适合不需要考虑兼容性的布局 父容器 .flex-mixin (@leftWidth: 0) { display: flex; .left { width: @leftWidth; } .right { flex: 1; } } gird 布局 // gird 布局 // 适合不需要考虑兼容性的布局(目前更建议使用 flex) 父容器 .gird-mixin (@leftWidth: 0) { display: grid; grid-template-columns: @leftWidth auto; // 列宽 grid-template-rows: repeat(2, 600px); // 列高 } 两列布局整理汇总 // ## 两列布局 #two-column { // 浮动:组合 margin 负值 // 适合 PC 端 父容器 存在【右侧比左侧高,浮动导致塌陷】问题 .float-margin-mixin (@leftWidth: 0) { .left { float: left; width: @leftWidth; } .right { margin-left: @leftWidth; } } // 浮动:组合清浮动 // 适合 PC 端 父容器 需要在右边自适应模块的 html 外层再包裹一层 right-fix 类名元素 .float-clear-mixin (@leftWidth: 0) { .left, .right-fix { float: left; } .left { width: @leftWidth; } .right { } } // 浮动:组合 BFC flex // 适合 PC 端 父容器 均浮动(最佳方案) .float-bfc-mixin (@leftWidth: 0) { .left, .right-fix { float: left; } .left { width: @leftWidth; } .right { display: flex; // 或 overflow: hidden; } } // 表格 // 适合需要等高的布局 父容器 table 布局默认是等高布局 .table-mixin (@leftWidth: 0) { display: table; width: 100%; .left { display: table-cell; width: @leftWidth; } .right { display: table-cell; } } // 定位 // 适合需要脱离文档流的布局 父容器 .position-mixin (@leftWidth: 0) { position: relative; .left { position: absolute; width: @leftWidth; } .right { position: absolute; left: @leftWidth; right: 0; } } // flex 布局 // 适合不需要考虑兼容性的布局 父容器 .flex-mixin (@leftWidth: 0) { display: flex; .left { width: @leftWidth; } .right { flex: 1; } } // gird 布局 // 适合不需要考虑兼容性的布局(目前更建议使用 flex) 父容器 .gird-mixin (@leftWidth: 0) { display: grid; grid-template-columns: @leftWidth auto; // 列宽 grid-template-rows: repeat(2, 600px); // 列高 } } 多列布局之三列布局

**在线预览 Demo:**http://82.157.62.28:3000/#/index

需求: 左中 定宽 右侧自适应

Vue 版组件复制粘贴

链接:github.com/Sympath/duo…

浮动:组合 margin

这种适合右侧比左侧高的情况,如果右侧比左侧高就凉了,因为浮动形成 bfc 从而会导致高度塌陷

.layout-tree-column-float-margin (@leftWidth: 0) { .left, .center{ float:left; width: @leftWidth; } .right { margin-left: @leftWidth; } } 浮动:组合 BFC

浮动元素不会和 BFC 重叠

.layout-tree-column-float-bfc (@leftWidth) { .left, .center { float:left; width: @leftWidth; } .right { overflow: hidden; } } 表格

table 布局默认是等高布局

.layout-tree-column-table (@leftWidth) { display: table; width: 100%; .left, .center { display: table-cell; width: @leftWidth } .right { display: table-cell; } } 定位 .layout-tree-column-position (@leftWidth) { position: relative; .left, .center { width: @leftWidth } .right { position: absolute; left: @leftWidth; right: 0; } } flex 布局 .layout-tree-column-flex (@leftWidth) { display:flex; .left, .center { width: @leftWidth } .right { flex:1; } } gird 布局 .layout-two-column-gird (@leftWidth, @centerWidth, @leftHeight) { display: grid; grid-template-columns: @leftWidth @centerWidth auto; // 列宽 grid-template-rows: repeat(2,@leftHeight); // 列高 .left { } .right { } } 三列布局整理汇总 /** 布局相关 1. 命名规范:如果需要传参,则定义成 mixin,命名后缀也需要带上这个,便于区分 2. 每个方案的使用说明都至少存在如下信息 面向场景 设置位置 特点(可无) */ #layout { // ## 两列布局 #three-column { // 浮动:组合 margin 负值 // 适合 PC 端 父容器 存在【右侧比左侧高,浮动导致塌陷】问题 .float-margin-mixin (@leftWidth) { .left { float:left; width: @leftWidth; } .right { margin-left: @leftWidth; } } // 浮动:组合清浮动 // 适合 PC 端 父容器 需要在右边自适应模块的 html 外层再包裹一层 right-fix 类名元素 .float-clear-mixin (@leftWidth) { .left, .right-fix { float:left; } .left { width: @leftWidth; } .right { .inner { clear: both; } } } // 浮动:组合 BFC // 适合 PC 端 父容器 均浮动(最佳方案) .float-bfc-mixin (@leftWidth) { .left, .right-fix { float:left; } .left { width: @leftWidth; } .right { .inner { clear: both; } } } // 表格 // 适合需要等高的布局 父容器 table 布局默认是等高布局 .table-mixin (@leftWidth) { display: table; width: 100%; .left { display: table-cell; width: @leftWidth } .right { display: table-cell; } } // 定位 // 适合需要脱离文档流的布局 父容器 .position-mixin (@leftWidth) { position: relative; .left { width: @leftWidth } .right { position: absolute; left: @leftWidth; right: 0; } } // flex 布局 // 适合不需要考虑兼容性的布局 父容器 .flex-mixin (@leftWidth) { display:flex; .left { width: @leftWidth } .right { flex:1; } } // gird 布局 // 适合不需要考虑兼容性的布局(目前更建议使用 flex) 父容器 .gird-mixin (@leftWidth) { display: grid; grid-template-columns: @leftWidth auto; // 列宽 grid-template-rows: repeat(2,600px); // 列高 .left { } .right { } } } } 多列布局之多列布局

在线预览 Demo: http://82.157.62.28:3000/#/index

需求: 两列定宽中间自适应

Vue 版组件复制粘贴

链接:github.com/Sympath/duo…

圣杯布局 结构

注意:这里把 center 放在第一位,是为了优先加载

中间 左边 右边 水平排列:三个容器同时浮动,此时会引起左右侧内容掉落 腾出位置:父容器加内填充,准备左右侧放置空间 摆放位置:margin 负值实现同行排列,相对定位实现位置移动 /** 布局相关 1. 命名规范:如果需要传参,则定义成 mixin,命名后缀也需要带上这个,便于区分 2. 每个方案的使用说明都至少存在如下信息 面向场景 设置位置 特点(可无) */ #layout { // ## 三列布局 #three-column { .holy-grail(@leftWeight, @rightWeight){ /* 第 1 步: 三个容器同时设置浮动 - 在一行排列 放不下 left 和 right 掉下去 */ #center,#left,#right{float:left} /* 第 2 步 给父容器加内填充 - 放 left 和 right 2 个容器*/ #parent{ padding-left: @leftWeight; padding-right: @rightWeight; } /* 第 3 步: 把 left 移动到原本的位置 - left 在 center(100%)的前面 把 right 移动到原本的位置 - right 在 center 的后面 技巧: margin 负值 - 移动 定位方位 - 移动 */ #left{margin-left:-100%;position: relative;left:-@leftWeight;} #right{margin-left:-@rightWeight;position: relative;right:-@rightWeight;} } } }

双飞翼布局 结构

中间部分内部增加一层结构

中间 左边 右边 水平排列:三个容器同时浮动,此时会引起左右侧内容掉落 腾出位置:中间的容器的子容器设置 margin 外间距 摆放位置:margin 负值实现 /** 布局相关 1. 命名规范:如果需要传参,则定义成 mixin,命名后缀也需要带上这个,便于区分 2. 每个方案的使用说明都至少存在如下信息 面向场景 设置位置 特点(可无) */ #layout { // ## 三列布局 #three-column { .threesome-wing(@leftWeight, @rightWeight){ /* 第 1 步: 三个容器同时设置浮动 - 在一行排列 放不下 left 和 right 掉下去 */ #center,#left,#right{float:left} /* 第 2 步: 给中间的容器的子容器设置 margin 外间距 => left 和 right 的位置给留出来*/ #inner{ margin-left:@leftWeight; margin-right:@rightWeight; } /* 第 3 步: 把 left 移动到原本的位置 - left 在 center(100%)的前面 把 right 移动到原本的位置 - right 在 center 的后面 技巧: margin 负值 - 移动 */ #left{margin-left:-100%} #right{margin-left:-@rightWeight;} } } }

总结: 双飞翼把圣杯的定位位移的属性给优化掉了 margin + padding

等分布局 浮动布局 html 结构:这里特殊一点,外层需要加一层 div

浮动+盒模型+margin 负值

水平排列:浮动实现水平排列 等分:设置宽度 间距:盒模型box-sizing: border-box + padding-left实现,设置在外层上,避免内容被影响 最左侧间隙:父容器 margin 负值,这里不能对第一个元素特殊处理,会导致这个元素内容偏大 // @numberOfRow 一行个数 // @space 元素间隙 .float(@numberOfRow, @space: 0) { .parent{ margin-left: -@space; } .parent>div{ float: left; width:1/@numberOfRow; /* padding + border */ box-sizing: border-box; padding-left: @space; } } 表格布局 html 结构:这里特殊一点,外层需要加一层 div

表格+margin 负值

水平排列:表格布局实现水平排列,注意表格必须设置宽度 100%,不然不会继承父容器宽度 等分:默认等分等高 间距:border实现 最左侧间隙:margin 负值,但这里不能对父容器处理,而是要在父容器外面再加一层,因为父容器身上设置了宽度 100% // @space 元素间隙 .table(@space: 0) { .wrap { margin-left: -@space; } .parent{ display: table; width: 100%; } .parent>div{ display: table-cell; border-left: @space solid #fff; } } 弹性布局 html 结构 水平排列:弹性布局 等分:父容器设置flex: 1即可 间距:border实现 最左侧间隙:父容器 margin 负值,

扩展:flex: 1是一个综合值,其值包含flex-grow、flex-shark和flex-basic,默认值为0 1 auto,即父多时子原样,父少时一起小,这个属性有继承性,所以可以放在父项目上进行统一设置。

// @space 元素间隙 .flex(@space: 0) { .parent{ display: flex; flex: 1; margin-left: -@space; } .parent>div{ border-left: @space solid #fff; } } 最后汇总

至此,我们也就完成了前端知识中布局的梳理,知识网络的构建非一日之功,但成体系了,就成了正规军,加油!

本文布局均有在线案例,可见:http://82.157.62.28:3000/#/index 本文布局均实现对应的 vue 组件,拿走即用,其他框架可以类比自实现,仓库地址:github.com/Sympath/duo… 本地组件发布至自己的组件仓库,可以去瞅瞅或点个 star,感谢!npm 地址:www.npmjs.com/package/duo…



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3