常用的宽度自适应的方法通常是利用了block
水平的元素宽度能随父容器调节的流动特性。另外一种思路是利用CSS中的calc()
方法来动态设定宽度。还有一种思路是,利用CSS中的新型布局flex layout
与grid layout
。
首先创建基本的HTML布局和最基本的样式。
<div class="wrapper" id="wrapper">
<div class="left">
左边固定宽度,高度不固定 </br> </br></br></br>高度有可能会很小,也可能很大。
</div>
<div class="right">
这里的内容可能比左侧高,也可能比左侧低。宽度需要自适应。</br>
基本的样式是,两个div相距20px, 左侧div宽 120px
</div>
</div>
基本的样式是,两个盒子相距20px
, 左侧盒子宽 120px
,右侧盒子宽度自适应。基本的CSS样式如下:
.wrapper {
padding: 15px 20px;
border: 1px dashed #ff6c60;
}
.left {
width: 120px;
border: 5px solid #ddd;
}
.right {
margin-left: 20px;
border: 5px solid #ddd;
}
下面的代码都是基于这套基本代码做覆盖,通过给容器添加不同的类来实现效果。
双inline-block
方案
.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);
}
这种方法是通过width: calc(100% - 140px)
来动态计算右侧盒子的宽度。需要知道右侧盒子距离左边的距离,以及左侧盒子具体的宽度(content+padding+border),以此计算父容器宽度的100%
需要减去的数值。同时,还需要知道右侧盒子的宽度是否包含border
的宽度。
在这里,为了简单的计算右侧盒子准确的宽度,设置了子元素的box-sizing:border-box;
以及父元素的box-sizing: content-box;
。
同时,作为两个inline-block
的盒子,必须设置vertical-align
来使其顶端对齐。
另外,为了准确地应用计算出来的宽度,需要消除div
之间的空格,需要通过设置父容器的font-size: 0;
,或者用注释消除html
中的空格等方法。
缺点:
-
需要知道左侧盒子的宽度,两个盒子的距离,还要设置各个元素的
box-sizing
-
需要消除空格字符的影响
-
需要设置
vertical-align: top
满足顶端对齐。
双float
方案
.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);
}
本方案和双float
方案原理相同,都是通过动态计算宽度来实现自适应。但是,由于浮动的block
元素在有空间的情况下会依次紧贴,排列在一行,所以无需设置display: inline-block;
,自然也就少了顶端对齐,空格字符占空间等问题。
不过由于应用了浮动,父元素需要清除浮动。
缺点:
-
需要知道左侧盒子的宽度,两个盒子的距离,还要设置各个元素的
box-sizing
。 -
父元素需要清除浮动。
float+margin-left
方案
.wrapper-float {
overflow: hidden; // 清除浮动
}
.wrapper-float .left {
float: left;
}
.wrapper-float .right {
margin-left: 150px;
}
上面两种方案都是利用了CSS的calc()
函数来计算宽度值。下面两种方案则是利用了block
级别的元素盒子的宽度具有填满父容器,并随着父容器的宽度自适应的流动特性。
但是block
级别的元素都是独占一行的,所以要想办法让两个block
排列到一起。
我们知道,block
级别的元素会认为浮动的元素不存在,但是inline
级别的元素能识别到浮动的元素。这样,block
级别的元素就可以和浮动的元素同处一行了。
为了让右侧盒子和左侧盒子保持距离,需要为左侧盒子留出足够的距离。这个距离的大小为左侧盒子的宽度以及两个盒子之间的距离之和。然后将该值设置为右侧盒子的margin-left
。
缺点:
-
需要清除浮动
-
需要计算右侧盒子的
margin-left
使用absolute+margin-left
方法
另外一种让两个block
排列到一起的方法是对左侧盒子使用position: absolute
的绝对定位。这样,右侧盒子也能无视掉它。
.wrapper-absolute .left {
position: absolute;
}
.wrapper-absolute .right {
margin-left: 150px;
}
缺点:
-
使用了绝对定位,若是用在某个div中,需要更改父容器的
position
。 -
没有清除浮动的方法,若左侧盒子高于右侧盒子,就会超出父容器的高度。因此只能通过设置父容器的
min-height
来放置这种情况。
使用float+BFC
方法
上面的方法都需要通过左侧盒子的宽度,计算某个值,下面三种方法都是不需要计算的。只需要设置两个盒子之间的间隔。
.wrapper-float-bfc {
overflow: auto;
}
.wrapper-float-bfc .left {
float: left;
margin-right: 20px;
}
.wrapper-float-bfc .right {
margin-left: 0;
overflow: auto;
}
这个方案同样是利用了左侧浮动,但是右侧盒子通过overflow: auto;
形成了BFC,因此右侧盒子不会与浮动的元素重叠。
这种情况下,只需要为左侧的浮动盒子设置margin-right
,就可以实现两个盒子的距离了。而右侧盒子是block
级别的,所以宽度能实现自适应。
缺点:
-
父元素需要清除浮动
flex
方案
grid
方案
双飞翼布局 & 圣杯布局
双飞翼布局和圣杯布局目的都是左右两栏固定宽度,中间部分自适应。
【圣杯布局】
在这里,实现了左(200px) 右(220px) 宽度固定,中间自适应,container部分高度保持一致。
稍微说明一下:
html代码中 middle部分首先要放在container的最前部分。然后是left,right
1.将三者都 float:left , 再加上一个position:relative (因为相对定位后面会用到)
2.middle部分 width:100%占满
3.此时middle占满了,所以要把left拉到最左边,使用margin-left:-100%
4.这时left拉回来了,但会覆盖middle内容的左端,要把middle内容拉出来,所以在外围container加上 padding:0 220px 0 200px
5.middle内容拉回来了,但left也跟着过来了,所以要还原,就对left使用相对定位 left:-200px 同理,right也要相对定位还原 right:-220px
6.到这里大概就自适应好了。如果想container高度保持一致可以给left middle right都加上min-height:130px
当然,为了保证窗口不能缩太小无法展示左右,可以给body加上 min-width。
【双飞翼布局】
双飞翼布局,始于淘宝UED
如果把三栏布局比作一只大鸟,可以把main看成是鸟的身体,sub和extra则是鸟的翅膀。这个布局的实现思路是,先把最重要的身体部分放好,然后再将翅膀移动到适当的地方.
恩,这里有一只鸟~
左翅sub有200px,右翅extra..220px.. 身体main自适应未知
1.html代码中,main要放最前边,sub extra
2.将main sub extra 都float:left
3.将main占满 width:100%
4.此时main占满了,所以要把sub拉到最左边,使用margin-left:-100% 同理 extra使用margin-left:-220px
5.main内容被覆盖了,除了使用外围的padding,还可以考虑使用margin。给main增加一个内层div-- main-inner, 然后margin:0 220px 0 200px
6.main正确展示