【css】圣杯布局双飞翼布局的各种解法与思考分析

背景

  • 现在布局一般都用flex了,最近发现考布局还有很多在考圣杯布局和双飞翼布局的,所以来研究下。

圣杯布局

html骨架

<div class="content">
    <div class="center">
    </div>
    <div class="left">
    </div>
    <div class="right">
    </div>
</div>

原理

  • 圣杯布局原理就是父元素左右两边留出固定内边距,让左右两块塞进这个内边距里。

第一种解法

  • 第一种解法就是百度到最多的解法,内部三元素全部浮动和相对定位。
  • 主要技巧:
  • 一、利用相对定位元素之间参照定位为最近的元素,使得每个元素可以使用margin和left来调整自身位置。
  • 二、利用float元素并排显示特性,调整每个元素位置即可放入padding。
  • 缺点:
  • 当中间元素间距小于左边元素间距时就会发生bug,导致left位移一个自身身位不够一行,于是换到下一行。我就没懂为啥这种有明显bug的布局会那么多人抄。
       .content{
            padding: 0 300px;
        }
        .center,.left,.right{
            position: relative;
            min-height: 130px;
            float: left;
        }
        .center{
            background: blue;
            width: 100%;
        }
        .left{
            left:-300px;
            margin-left: -100%;
            background: yellow;
            width: 300px;
        }
        .right{
            background: #000;
            width:300px;
            left:100%;
            margin-left:-100%;
        }

第二种解法

  • 第一种解法是利用相对位置之间进行参照,我们也可以把包裹的容器作为相对位置进行定位,然后用calc计算。
  • 主要技巧:
  • 利用calc来计算位置,左侧靠左边距,右侧靠右边距塞进去。
  • 缺点:
  • 好像没啥缺点。calc可能有兼容性问题
   		.content{
            padding: 0 300px;
            position: relative;
        }
        .center,.left,.right{
            min-height: 130px;
            float: left;
        }
        .center{
            background: blue;
            width: 100%;
        }
        .left{
            background: yellow;
            width: 300px;
            margin-left: calc(-100% - 300px);
        }
        .right{
            background: #000;
            width:300px;    
            margin-right: -300px;
        }

第三种解法

  • 我们发现float可以水平排列,那么要让元素行内排列除了float还能用什么?
  • 没错就是inline-block。
  • 主要技巧:
  • 一、由于都为行内块,所以父元素需要添加不换行属性。
  • 二、由于默认font-size不为0,所以为了无偏差需要改字号。
  • 缺点:
  • 这种布局倒是不会出现第一种解法的bug,但是由于改了字号所以内部不适合直接放内容。
      .content{
            padding: 0 300px;
            white-space: nowrap;
            font-size: 0;
        }
        .center,.left,.right{
            position: relative;
            min-height: 130px;
            display: inline-block;
        }
        .center{
            background: blue;
            width: 100%;
        }
        .left{
            left: -300px;
            margin-left:-100%;
            background: yellow;
            width: 300px;
        }
        .right{
            background: #000;
            width:300px;
            margin-left: 100%;
            right: 300px;
        }

第四种解法

  • 除了上面几种解法,当然还有万能的绝对定位,直接把元素塞进padding里即可。
  • 主要技巧:
  • 没什么技巧,就是暴力。
  • 缺点:
  • 好像没啥特别的缺点。
        .content{
            padding: 0 300px;
            position: relative;
        }
        .center,.left,.right{
            min-height: 130px;
        }
        .center{
            background: blue;
            width: 100%;
        }
        .left{
            background: yellow;
            width: 300px;
            position: absolute;
            top:0;
            left:0;
        }
        .right{
            background: #000;
            width:300px;
            position: absolute;
            top:0;
            right: 0;
        }

双飞翼布局

html骨架

<div class="container"> 
  <div class="main">
      <div class="content"></div> 
    </div>
  <div class="left"></div> 
  <div class="right"></div> 
</div>

原理

  • 前面说圣杯是父元素挖出个内边距留给两侧,这个双飞翼由于里面多了个div,所以原理就是里面的div设置外边距把位置让出来,另外2个调整位置插进去。

第一种解法

  • 首先是百度的最多的解法:
  • 主要技巧:
  • 一、跟上面圣杯一样,也是利用float元素调整边距会在一行的特性。
  • 二、跟上面有个区别,就是不需要相对定位调整位置了,于是也没有上面圣杯用相对定位的位移而产生的bug。
  • 三、需要设置字体大小,不然main嵌套的content位置下移。
     .left, .main, .right {
            float: left;
            min-height: 130px;       
        }
        .left {
            margin-left: -100%;
            background: green;
            width: 200px;
        }
        .right {
            margin-left: -300px;
            background-color: red;
            width: 300px;
        }
        .main {
            font-size: 0;
            width: 100%;
        }
        .content{
            margin: 0 300px 0 200px;
            background: blue;
            min-height: 130px;
        }

第二种解法

  • 用inline-block
  • 由于main和content都要设置inline-block,所以导致宽度继承了body的宽度,无法获取真正的100%宽度,于是靠calc来计算。
  • 主要技巧:
  • 利用calc计算中间区域内容宽度以及右侧栏边距。
        .left, .main, .right {
            display: inline-block;
            min-height: 130px;        
        }
        .left {
            background: green;
            width: 200px;
            margin-left: -100%;
        }
        .right {
            background-color: red;
            width: 300px;
            margin-left: calc(100% - 300px - 200px);
        }
        .main {
            width: 100%
        }
        .content{
            margin: 0 300px 0 200px;
            background: blue;
            min-height: 130px;
            display: inline-block;
            width:calc(100% - 300px - 200px)
        }
        .container{
            white-space: nowrap;
            font-size: 0;
        }

第三种解法

  • 万能解法绝对定位。
  • 这个没啥说的,不管什么布局都很好用。
  .container{
            position: relative;
            font-size: 0;
        }
        .left {
            background: green;
            width: 200px;
            height: 130px;
            position: absolute;
            top:0;
            left:0
        }
        .right {
            background-color: red;
            width: 300px;
            height: 130px;
            position: absolute;
            top:0;
            right:0
        }
        .main{
            position: relative;
        }
        .content{
            margin: 0 300px 0 200px;
            background: blue;         
            height: 130px;
        }

总结

  • 以上就是圣杯和双飞翼的各种解法,当然用flex,grid,table之类也能做出来,只是为其思想(挖内边距填位置和挖外边距填位置)试着去用各种方法做相同的布局。另外和calc类似的transform那些就不说了。
  • 可以发现,这2种布局都比较老式,但还是有比较好的解法,除去万能绝对定位,圣杯布局推荐用第三种方式,双飞翼推荐用第一种方式。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

业火之理

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值