CSS 两列三列布局
一直以来对于布局自适应问题,都没有好好总结,趁着最近面试,忙碌之余也有空闲,便打算开始整理整理相关知识
1. 两列布局
1.1 float + BFC (左边固定,右边自适应)
<div>
<div style="float: left; width: 200px; background: red;">
left
</div>
<div style="background:green; overflow:hidden;">
i am right; i am right; i am right;
<br />
i am right; i am right; i am right;
<br />
i am right; i am right; i am right;
<br />
</div>
</div>
单独设置 左 元素 float: left
时,该元素脱离文档流。此时 右 元素会占据 左 元素的位置,并被 左 元素遮挡。但文字会环绕 左 元素。
此时,可通过让 右 元素形成 BFC,打破环绕。
1.2 float + margin-left (左边固定,右边自适应)
<div>
<div style="float: left; width: 200px; background: red;">
left
</div>
<div style="background:green; margin-left: 200px;">
i am right; i am right; i am right;
<br />
i am right; i am right; i am right;
<br />
i am right; i am right; i am right;
<br />
</div>
</div>
原理同上,通过 margin-left
使得 右 元素打破环绕。
1.3 absolute + margin-left (左边固定,右边自适应)
<div>
<div style="position: absolute; width: 200px; background: red;">
left
</div>
<div style="background:green; margin-left: 200px;">
i am right; i am right; i am right;
<br />
i am right; i am right; i am right;
<br />
i am right; i am right; i am right;
<br />
</div>
</div>
同 float + margin-left 的方案,既然 float 可以使得左边元素脱离文档流,那么 absolute 也可以脱离文档流。
这个时候可以使用 margin-left 与左边元素隔开距离,但是使用 overflow: hidden; 不可以。
1.4 absolute + absolute (左或右自适应宽度均可)
<div style="position: relative;">
<div style="position: absolute; left: 0; width: 200px;background: red;">
left
</div>
<div style="position: absolute; left: 200px; right: 0;background: blue;">
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
</div>
</div>
通过给两个子元素设置为 absolute, 绝对定位来自适应宽度。
1.5 float + 负外边距 (左或右自适应宽度均可)
1.5.1 左边自适应,右边定宽
.clearfix {
content: "";
display: block;
clear: both;
}
<div class="clearfix">
<div style="float: left; width: 100%;">
<div style="margin-right: 200px;background: red;">
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
</div>
</div>
<div style="float: left;background: blue; width: 200px; margin-left: -200px;">
I’m the Sidebar!
</div>
</div>
左右 元素均设置为左浮动,同时 左 元素宽度为 100%, 这时候 右 元素会被 挤 到下一行,而通过 margin-left 为 负的自身宽度(-200px), 又使得 左右 元素又在同一行。
但是这个时候, 左 元素会遮挡 右 元素,因此我们将真正内容作为 左 元素的子元素,设置子元素的 margin-right 确保与 右 元素隔开。
1.5.2 左边定宽,右边自适应
<div class="clearfix">
<div style="float: left;background: blue; width: 200px; margin-right: -100%;">
I’m the Sidebar!
</div>
<div style="float: left; width: 100%;">
<div style="margin-left: 200px;background: red;">
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
</div>
</div>
</div>
左右两个元素设置为 float: left, 右 元素设置宽度为 100%, 这时候左右元素分为两行。
设置左 元素 margin-right 为 -100%, 将右 元素又拉回到和 左 元素同一行。
这时候,右 元素会把 左 元素遮挡,那么通过设置 margin-left
和 左 元素拉开距离。
1.6 flex 布局 (左或右自适应宽度均可)
<div style="display: flex;">
<div style="width: 100%;background: red;">
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
</div>
<div style="background: blue; flex: 0 0 200px;">
I’m the Sidebar!
</div>
</div>
缺点:
- 需要注意IE兼容性
通过设置 flex: 0 0 200px
, 即 不伸长,不收缩,宽度为 200px
1.7 table (左边固定宽度,右边自适应)
<table>
<tbody>
<tr>
<td width="200px" style="background: red;">i am the sidebar</td>
<td style="background: blue;">
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
</td>
</tr>
</tbody>
</table>
利用 table 布局,在宽度固定的 td 标签上设置 width,另外一个元素自然会占据剩余宽度。
优点:
- 无需多余的 css 来实现自适应
- 垂直方向会自动居中
缺点:
- 很多多余的 HTML 结构嵌套
1.8 table-cell 伪表格布局 (左边固定宽度,右边自适应)
<div>
<div style="display: table-cell;width: 200px;background: red;">
left
</div>
<div style="display: table-cell;background: blue;">
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
Main content in here;
</div>
</div>
设置子元素为 table-cell, 可以实现和 table 一样的效果
2. 三列布局
2.1 圣杯布局
为了主内容区最先显示,因此在 dom 结构 middle 需要设置在最前面。
<div class='clearfix' style="padding: 0 200px 0 100px;">
<div style="float: left;background: blue;width: 100%;">middle</div>
<div style="float: left;background: red;width: 100px;margin-left: -100%;position: relative;left: -100px;">left</div>
<div style="float: left;background: green;width: 200px;margin-left: -200px;position: relative;left:200px;">right</div>
</div>
三列元素,都设置为 float: left, 这时候,三个元素会凑在一起。设置 middle 宽度为 100%, 这时候 middle 独占一行,left 与 right 相连,在第二行。
left 元素设置 margin-left 为 -100%, -100% 相对于 父元素宽度,此时 left 与 middle 同一行,且与 middle 左边对齐。
同理 right 元素设置 margin-left 为 (-自身的宽度), 则 right 与 middle 同一行,且与 middle 右边对齐。
三个元素同在一行,但是此时的问题是,left 会遮挡 middle 的左边,right 会遮挡 middle 的右边,即 middle 的宽度过宽, 那么我们可以设置 三个元素的共同父元素的 padding。
设置完 padding 之后, middle 的位置合适,但是此时 left 和 right 都有一定的偏移,这时候可以将 left, right 设置为 relative, 并移动对应的距离即可。
缺点:
- 在屏幕变小,middle 宽度小于 left 宽度时,布局会被破坏
2.2 双飞翼布局(淘宝对于圣杯布局的改进)
<div class='clearfix'>
<div style="float: left;background: blue;width: 100%;">
<div style="padding: 0 200px 0 100px;"> <!-- 使用 margin 也行 -->
middle
</div>
</div>
<div style="float: left;background: red;width: 100px;margin-left: -100%;">left</div>
<div style="float: left;background: green;width: 200px;margin-left: -200px;">right
</div>
</div>
同样是 float + 负 margin 的做法,放弃了 relative 定位的方式。而是通过增加一层 dom 结构,设置 padding 的值, 使得真正的内容显示在中间区域。
优点:
- 解决了圣杯布局出现的,屏幕小时,布局被破坏的问题
缺点:
- 需要多余的 dom 层级结构
2.3 绝对定位
<div style="position: relative;">
<div style="background: red;width: 100px;position: absolute; left: 0; top: 0;">left</div>
<div style="background: blue;margin: 0 200px 0 100px;"> <!-- padding 也行 -->
middle
</div>
<div style="background: green;width: 200px;position: absolute;right: 0; top: 0;">right
</div>
</div>
优点:
- 左 中 右 dom 结构的位置顺序可以随意调整
缺点:
- 左 中 右 的实际高度由 middle 决定,如果 left / right 高于 middle,此时 left / right 会遮挡 footer 区域
2.4 浮动定位
<div style="position: relative;">
<div style="background: red;width: 100px; float: left;">left</div>
<div style="background: green;width: 200px; float: right;">right</div>
<div style="background: blue;margin: 0 200px 0 100px;"> <!-- padding 也行 -->
middle
</div>
</div>
同绝对定位一样,也就是使得 左 右 元素脱离文档流,middle 元素使用 padding 或 margin 与两个元素隔出距离。
缺点:
- middle元素必须出现在 left 和 right 元素之后,不利于主题内容的呈现
2.5 flex 布局
<div style="display: flex;">
<div style="background: red; flex: 0 0 100px;">left</div>
<div style="background: blue; flex: 1 1 auto;">
middle
</div>
<div style="background: green; flex:0 0 200px;">right
</div>
</div>
优点:
- 左 中 右 元素的 dom 结构顺序可以通过设置 order 来处理,很灵活
<div style="display: flex;">
<div style="background: blue; flex: 1 1 auto;">
middle
</div>
<div style="background: red; flex: 0 0 100px; order: -1;">left</div>
<div style="background: green; flex:0 0 200px;">right
</div>
</div>
缺点:
- 需要注意 flex 在 IE 下的兼容性
参考资料
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论