左侧固定,右侧自适应的布局方案

Clloz · · 49次浏览 ·

前言

两栏布局是我们经常遇到的一种布局方式,实现两栏布局一般的需求是左侧固定宽度,右侧自适应,解决方法也多种多样,可以用float,inline-block,配合calc来设置宽度,也可以用CSS3的新布局方法flex grid,其实核心问题就是如何让两个元素在同一行并且合理分配他们的宽度。下面来总结一下不同的方法以及其中的细节和注意点。

基本布局和基本样式

虽然解决的方法各不相同,但是整个HTML的结构和一些必要的样式是一样,所以我们先把这个骨架搭好,后面只要给这个骨架一些小的装饰就可以完成功能了,这样对于我们的扩展和维护都比较有利。

两栏布局的结构非常简单,我们需要一个wrap和一左一右两个div就可以了,所以HTML结构如下:

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

然后我们要把一些在各种实现方式下都统一的样式提取出来,比如左侧的宽度,两个块之间的间距,字体,背景色,内边距等,本文我们设置左侧div宽度为200px,两个div间距10px,如果设置左右不同的border或者padding需要设置box-sizing: border-box

.wrap {
    height: 200px;
    margin-top: 30px;
    position: relative;
}

.wrap .left,
.wrap .right {
    height: 100%;
    padding: 10px;
    box-sizing: border-box;
    color: white;
    font-size: 30px;
    line-height: 1.5;
}

.wrap .left {
    background-color: pink;
    width: 200px;
}

.wrap .right {
    background-color: #32afd8;
}

完成了基本框架我们就可以开始尝试各种不同的实现方法了。

float+margin-left方案

要让两个元素在同一行我们首先想到的就是float,宽度自适应是块级元素的特性。这个方案是设置左侧的div浮动,给右侧的div一个margin-left来实现的。块级元素有默认独占一行,并且填满父容器,随着父元素的宽度自适应的流动特性。而float元素会脱离normal flow,后面的块级元素的布局会无视浮动元素的存在来渲染。所以我们只要让左侧的元素浮动,就能让两个块级元素存在在同一行,但是为了不让元素重叠,我们需要给左边的元素预留足够的距离以便两个元素都能完全展示出来,所以我们要为右边的元素设置margin-left,值为左侧元素的宽度加上两个元素之间的距离。代码如下:

.eg1 .left {
    float: left;
}

.eg1 .right {
    margin-left: 210px;
}

需要注意的是如果父元素没有设置高度,那么由于浮动的存在会发生高度塌陷,需要清除浮动。

双float方案

单个float可以,那么我们设置两个元素都是float自然也没问题,两个元素会在同一行,唯一的问题是元素浮动以后宽度是根据内容决定的,我们需要为右边的元素设置一个宽度,calc函数可以帮我们解决这个问题。

.eg3 .left,
.eg3 .right {
    float: left;
}

.eg3 .right {
    width: calc(100% - 210px);
    margin-left: 10px;
}

.clearfix::after {
    content: '';
    display: block;
    clear: both;
}

这种方式同样需要注意父元素的清除浮动

方案缺点:

  • 需要知道左侧元素的宽度和两个元素之间的距离,并且要设置box-sizing
  • 需要清除浮动

inline-block方案

floatinline-block是非常相似的,一般用float可以解决的问题,inline-block也一样可以,两栏布局同样可以用inline-block来解决。我们设置左右两个元素display: inline-block,由于inline-block的特性,我们需要设置父元素的font-size: 0;以避免两个元素间的空格,同时因为两个元素的字体大小以及padding不同等原因,我们需要用vertical-align属性来对其两个元素。代码如下:

.eg2 .left,
.eg2 .right {
    display: inline-block;
    vertical-align: top;
}

.eg2 .left {
    width: 200px;
}

.eg2 .right {
    width: calc(100% - 210px);
    margin-left: 10px;
}

对于vertical-align的细节不理解的可以看这篇文章

方案缺点:

  • 需要知道左侧元素的宽度和两个元素之间的距离
  • 需要解决inline-block缝隙问题
  • 需要用vertical-aling来对齐元素

absolute+margin-left方案

用绝对定位同样可以让两个块级元素在同一行排列,和float+margin-left的使用方法相似,浮动和绝对定位的区别是绝对定位完全脱离了文档流,而浮动依然保留了一些流动性。我们需要设置父元素的position为非static,同时由于没有清除浮动类似的机制,我们必须为父元素限定min-height,否则左侧元素的高度超出右侧元素的话,就会溢出。代码如下:

.eg4 .left {
    position: absolute;
}

.eg4 .right {
    margin-left: 210px;
}

方案缺点:

  • 需要设置父元素的position为非static
  • 需要限定高度

float+BFC方案

BFC有一个特性是不会和float元素重叠,利用这一特性,我们可以让左边的元素浮动,右边的元素生成一个新的BFC,在给一个边距就实现了需求。代码如下:

.eg5 .left {
    float: left;
    margin-right: 10px;
}

.eg5 .right {
    overflow: hidden;
}

需要注意,如果是用overflow来实现的BFC并使用margin-left来预留编剧必须加上左边元素的宽度。

flex布局方案

flex可以说是最好的方案了,代码少,使用简单。有朝一日,大家都改用现代浏览器,就可以使用了。
需要注意的是,flex容器的一个默认属性值:align-items: stretch;。这个属性导致了列等高的效果。
为了让两个盒子高度自动,需要设置: align-items: flex-start;代码如下:

.wrap.wrap-flex {
    display: flex;
    align-items: flex-start;
}

.wrap.wrap-flex .left {
    flex: 0 0 auto;
}

.wrap.wrap-flex .right {
    flex: 1 1 auto;
    margin-left: 10px;
}

当父容器宽度放不下两个元素的情况

  1. 双float和双inline-block方案右侧元素会移动到下一行,并根据calc函数计算宽度
  2. 采用了margin-left的方案右侧元素会不可见,宽度为0
  3. BFC方案右侧元素也会掉到下一行。
  4. flex方案依然会按照原来的布局显示

文中示例查看页面
更直观的示例查看页面

参考文章

七种实现左侧固定,右侧自适应两栏布局的方法


Clloz

人生をやり直す

发表评论

电子邮件地址不会被公开。 必填项已用*标注

我不是机器人*

EA PLAYER &

历史记录 [ 注意:部分数据仅限于当前浏览器 ]清空

      00:00/00:00