CSS布局经典问题:两栏布局-左侧固定,右侧自适应

这个问题在开发时碰过非常多次,是经典布局问题。很多公司的面试题也会问这类问题,今天就详细的来谈一下这类问题。


还有一篇类似的文章,关于三栏布局 详情请戳


题意非常明确,左侧的块宽度是固定的,右侧的宽度会随着浏览器的宽度变化的,见下图。

1.BFC

为了解决这个问题,首先,我们来理解一下何为BFC。

BFC(Block Formatting Context)直译为“块级格式化范围”。

BFC提供了一个环境,HTML元素在这个环境中按照一定规则进行布局。它不会影响到其它环境中的布局。可以把它理解成是一个独立的容器,并且这个容器的里box的布局,与这个容器外的毫不相干。

触发BFC的条件
  1. float的值不为none。
  2. overflow的值不为visible。
  3. display的值为table-cell, table-caption, inline-block中的任何一个。
  4. position的值不为relative和static。

为了加深我们理解BFC为何物,下面看一个例子,上代码。

    .wrapper{ border: 5px solid #000; }
    .red { background-color:red; }
    .yellow { background-color:yellow; }
    .orange { background-color:orange; }
    .green { background-color:green; }
    .box{ 100px; height:100px; float:left; }
    <div class="wrapper">
        <div class="container">
            <div class="red box"></div>
            <div class="yellow box"></div>
        </div>
        <div class="container">
            <div class="orange box"></div>
            <div class="green box"></div>
        </div>
    </div>

见效果:

很明显,.wrapper中所有的box都是浮动,父级标签没有被内容撑开,虽然.red、.yellow和.orange和.green是在两个不同的div中,但是仍不会换行。这是由于设置了浮动元素的块会形成一个BFC布局,前面提到过了:

  1. 对于一个BFC来说它不会影响到其他环境的布局,反之亦然。
  2. 在BFC中,每一个元素左外边与包含块的左边相接触(对于从右到左的格式化,右外边接触右边),即使存在浮动也是如此。
  3. 当容器有足够的剩余空间容纳BFC的宽度时,所有浏览器都会将BFC放置在浮动元素所在行的剩余空间内。
  4. 在进行普通流中的块级非替换元素的高度计算时,浮动子元素不参与计算。
  5. 在计算生成了BFC 的元素的高度时,其浮动子元素应该参与计算。
    故呈现了这样的效果。

若想要让每一个.container中的元素都单独占据一行,可以让.container变成BFC布局(overflow:hidden)。

看到这里。相信你对BFC也有一定的理解了。如若不理解,可以看看这篇文章,有可取之处。
关于Block Formatting Context--BFC和IE的hasLayout

关于IE的layout可以看看这篇文章
IE的layout属性详解


2.左侧固定,右侧自定义布局实现

回到题目,下面来看看如何实现左侧固定,右侧自适应布局

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

2.1利用BFC之方法一

由于在BFC中,每一个元素左外边与包含块的左边相接触(对于从右到左的格式化,右外边接触右边),即使存在浮动也是如此。创建了BFC的元素不能与浮动元素重叠。且当容器有足够的剩余空间容纳BFC的宽度时,所有浏览器都会将BFC放置在浮动元素所在行的剩余空间内。利用这些特性,就可以达到效果。

    .left{
        float: left;
         200px;
        height: 200px;
        background: green;
    }
    .right{
        overflow: hidden;
        height: 300px;
        background: red;
    }

2.2利用margin-left

首先还是设置left浮动让他变为BFC,由2.1方法可知,在BFC中,每一个元素左外边与包含块的左边相接触(对于从右到左的格式化,右外边接触右边),即使存在浮动也是如此。所以left和right会重叠。然后利用margin-left让right腾出位置。

        .left{
            float: left;
             200px;
            height: 200px;
            background: green;
        }
        .right{
            margin-left: 200px;
            height: 300px;
            background: red;
        }

2.3使用绝对定位

同样,这个方法和2.2方法类似,也是left的形成BFC方式不同,就不过多描述了。

    .container{
        position: relative;
    }
    .left{
        position: absolute;
        left: 0;
        top: 0;
         200px;
        height: 200px;
        background: green;
    }
    .right{
        margin-left: 200px;
        height: 200px;
        background: red;
    }

2.4利用flex布局

flex布局走天下阿。。但是兼容性问题还是摆在那里,有所取舍吧。

    .container{
        display: flex;
        display: -webkit-box;
        display: -moz-box;
        display: -ms-flexbox;
        100%;
        height: 200px;
    }
    .left{
         200px;
        background: green;
    }
    .right{
        // 如果此处用100%会导致左侧元素不足固定宽度,因为left+right的宽度大于父级宽度,会进行一个等比缩放
        //100%;
        flex:1;
        background: red;
    }

2.5利用grid布局

 .container{
        display: grid;
        grid-template-rows: 200px;
        grid-template-columns: 200px auto;
        100%;
    }
    .left{
        background: green;
    }
    .right{
        background: red;
    }

2.6利用table-cell

 .container{
        display: table;
        100%;
    }
    .left{
        display: table-cell;
        height: 200px;
         200px;
        background: green;
    }
    .right{
        display: table-cell;
        height: 200px;
        background: red;
    }

知识扩展

前面提到了BFC,与之类似的还有IFC,GFC,FFC。。很晕吧,贴上两个链接,希望你看了能有所收获。
CSS魔法堂:重新认识Box Model、IFC、BFC和Collapsing margins
css3之BFC、IFC、GFC和FFC


以上内容,如有错误请指出,不甚感激。

原文地址:https://www.cnblogs.com/adelina-blog/p/6781945.html