前言

最近我朋友在群里发了一张图,说为什么main的宽度100%了,sub还是可以覆盖它呢?看来是时候带他回忆一波经典的圣杯布局和双飞翼布局了。正好最近看到好多面试题都有提到。 /笑哭

群内链接如下图:

圣杯布局和双飞翼布局 - 图1

字面意思

圣呗布局和双飞翼布局从字面意思来看是这样的:

一个像圣杯或者像展翅的禽类这样的布局

通俗的来说就是左右两栏固定宽度,中间部分自适应的三栏布局。

两者本质

圣杯布局和双飞翼布局 - 图2

圣杯布局

  1. 首先把left、middle、right都放出来
  2. 给它们三个设置上float: left, 脱离文档流;
  3. 一定记得给container设置上overflow: hidden; 可以形成BFC撑开文档
  4. left、right设置上各自的宽度
  5. middle设置width: 100%;

接下来比较重要了:

  1. 给left、middle、right设置position: relative;
  2. left设置 left: -leftWidth, right设置 right: -rightWidth;
  3. container设置padding: 0, rightWidth, 0, leftWidth;

我注意到圣杯布局的left、middle、right都有position: relative;

设:

  1. .left width:200px
  2. .right width:220px
  3. 复制代码

那么下面的这些属性为什么要存在?

  1. .container上面的paddind
  2. .left left: -200px;
  3. .right right: -220px;
  4. 复制代码

因为不这样设置 会遮挡middle的内容

可以自己尝试一下下


圣杯布局示例代码如下:

  1. <!DOCTYPE html>
  2. <html lang="zh">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>圣杯布局</title>
  8. <style>
  9. * {
  10. margin: 0;
  11. padding: 0;
  12. }
  13. .header,
  14. .footer {
  15. height: 100px;
  16. line-height: 100px;
  17. background-color: green;
  18. text-align: center;
  19. font-size: 30px;
  20. font-weight: bolder;
  21. }
  22. .footer {
  23. background-color: goldenrod;
  24. }
  25. .container {
  26. padding: 0 220px 0 200px;
  27. overflow: hidden;
  28. }
  29. .left,
  30. .middle,
  31. .right {
  32. position: relative;
  33. float: left;
  34. min-height: 130px;
  35. word-break: break-all;
  36. }
  37. .left {
  38. margin-left: -100%;
  39. left: -200px;
  40. width: 200px;
  41. background-color: red;
  42. }
  43. .right {
  44. margin-left: -220px;
  45. right: -220px;
  46. width: 220px;
  47. background-color: green;
  48. }
  49. .middle {
  50. width: 100%;
  51. background-color: blue;
  52. }
  53. </style>
  54. </head>
  55. <body>
  56. <div class="header">header</div>
  57. <div class="container">
  58. <div class="middle">
  59. <h4>middle</h4>
  60. <p>
  61. middlemiddlemiddlemiddlemiddlemiddlemiddlemiddle
  62. middlemiddlemiddlemiddlemiddlemiddlemiddlemiddle
  63. middlemiddlemiddlemiddlemiddlemiddlemiddlemiddle
  64. middlemiddlemiddlemiddlemiddlemiddlemiddlemiddle
  65. middlemiddlemiddlemiddlemiddlemiddlemiddlemiddle
  66. middlemiddlemiddlemiddlemiddle
  67. </p>
  68. </div>
  69. <div class="left">
  70. <h4>left</h4>
  71. <p>
  72. leftleftleftleftleftleftleftleftleftleftleftleft
  73. leftleftleftleftleftleftleftleftleftleftleftleft
  74. leftleftleftleftleftleftleftleftleftleftleftleft
  75. </p>
  76. </div>
  77. <div class="right">
  78. <h4>right</h4>
  79. <p>
  80. rightrightrightrightrightrightrightrightrightright
  81. rightrightrightrightrightrightrightrightrightright
  82. rightrightrightrightrightrightright
  83. </p>
  84. </div>
  85. </div>
  86. <div class="footer">footer</div>
  87. </body>
  88. </html>
  89. 复制代码

双飞翼布局

