前段时间在刷网页的时候偶然看到一个面试题,大体是这么说的,定义一个父元素和子元素,其宽高都不确定(也就是是动态变化的),如何实现子元素在父元素中上下左右居中。
好家伙,我琢磨了一下,不给宽高是个坑啊,简单的html+css很难实现,我随即想到了js,js可以通过clientWidth和clientHeight获取元素宽高啊,我随手写了一段代码:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> .parent{ width: 600px; height: 300px; border: 1px solid red; } .child{ width: 200px; height: 200px; border: 2px solid greenyellow; position: absolute; } </style> </head> <body> <div class="parent"> <div class="child"> </div> </div> <script type="text/javascript"> window.onload=function(){ var parent=document.getElementsByClassName("parent")[0]; var pWidth=parent.clientWidth; var pHeight=parent.clientHeight; var child=document.getElementsByClassName("child")[0]; var cWidth=child.clientWidth; var cHeight=child.clientHeight; child.style.left=pWidth/2 - cWidth/2 +"px"; child.style.top=pHeight/2 - cHeight/2 +"px"; } </script> </body> </html>为了效果明显,我给父元素和子元素都随机添加了宽高,当然我们随机改变宽高,不需要再改动其他代码,居中依然会实现。
那么,一个小小的居中效果需要这么繁琐的实现,是不是太不尽人意了,对,W3C替我们想到了,css3提供了flex布局模式,这类问题可迎刃而解
flex布局是什么呢?Flex是Flexible Box的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。
至于定义在这不深挖,主要看技术实现
首先引入flex,很方便,我们只需要display:flex,这里会牵扯到兼容性问题,也不深究,文档网上有
有张图把flex描述地挺直观的,拿来分享一下
注:flex容器的所有子元素自动成为容器成员,称为Flex项目(flex item),简称"项目"。
容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做main start
,结束位置叫做main end
;交叉轴的开始位置叫做cross start
,结束位置叫做cross end
。
容器的特性
容器共可以设置六个属性
- flex-direction
- flex-wrap
- flex-flow
- justify-content
- align-items
- align-content
一.flex-direction
这个是确定主轴方向的(即项目的排列方向)
它可以设置四个值
- row(默认值):主轴为水平方向,项目自左向右排列
- row-reverse:主轴为水平方向,起点在右端,也就是项目自右向左排列
-
column:主轴为垂直方向,项目自上而下排列
- column-reverse:主轴为垂直方向,项目自下而上排列
二.flex-wrap
定义如果一条轴线排不下,如何换行
它可以设置三个值
- nowrap(默认值):不换行
- wrap:换行,第一行在上方
- wrap-reverse :换行,第一行在下方
三.flex-flow
flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。
四.justify-content
定义了项目在主轴上的对齐方式
它可能取五个值
flex-start
(默认值):左对齐flex-end
:右对齐-
center
: 居中
space-between
:两端对齐,项目之间的间隔都相等。space-around
:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍
五.align-items属性
该属性定义项目在交叉轴上如何对齐。也就是默认的竖轴垂直方向上的对齐方式
它可以取五个值
flex-start
:交叉轴的起点对齐。flex-end
:交叉轴的终点对齐。center
:交叉轴的中点对齐。baseline
: 项目的第一行文字的基线对齐。stretch
(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
六.align-content
该属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
它可以有六个值
-
flex-start
:与交叉轴的起点对齐。 flex-end
:与交叉轴的终点对齐。center
:与交叉轴的中点对齐。space-between
:与交叉轴两端对齐,轴线之间的间隔平均分布。space-around
:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。stretch
(默认值):轴线占满整个交叉轴。
好了,啰嗦了这么多,我们该解决问题了,这里我尝试一下 align-items:center来实现子元素垂直居中
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> .parent{ width: 600px; height: 300px; border: 1px solid red; display: flex; align-items: center; } .child{ margin: 0 auto; width: 200px; height: 200px; border: 2px solid greenyellow; background: url(img/timg.jpg) no-repeat 45% 35%; } </style> </head> <body> <div class="parent"> <div class="child"> </div> </div> </script> </body> </html>
结果显然是喜人的,垂直居中实现了
好了,关于项目本身所带有的属性在这就不念经了,推荐一篇博文——点击打开链接