多种方式实现 三栏布局
三栏布局的要求,左右固定中间,自动适应
下面整理了四种三栏布局的方式
1. 圣杯布局(grial)padding solution
2. 双分翼布局(double Fly) margin solution
3. 浮动加BFC
4. flex
一、圣杯布局 和 双飞翼布局
圣杯 和 双飞翼布局用的是同一个原型,也就是说是基于一个基本的原理上升成的
下面先开始一步一步的做这个原型
1. 左边Left元素宽度200像素,右边Right元素宽度100像素,中间主体Main元素宽度自适应(Main不设置宽度)
2. Mian元素在上面
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>三栏布局</title> <style> *{ margin: 0; padding: 0; } .header, .footer{ height: 100px; background-color: #ddd; } .main{ height: 100px; background-color: #cfa; /* Mian元素不设置宽度,宽度自适应 */ } .left{ width: 100px; height: 100px; background-color: #fca; } .right{ width: 200px; height: 100px; background-color: #acf; } </style> </head> <body> <div class="header">Header</div> <div class="content"> <div class="main">Main</div> <!-- Mian元素在上面 --> <div class="left">Left</div> <div class="right">Right</div> </div> <div class="footer">Footer</div> </body> </html>
1、为什么Mian元素放到最上面
Main、Left、Right这三个元素,正常顺序是左中右(Left、Main、Right),但是我们在页面布局中把Mian放到最上面,
目的是元素加载完,最好是先渲染Main,因为它里面还有很多其它元素。
浏览器DOM树的遍历是深度优先遍历,查看Main元素后,继续查看它里面的子元素,它的兄弟元素Left、Right会放到后面,这是关于页面DOM树解析的规则。
所以对于我们页面更好的渲染,让Main元素尽早的加载出来,包括Main对应的资源尽早的去拿取,
对用户的体验是一个非常不错的提升,所以要把Main放到上面来
深度优先是二叉树算法,让Main元素更快的加载、渲染出来
目前的效果是这样的
HeaderMainLeftRightFooter
2、圣杯布局和双飞翼布局的原型
header和footer这两个元素不考虑,只看中间着三个元素,
三栏布局首先要把Main、Left、Right,这三个元素排到一行
设置content元素下面三个div浮动 float: left; 把他们排到一行上去
<style> *{ margin: 0; padding: 0; } .header, .footer{ height: 100px; background-color: #ddd; } .main{ height: 100px; background-color: #cfa; } .left{ width: 200px; height: 100px; background-color: #fca; } .right{ width: 100px; height: 100px; background-color: #acf; } /* 设置浮动 */ .content > div{ float: left; } </style>
因为设置了浮动,Main、Left、Right、Footer都飘起来了
HeaderMainLeftRightFooter
给Main元素设置宽度 width:100%; ,让它撑开一整行
<style> *{ margin: 0; padding: 0; } .header, .footer{ height: 100px; background-color: #ddd; } .main{ height: 100px; background-color: #cfa; width:100%; /* 设置宽度100% */ } .left{ width: 200px; height: 100px; background-color: #fca; } .right{ width: 100px; height: 100px; background-color: #acf; } .content > div{ float: left; } </style>
因为浮动后高度塌陷,导致Footer元素也跟着上来了
HeaderMainLeftRightFooter
清除浮动
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>三栏布局</title> <style> *{ margin: 0; padding: 0; } /* 清除浮动 */ .clearfix::after{ content: ""; display: block; clear: both; } .header, .footer{ height: 100px; background-color: #ddd; } .main{ height: 100px; background-color: #cfa; width:100%; } .left{ width: 200px; height: 100px; background-color: #fca; } .right{ width: 100px; height: 100px; background-color: #acf; } .content > div{ float: left; } </style> </head> <body> <div class="header">Header</div> <div class="content clearfix"> <!-- 清除浮动 --> <div class="main">Main</div> <div class="left">Left</div> <div class="right">Right</div> </div> <div class="footer">Footer</div> </body> </html>
这样下面Footer元素就摆放到下面去了,而且centent元素把三个子元素都包裹住了,
现在这样和我们想要的三栏布局还差一些
HeaderMainLeftRightFooter
浮动元素本质上是一行,是先排列Main元素,后面跟着排列Left元素 和 Right元素,
浮动元素是从左到右排,如果一行装不下就放到下一行,
或者说说浮动元素本质上是一行,只不过是折行了,这是浮动的特点。
给Lift元素设置 margin-left: -100%; 相当于一个父级的宽度
<style> *{ margin: 0; padding: 0; } .clearfix::after{ content: ""; display: block; clear: both; } .header, .footer{ height: 100px; background-color: #DDD; } .main{ height: 100px; background-color: #cfa; width:100%; } .left{ width: 200px; height: 100px; background-color: #fca; margin-left:-100%; /* 设置margin */ } .right{ width: 100px; height: 100px; background-color: #acf; } .content > div{ float: left; } </style>
Left元素就跑到上面一行去了
HeaderMainLeftRightFooter
Right元素也是,设置自身的宽度的负树值 margin-left: -100px; ,就排到右边来了
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>三栏布局的原型</title> <style> *{ margin: 0; padding: 0; } .clearfix::after{ content: ""; display: block; clear: both; } .header, .footer{ height: 100px; background-color: #ddd; } .main{ height: 100px; background-color: #cfa; width:100%; } .left{ width: 200px; height: 100px; background-color: #fca; margin-left:-100%; } .right{ width: 100px; height: 100px; background-color: #acf; margin-left:-100px; /* 设置margin */ } .content > div{ float: left; } </style> </head> <body> <div class="header">Header</div> <div class="content clearfix"> <div class="main">Main</div> <div class="left">Left</div> <div class="right">Right</div> </div> <div class="footer">Footer</div> </body> </html>
Right元素就到右边的位置上了
HeaderMainLeftRightFooter
流式布局会从上到下,一行铺满会放到下一行,如果一行能放得下都会放到一行,
所以Left元素设置 margin:-100%; 负的百分之百会往上提一整行,同样Right元素设置负自身宽度会贴右侧自身宽度的位置上
这是浮动的一个特点,从左到右、从上到下的排列方式,
这点一定要理解,如果不理解就会很蒙
接下来开始圣杯布局 和 双飞翼布局,
现在的问题是Main元素是被Left元素和Right元素压住的,
我们希望Main元素是在Left元素和Right元素中间的位置,下面基于这样一个原型,去生成圣杯模式和双飞翼模式。
3、圣杯模式
圣杯模式的意思是,我们希望达到一种理想的模式(布局方式),这是一个隐喻并不是杯子。
圣杯布局的核心思想
1). 父级content元素使用padding属性预留位置,设置 padding: 0 100px 0 200px;
2). 子元素设置相对定位,进行位置调整,
设置Left元素 position:relative; left:-200px;
设置Right元素 position:relative; right:-100px;
把Left、Right两个元素放到对应的位置去
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>grail</title> <style> *{ margin: 0; padding: 0; } .clearfix::after{ content: ""; display: block; clear: both; } .header, .footer{ height: 100px; background-color: #ddd; } .main{ height: 100px; background-color: #cfa; width:100%; } .left{ width: 200px; height: 100px; background-color: #fca; margin-left:-100%; position:relative; left:-200px; } .right{ width: 100px; height: 100px; background-color: #acf; margin-left:-100px; position:relative; right:-100px; } .content > div{ float: left; } .content{ padding:0 100px 0 200px; } </style> </head> <body> <div class="header">Header</div> <div class="content clearfix"> <div class="main">Main</div> <div class="left">Left</div> <div class="right">Right</div> </div> <div class="footer">Footer</div> </body> </html>
4、双飞翼布局
双飞翼布局也是基于这个原型生成,还是中间的Main元素被Left、Rigth元素压住了
双飞翼布局来自淘宝团队,他们是怎么解决这个问题的呢?
1). 改变HTML的结构,给Main套了一个外层(外层是wrapper)
2). 设置外层wrapper元素的宽度 width:100%; ,然后设置Main元素
3). Main元素不需要宽度width:100%,因为设置了它父级(wrapper元素)的宽度,
设置了Main父级的宽度,Main撑满父级的包含块就可以了
4). 通过设置Main的 margin:0 200px 0 100px;
Main元素自己在当前的wrapper父元素内,两边的margin正好是预留Left、right的位置
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>双飞翼布局 doubleFly</title> <style> *{ margin: 0; padding: 0; } .clearfix::after{ content: ""; display: block; clear: both; } .header, .footer{ height: 100px; background-color: #ddd; } .main{ height: 100px; background-color: #cfa; /* width:100%; */ margin:0 100px 0 200px } .left{ width: 200px; height: 100px; background-color: #fca; margin-left:-100%; } .right{ width: 100px; height: 100px; background-color: #acf; margin-left:-100px; } .content > div{ float: left; } .wrapper{ width: 100%; } </style> </head> <body> <div class="header">Header</div> <div class="content clearfix"> <div class="wrapper"> <div class="main">Main</div> </div> <div class="left">Left</div> <div class="right">Right</div> </div> <div class="footer">Footer</div> </body> </html>
圣杯布局和双飞翼,一个是用padding预留,一个是用margin把两边撑开
叫双飞翼是因为有两边两个耳朵,中间是主体部分
二、浮动加BFC布局
本质上是用了浮动元素的一些特点
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>float + BFC</title> <style> *{ margin: 0; padding: 0; } .left{ width: 100px; height: 100px; background-color: #fac; } .right{ width: 200px; height: 100px; background-color: #caf; } .center{ /* 中间自适应不设置宽度 */ height: 120px; background-color: #acf; } </style> </head> <body> <div class="left"></div> <div class="right"></div> <div class="center"></div> </body> </html>
两边的元素加浮动,中间的元素触发BFC,
触发BFC的元素会避开浮动元素,从而实现三栏布局
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>float + BFC</title> <style> *{ margin: 0; padding: 0; } .left{ width: 100px; height: 100px; background-color: #fac; float: left; /* 左浮动 */ } .right{ width: 200px; height: 100px; background-color: #caf; float: right; /* 右浮动 */ } .center{ /* 中间自适应不设置宽度 */ height: 120px; background-color: #acf; overflow: hidden;/* 触发BFC 或者用 display:flow-root专门触发BFC */ } </style> </head> <body> <div class="left"></div> <div class="right"></div> <div class="center"></div> </body> </html>
三、flex布局
flex实现三栏布局就比较简单了
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>flex</title> <style> *{ margin: 0; padding: 0; } .content > div{ height: 100px; } .header, .footer{ height: 100px; background-color: #ddd; } .content{ display: flex; } .main{ order: 2; flex: 1; background-color: #fac; } .left{ order: 1; width: 200px; background-color: #afc; } .right{ order: 3; width: 100px; background-color: #fca; } </style> </head> <body> <div class="header">Header</div> <div class="content"> <div class="main">Main</div> <div class="left">Left</div> <div class="right">Right</div> </div> <div class="footer">Footer</div> </body> </html>
收藏记录一篇圣杯双飞翼布局的帖子
三句话总结圣杯,双飞燕布局
https://juejin.cn/post/6844903807936102414
https://blog.csdn.net/weixin_34127717/article/details/91386223
firstTime: 20220207