双飞翼布局和圣杯布局很类似,不过是在middle的div里又插入一个div,通过调整内部div的margin值,实现中间栏自适应,内容写到内部div中。

这样可以先做好主体部分,然后再将附属部分放到合适的位置!

  1. 首先把left、middle、right都放出来, middle中增加inner
  2. 给它们三个设置上float: left, 脱离文档流;
  3. 一定记得给container设置上overflow: hidden; 可以形成BFC撑开文档
  4. left、right设置上各自的宽度
  5. middle设置width: 100%;

接下来与圣杯布局不一样的地方:

  1. left设置 margin-left: -100%, right设置 right: -rightWidth;
  2. container设置padding: 0, rightWidth, 0, leftWidth;
  1. <!DOCTYPE html>
  2. <html lang="zh">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>双飞翼布局</title>
  8. <style>
  9. * {
  10. margin: 0;
  11. padding: 0;
  12. }
  13. .header,
  14. .footer {
  15. height: 100px;
  16. line-height: 100px;
  17. background-color: green;
  18. text-align: center;
  19. font-size: 30px;
  20. font-weight: bolder;
  21. }
  22. .footer {
  23. background-color: goldenrod;
  24. }
  25. .container {
  26. overflow: hidden;
  27. }
  28. .left,
  29. .middle,
  30. .right {
  31. float: left;
  32. min-height: 130px;
  33. word-break: break-all;
  34. }
  35. .left {
  36. margin-left: -100%;
  37. width: 200px;
  38. background-color: red;
  39. }
  40. .right {
  41. margin-left: -220px;
  42. width: 220px;
  43. background-color: green;
  44. }
  45. .middle {
  46. width: 100%;
  47. height: 100%;
  48. background-color: blue;
  49. }
  50. .inner {
  51. margin: 0 220px 0 200px;
  52. min-height: 130px;
  53. background: blue;
  54. word-break: break-all;
  55. }
  56. </style>
  57. </head>
  58. <body>
  59. <div class="header">header</div>
  60. <div class="container">
  61. <div class="middle">
  62. <div class="inner">
  63. <h4>middle</h4>
  64. <p>
  65. middlemiddlemiddlemiddlemiddlemiddlemiddlemiddle
  66. middlemiddlemiddlemiddlemiddlemiddlemiddlemiddle
  67. middlemiddlemiddlemiddlemiddlemiddlemiddlemiddle
  68. middlemiddlemiddlemiddlemiddlemiddlemiddlemiddle
  69. middlemiddlemiddlemiddlemiddlemiddlemiddlemiddle
  70. middlemiddlemiddlemiddlemiddle
  71. </p>
  72. </div>
  73. </div>
  74. <div class="left">
  75. <h4>left</h4>
  76. <p>
  77. leftleftleftleftleftleftleftleftleftleftleftleft
  78. leftleftleftleftleftleftleftleftleftleftleftleft
  79. leftleftleftleftleftleftleftleftleftleftleftleft
  80. </p>
  81. </div>
  82. <div class="right">
  83. <h4>right</h4>
  84. <p>
  85. rightrightrightrightrightrightrightrightrightright
  86. rightrightrightrightrightrightrightrightrightright
  87. rightrightrightrightrightrightright
  88. </p>
  89. </div>
  90. </div>
  91. <div class="footer">footer</div>
  92. </body>
  93. </html>
  94. 复制代码

总结

圣杯布局在DOM结构上显得更加直观和自然;

双飞翼布局省去了很多css,而且由于不用使用定位,可以获得比圣杯布局更小最小宽度;

说到这里需要注意一下 由于双飞翼布局会一直随着浏览器可视区域宽度减小从而不断挤压中间部分宽度。

所以需要设置给页面一个min-width > LeftWidth + RightWidth;


还有一件事就是他们在单独部分内容扩充的时候,童鞋们可能发现了 底部会参差不齐。

在我的老师那里知道了最简单的解决办法 / 笑哭

给left、middle、right设置上 padding-bottom: 9999px; margin-bottom: -9999px;

就让他变得无限高,但是又给他送回去了。真的是让我脑洞大开!!!

demo地址

圣杯布局

双飞翼布局