首先创建基本的HTML布局和最基本的样式。
<div class="wrapper" id="wrapper"> <div class="left"> 左边固定宽度,高度不固定 </br> </br></br></br>高度有可能会很小,也可能很大。 </div> <div class="right"> 这里的内容可能比左侧高,也可能比左侧低。宽度需要自适应。</br> 基本的样式是,两个div相距20px, 左侧div宽 120px </div> </div>
.wrapper {
padding: 15px 20px;
border: 1px dashed #ff6c60;
}
.left {
width: 120px;
border: 5px solid #ddd;
}
.right {
margin-left: 20px;
border: 5px solid #ddd;
}
一、布局方式
1、双inline-block
作为两个inline-block
的盒子,必须设置vertical-align
来使其顶端对齐。为了准确地应用计算出来的宽度,需要消除div
之间的空格,需要通过设置父容器的font-size: 0;
,或者用注释消除html
中的空格等方法。
.wrapper-inline-block {
box-sizing: content-box;
font-size: 0; // 消除空格的影响
}
.wrapper-inline-block .left,
.wrapper-inline-block .right {
display: inline-block;
vertical-align: top; // 顶端对齐
font-size: 14px;
box-sizing: border-box;
}
.wrapper-inline-block .right {
width: calc(100% - 140px);
}
注意点:
-
需要知道左侧盒子的宽度,两个盒子的距离,还要设置各个元素的
box-sizing
-
需要消除空格字符的影响
-
需要设置
vertical-align: top
满足顶端对齐。
2、双flot
通过动态计算宽度来实现自适应,由于浮动的block
元素在有空间的情况下会依次紧贴,排列在一行,所以无需设置display: inline-block;
,也就少了顶端对齐,空格字符占空间等问题。
.wrapper-double-float {
overflow: auto; // 清除浮动
box-sizing: content-box;
}
.wrapper-double-float .left,
.wrapper-double-float .right {
float: left;
box-sizing: border-box;
}
.wrapper-double-float .right {
width: calc(100% - 140px);
}
注意点:
-
需要知道左侧盒子的宽度,两个盒子的距离,还要设置各个元素的
box-sizing
。 -
父元素需要清除浮动。
3、float+margin-left方案
利用了block
级别的元素盒子的宽度具有填满父容器,并随着父容器的宽度自适应的流动特性。
但是block
级别的元素都是独占一行的,所以要想办法让两个block
排列到一起。block
级别的元素会认为浮动的元素不存在,但是inline
级别的元素能识别到浮动的元素。这样,block
级别的元素就可以和浮动的元素同处一行了。
为了让右侧盒子和左侧盒子保持距离,需要为左侧盒子留出足够的距离。这个距离的大小为左侧盒子的宽度以及两个盒子之间的距离之和。然后将该值设置为右侧盒子的margin-left
。
.wrapper-float {
overflow: hidden; // 清除浮动
}
.wrapper-float .left {
float: left;
}
.wrapper-float .right {
margin-left: 150px;
}
注意点:
-
需要清除浮动
-
需要计算右侧盒子的
margin-left
4、absolute+margin-left方案
让两个block
排列到一起的方法是对左侧盒子使用position: absolute
的绝对定位。这样,右侧盒子也能无视掉它。
.wrapper-absolute .left {
position: absolute;
}
.wrapper-absolute .right {
margin-left: 150px;
}
注意点:
-
使用了绝对定位,若是用在某个div中,需要更改父容器的
position
。 -
没有清除浮动的方法,若左侧盒子高于右侧盒子,就会超出父容器的高度。因此只能通过设置父容器的
min-height
来放置这种情况。
5、float+BFC方案
利用左侧浮动,但是右侧盒子通过overflow: auto;
形成了BFC,因此右侧盒子不会与浮动的元素重叠。
为左侧的浮动盒子设置margin-right
,就可以实现两个盒子的距离了。而右侧盒子是block
级别的,所以宽度能实现自适应。
.wrapper-float-bfc {
overflow: auto;
}
.wrapper-float-bfc .left {
float: left;
margin-right: 20px;
}
.wrapper-float-bfc .right {
margin-left: 0;
overflow: auto;
}
注意点:
- 父元素需要清除浮动
6、flex方案
flex
容器的一个默认属性值:align-items: stretch;
。这个属性导致了列等高的效果。
为了让两个盒子高度自动,需要设置: align-items: flex-start;
.wrapper-flex {
display: flex;
align-items: flex-start;
}
.wrapper-flex .left {
flex: 0 0 auto;
}
.wrapper-flex .right {
flex: 1 1 auto;
}
7、grid方案
.wrapper-grid {
display: grid;
grid-template-columns: 120px 1fr;
align-items: start;
}
.wrapper-grid .left,
.wrapper-grid .right {
box-sizing: border-box;
}
.wrapper-grid .left {
grid-column: 1;
}
.wrapper-grid .right {
grid-column: 2;
}
注意点:
-
grid
布局也有列等高的默认效果。需要设置:align-items: start;
。 -
grid
布局还有一个值得注意的小地方和flex
不同:在使用margin-left
的时候,grid
布局默认是box-sizing
设置的盒宽度之间的位置。而flex
则是使用两个div的border
或者padding
外侧之间的距离。
二、极限情况
最后可以再看一下在父容器极限小的情况下,不同方案的表现。主要分成四种情况:
-
动态计算宽度的情况
两种方案: 双inline-block方案和双float方案。宽度极限小时,右侧的div宽度会非常小,由于遵循流动布局,所以右侧div会移动到下一行。
-
动态计算右侧margin-left的情况
两种方案: float+margin-left方案和absolute+margin-left方案。宽度极限小时,由于右侧的div忽略了文档流中左侧div的存在,所以其依旧会存在于这一行,并被隐藏。
-
float+BFC
方案的情况这种情况下,由于BFC与float的特殊关系,右侧div在宽度减小到最小后,也会掉落到下一行。
-
flex
和grid
的情况这种情况下,默认两种布局方式都不会放不下的div移动到下一行。不过 flex布局可以通过 flex-flow: wrap;来设置多余的div移动到下一行。 grid布局暂不支持。