平时开发或者面试的时候,经常会遇到这样的场景,实现一个三栏布局,具体要求如下:
高度为100px,左右栏宽度固定为300px,中间栏宽度自适应。
有多种布局方案可以实现,这里一一探索。
浮动布局方案
实现思路:
通过让左右两栏固定宽度和浮动,并设置中间栏的左右外边距实现三栏自适应
这里还有一种实现思路,中间栏创建一个BFC同样可以实现自适应,原理是浮动不会影响BFC内的内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>三栏布局-浮动布局方案</title> <style> .left, .right, .main { height: 100px; } .left { width: 300px; float: left; background: red; } .right { width: 300px; float: right; background: blue; } .main { margin-left: 300px; margin-right: 300px; background: yellow; } </style> </head> <body> <article> <aside class="left">left</aside> <aside class="right">right</aside> <main class="main">main</main> </article> </body> </html>
|
缺点:
- 内容展现顺序与DOM结构不一致,主体内容后加载,一定程度影响用户体验
- 当宽度缩小到不足以显示三栏时,右侧栏会被挤到下方
兼容性:
- PC端支持IE6+, Firefox 2+, Chrome 1+
- 移动端支持iOS Safari 1.0,Android browser 1.0
绝对定位布局方案
实现思路:
容器设置为相对定位,左右两栏分别用绝对定位,中间栏增加左右外边距实现自适应
还有一种思路, 左右两栏分别绝对定位在两侧,中间栏同样使用绝对定位,并设置左右的距离为300px
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>三栏布局-绝对定位方案</title> <style> .container { position: relative; } .main, .left, .right { height: 100px; } .main { margin-left: 300px; margin-right: 300px; background: yellow; } .left { position: absolute; top: 0; left: 0; width: 300px; background: red; } .right { position: absolute; top: 0; right: 0; width: 300px; background: blue; } </style> </head> <body> <article class="container"> <main class="main">main</main> <aside class="left">left</aside> <aside class="right">right</aside> </article> </body> </html>
|
缺点:
- 父元素必须要定位(使用非static的定位方式)
- 宽度缩小到无法显示主体内容时,主体内容会被覆盖无法显示
优点:
- 内容可以优先加载
兼容性:
- PC端支持IE6+, Firefox 2+, Chrome 1+
- 移动端未知
Flex布局方案
实现思路:
设置容器为flex,然后左右栏设置固定宽度不可伸缩,中间栏设置为自动伸缩
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>三栏布局-弹性盒布局方案</title> <style> .container { display: flex; } .left, .main, .right { height: 100px; } .left { flex: 0 0 300px; background: red; } .main { flex: 1 1 auto; background: yellow; } .right { flex: 0 0 300px; background: blue; } </style> </head> <body> <article class="container"> <aside class="left">left</aside> <main class="main">main</main> <aside class="right">right</aside> </article> </body> </html>
|
缺点:
- 无法兼容低版本的浏览器
优点:
- 代码简洁,DOM结构清晰
- 主流的实现方式
兼容性:
- PC端支持IE10及以上、Edge 12,chrome 21,firefox 28,safari 6.1(IE10为部分支持,其他浏览器版本为完全支持)
- 移动端支持iOS Safari 7, android browser 4.4
- 兼容性详情
网格布局方案
实现思路:
设置容器为grid,然后设置行高度为100px,设置三栏的宽度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>三栏布局-网格布局方案</title> <style> .container { display: grid; grid-template-rows: 100px; grid-template-columns: 300px 1fr 300px; } .left { background: red; } .main { background: yellow; } .right { background: blue; } </style> </head> <body> <article class="container"> <aside class="left">left</aside> <main class="main">main</main> <aside class="right">right</aside> </article> </body> </html>
|
缺点:
- 兼容性相对弹性盒要差,不过目前绝大部分浏览器较新的版本已经支持
优点:
- 代码简洁,DOM结构清晰
兼容性:
- PC端支持IE10及以上、Edge 16,chrome 57,firefox 52,safari 10.1(IE10为部分支持,其他浏览器为完全支持的起始版本)
- 移动端支持iOS Safari 10.3, android browser 67
- 兼容性详情
表格布局方案
实现思路:
设置容器为table且宽度为100%,并设置子元素为table-cell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>三栏布局-表格布局方案</title> <style> .container { display: table; width: 100%; } .left, .main, .right { display: table-cell; height: 100px; } .left { width: 300px; background: red; } .main { background: yellow; } .right { width: 300px; background: blue; } </style> </head> <body> <article class="container"> <aside class="left">left</aside> <main class="main">main</main> <aside class="right">right</aside> </article> </body> </html>
|
缺点:
- 非语义化
优点:
- 兼容浏览器版低
兼容性:
- PC支持IE8+, Firefox 3+, Chrome 4+, Safari 3.1+
- 移动端支持 iOS Safari 3.2, android browser 2.1
- 兼容性详情
圣杯布局
实现思路:
通过将左右两栏挂在容器的两侧,从而实现三栏布局,形状类似圣杯
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>三栏布局-圣杯布局方案</title> <style> .container { margin-left: 300px; margin-right: 300px; overflow: hidden; } .main, .left, .right { height: 100px; } .main { float: left; width: 100%; background: yellow; } .left { float: left; margin-left: -100%; width: 300px; position: relative; left: -300px; background: red; } .right { float: left; margin-left: -300px; width: 300px; position: relative; left: 300px; background: blue; } </style> </head> <body> <article class="container"> <main class="main">main</main> <aside class="left">left</aside> <aside class="right">right</aside> </article> </body> </html>
|
缺点:
- 当中间栏宽度比左栏宽度小时,布局会发生混乱
优点:
- 支持内容优先加载
兼容性:
- 参考浮动布局方案
双飞翼布局方案
实现思路:
基于圣杯布局,引入一个容器来放置中间栏,并且设置中间栏的外边距,不需要使用相对定位
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>三栏布局-双飞翼布局方案</title> <style> .main .in, .left, .right { height: 100px; } .main { float: left; width: 100%; } .main .in { margin-left: 300px; margin-right: 300px; background: yellow; } .left { float: left; width: 300px; margin-left: -100%; background: red; } .right { float: right; width: 300px; margin-left: -300px; background: blue; } </style> </head> <body> <article class="container"> <main class="main"> <div class="in">main</div> </main> <aside class="left">left</aside> <aside class="right">right</aside> </article> </body> </html>
|
缺点:
- DOM结构较复杂
优点:
- 支持内容优先加载
- 相对圣杯布局,宽度缩小,布局不会发生混乱
兼容性:
- 参考浮动布局方案
参考