Go to comments

多种方式实现 三栏布局

三栏布局的要求,左右固定中间,自动适应


下面整理了四种三栏布局的方式

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



Leave a comment 0 Comments.

Leave a Reply

换一张