css 关于div左右布局-左边定宽右边自适应

Author Avatar
tangdaohai 5月 21, 2017
  • 在其它设备中阅读本文章

一个比较常见的 css 布局面试题。 两个 div, 左边固定宽度, 右边 div 自适应宽度, 或者右边定宽,左边自适应都一样。

讲真这个面试题我也不知道在什么时候就有了, 但我确实是上周才看到, 才知道的… 因为我毕业后就经历过一次面试,然后一直在第一家公司工作到现在, 那时候主要是 js 与 java 方向…

1.使用 float

外层 div, 内部两个 div。定宽 div 设置float:right;属性, 自适应 div 只需要设置margin: 200px;(本文里面定宽 div 宽度都为200px), 其实就是预留出定宽 div 的空间

可以拖动浏览器窗口, 改变宽度试一下。在源博客地址中是可以正常展示的, 如果是分享爬虫类的站点可能会无法显示效果, 原文地址: css 关于div左右布局-左边定宽右边自适应

如下:

csscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscss

源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.float-container{
padding: 5px;
border: 1px solid #eee;
overflow: hidden;
}
.float-left{
width: 200px;
height: 100px;
background-color: mediumspringgreen;
float: left;
}
.float-right{
height: 100px;
background-color: skyblue;
word-wrap: break-word;
margin-left: 200px;
}
1
2
3
4
5
6
<div class="float-container">
<div class="float-left">1</div>
<div class="float-right">
csscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscss
</div>
</div>

但这种方式有个缺陷, 就是在html 中书写的顺序, 自适应 div 必须在定宽 div 的后面, 如果位置颠倒一下或者在左边定宽右边自适应的时候, 定宽的 div 并不听话了

1
2
3
4
5
6
7
<div class="float-container">
<!-- 调整左右 div 的书写顺序 -->
<div class="float-right">
csscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscss
</div>
<div class="float-left"></div>
</div>

就像下面这样:

csscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscsscss

为什么会这样呢?

原因很简单, 自适应 div 并没有设置 float、inline 等属性, 始终保持着 div 的继承父级宽高的特性, 自适应宽度的 div 先沾满了整个父级 div。如果定宽 div 写在了它后面, 那自然不会去侵占兄弟的地盘了, 只能被挤到了下面一行了。具体可以了解下html 文档流相关知识

怎么解决呢?

也很简单, 既然它是胆小鬼不会主动去抢占兄弟的地盘, 那我们帮它一下好了… 设置绝对定位的属性让它去那个空白的位置, 也就是margin-left: 200px;空出来的区域, 原来你兄弟早就给你留好了位置呀, 那还客气什么呢…

给定宽 div 的元素增加绝对定位属性(如果左边定宽的话,只需要修改 left-> right):

1
2
3
position: absolute;
left: 0;
top: 0;

当然父级元素也要增加一条属性(不然 float 属性的 div就会根据 body 去绝对定位了)

1
position: relative;

2.使用 display:table

这种方式就相对简单了, 父级元素设置display:table; width:100%;(父级必须设置宽度)。内部 div 设置为display:table-cell;。 给其中一个设置宽度,另一个自然而然的自适应宽度了。 但这个貌似只支持到IE7, 但我觉得现在这年代, IE 就不要去管它了吧, 他亲爹都不理它, 我们也不理它, 随它自生自灭去吧…

注意书写顺序, 会影响定宽元素在左边显示还是在右边显示

效果如下:

源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.table-container{
width: 100%;
padding: 5px;
border: 1px solid #eee;
display: table;
}
.table-left{
width: 200px;
background-color: mediumspringgreen;
}

.table-right{
background-color: skyblue;
}

.table-left, .table-right{
height: 100px;
display: table-cell;
}
1
2
3
4
<div class="table-container">
<div class="table-left"></div>
<div class="table-right"></div>
</div>

3. 使用 flex 布局

flex 布局是我个人非常喜欢的一种方式, 写起来爽歪歪。先给父级元素设置display: flex;。使用 felx 有两种实现方式(可能更多, 据我知道只有两种, 欢迎补充)

注意书写顺序, 会影响定宽元素在左边显示还是在右边显示

1. 定宽div设置 flex-shrink:0, 自适应div设置 width:100%;

flex-shrink 默认值为1, 表示空间不足将会缩小。如果设置为0表示空间不足也不缩小。另一个元素设置为width: 100%, 因为 flex 默认属性flex-shrink空间不足会自动缩小, 利用这个特性实现了自适应宽度。

效果如下:

源码源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.flex-container{
width: 100%;
padding: 5px;
border: 1px solid #eee;
display: flex;
}

.flex-left{
width: 200px;
height: 100px;
background-color: mediumspringgreen;
flex-shrink: 1;
}

.flex-right{
width: 100%;
height: 100px;
background-color: skyblue;
}
1
2
3
4
<div class="flex-container">
<div class="flex-left"></div>
<div class="flex-right"></div>
</div>

2. 自适应 div 设置flex-grow:1

flex-grow表示元素会不会自动填充多余的空间。默认值为0, 表示不会自动填充剩余空间。 如果这个元素设置为1, 那么这个元素不拉伸直至占满剩余的空间(如果有多余的空间)。这个属性太适合自适应 div 了, 也不需要给自适应 div 设置宽度, 这不就是为其量身打造的嘛。

这次将使左边的 div 自适应。

效果如下:

源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.flex-container{
width: 100%;
padding: 5px;
border: 1px solid #eee;
display: flex;
}

.flex-grow-left{
height: 100px;
background-color: skyblue;
flex-grow: 1;
}

.flex-grow-right{
width: 200px;
height: 100px;
background-color: mediumspringgreen;
}
1
2
3
4
<div class="flex-container">
<div class="flex-left"></div>
<div class="flex-right"></div>
</div>

个人比较喜欢最后这一个方式只要增加两个属性(父元素一个, 子元素一个)就实现了这种布局, 方便至极。

以上, 致那颗骚动的心……