CSS3 弹性布局 flex(给父盒子挂flex帅,让子元素排布练阵)
1.摘自 http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
布局的传统解决方案,基于盒状模型,依赖
display
属性 +position
属性 +float
属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。2009年,W3C 提出了一种新的方案----Flex 布局,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能,时至今日 flex已经成为主流布局方式 , 尤其在移动端 小程序等方面表现出色。
1.Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。
任何一个容器都可以指定为 Flex 布局, 父flex对子内部即块级和行内元素都生效的。
2.PS:父盒子设为 Flex 布局以后,内部的子元素的float、clear和vertical-align属性将失效。
因为有justify-content 和 aglin-items 解决了行内文本/img的水平垂直方式
3.给父元素设置了 display:flex 则相当于父变为块级display:block。 并且内部子元素的效果看起来是一行的像浮动一样的,但是可以设置flex-direction:column 变回在一列上一行显示的.
4.display: flex 是设置在 父元素上面的,但是对子元素生效的,父盒子设置flex之后,他里面的全部子元素,就都会变成 弹性block盒子了
5.float浮动 VS display:flex ? 区别是给当前盒子使用float是当前盒子生效去浮动到父级盒子上,而当前盒子使用flex是让内部子元素一行浮动.
5.PS:注意好flex盒子有些display/dir/justify/aglin属性只能设置在父盒子上然后对子盒子生效 ,有些grow/shrink/baise/flex属性只能给子盒子上对自己生效,不能混哦
6.要千万注意,子盒子的宽度或者高度在没有设置情况下,是不是去借用父盒子的宽度(被儿子p继承)或高度(由子内容撑大),此时给父盒子开flex ,则ju或者ag会出现失效情况,因为子宽或者高都占满了父,哪有空间给你排列了?
7.使用flex排序定位比如flex-center会调整改变position定位元素的起始位置,但是如果加上top和left偏移属性生效后,
则还是一样从定位父级的左上角开始,(即一旦给了top和left一起给则flex排序定位会失效,只给top或者left一边则另一边会保持flex的排序的定位) ,
这适合盒子在超级大定位父级盒子中定位,则可以使用flex先居中定位,然后单独使用top/left去改变另一侧. (俗称flex+absolute配合一起定位, HTML项目有这个用法去看)
PS:如果没加flex 和flex-center, 直接absolute+left+top箭头是 则定位父级左上角开始定位也是可以的.
PS:但如果盒子的定位父级 必须同时 是去使用flex的结构父级的话,否则不会影响的.还是从定位父级四个角开始(细品)
8.flex 要注意爷爷 > 父亲 > 儿子 关系层级的使用,会很乱的.
①比如div蓝色爷爷盒子使用flex 则三个红p爸爸盒子一定挤自己宽度,然后一行显示,因此加column则一列分行去显示
(column一列显示特别注意:主轴justify-content变为垂直方向对齐了不是水平了),分行保证p设置好宽度不被挤,或者p宽度是继承父级div的整行宽度
②然后,三个 红p爸爸盒子再次使用flex, 此时是对p内的文本生效的,对,没听错,flex对子内部span/i行内元素也生效,文本水平(justify) 和 垂直(aglin)居中对齐都让文本生效了(flex很神奇).
③注意:文字对齐得去每个p的flex设置ju和ag,不能去爷爷div那里,这样是不生效的,越级了.千万注意flex使用范围只能是当前设置flex的元素的子元素.(div蓝盒子只能管p红盒子的水平垂直排列方式, p红盒子才能管内部span盒子的东西 )
④案例1:如下图,给蓝盒子设置flex + column后,然后问蓝盒子的ju和ag是管谁的,
答:1.先清楚:加columnn换方向之后ju管垂直了,而ag管水平了.
2.是管红p盒子的水平和垂直. 但注意:p水平宽度如果继承父蓝盒子的宽度,则水平方向对齐即ag是失效的,都占满宽度了,只能是ju垂直排列是生效的
9. 如何解决红盒子内部两个span文字如果一上一下不对齐 ,(是一行内红色图标字号大了会带着字往下走一点不对齐.)
解决:因此是要在p盒子设置 ag 垂直对齐让文字统一在Y高度上中心,即在p盒子内垂直居中, (千万不能去了蓝爷爷盒子设置,这样只对p多个子红盒子之间垂直排列生效, 不对孙子跨级span文字生效)
PS1: 这两张图的文字ju水平对齐方式,已经设置为两端space-between了,然后再给第二个p即location设置aglin-center就Y上垂直也对齐了了,就不会一上一下了,一上一下是字体图标压宽总高度,本来正常其实是不会一上一下,因为一行的字体肯定都是一样宽高的嘛,就像下面的价格和付款人数那一行一样,正常都Y对齐了不用设置aglin-center的, 有两个span最多设置justify-content而已)
PS2: 其实看完上面你会发现, 所有mask即div下面的所有p宽度在没有设置的情况下,给mask加flex和justify-content是没用的因为p宽度继承了mask的宽度,占满整个mask宽度,因此p怎么可能在mask水平排列呢?
此时这里恰巧是flex-direction:column改变为垂直排列,这样justify-content就是针对垂直方向的,即高度按照内容来的,不会挤满,就可以排列了space-between排列mask垂直方向上的p了.
4.第一个div的flex 的居中,只能管a,让整个a子元素盒子居中在div,但管不了文字和图片在a盒子内(flex下a变盒子)水平居中,因此左右不对齐的. (为什么会水平不对齐,其实和上面一个道理,图片把整个a盒子的内容撑大了,则会默认用子最宽宽度作为父自身宽度,因此a内部还要再来一次水平居中,这里恰巧是column因此,ju是让图文在a垂直方向居中对齐,但是是失效的,因为图文高度这里是和a盒子高度一样的,没有高度给你去排列了,因此这里生效的是ag充当水平方向的居中,类似text-aglin)
因此要给a也加flex,和居中,这样a就能管两个子元素span和i的在a内的垂直和水平对齐方式了 . 一层套一层的居中,达到最终的层层居中(不能像定位一样越可以级移动居中)… *[当然这里可以用text-algin:center]
总结: ①爷爷设置flex ,说明要管父亲盒子的排列方式, 父亲设置flex说明要管儿子文本的排列方式
②子文本在父盒子居中了,然后父盒子又再次在爷爷盒子居中,文本才会最终再爷爷盒子内居中,flex不能跨级
即Flex设置在父盒子,只能管到和影响到子盒子,不能继承到孙子那里去,因此要分关系结构层分别使用flex,两次使用flex,让a蓝色盒子在con-item黄盒子内居中,绿盒子(sapn+i)又在a蓝盒子内居中.
2.Flex基础概念
①采用 Flex 布局的元素,称为 Flex 容器(flex container),简称"容器"。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称"项目"。
②给父元素设置display:flex,相当于给内部子元素设置了浮动一行显示,但是不会脱标的浮动(不会高度塌陷).
①容器默认存在两根轴:X水平的主轴(main axis)和 Y垂直的交叉轴(cross axis)。
(看到主轴就想X水平方向的排列东西 , 看到交叉轴就想Y垂直方向的排列东西)
②主轴的开始位置(与边框的交叉点)叫做main start
,结束位置叫做main end
;
③交叉轴的开始位置叫做cross start
,结束位置叫做cross end
。item子项目默认沿主轴排列。单个项目占据的X主轴空间叫做
main size
,占据的交叉轴Y空间叫做cross size
。
3.容器属性
一共有6种css属性用于调整flex 布局
flex-direction (设置X主轴的排列方向)
flex-wrap
flex-flow
justify-content (设置X主轴的排列方式)
align-items
align-content
3.1flex-direction
flex-direction
属性决定主轴的方向(即项目的排列方向)默认横向 row。
.box { flex-direction: row | row-reverse | column | column-reverse; } row(默认值):主轴为X水平方向,起点在左端。 [让内部子元素实现一行显示] row-reverse(X倒序):主轴为水平方向,起点在右端。 [类似右浮动] column:主轴为Y垂直方向,起点在上沿。 [让内部子元素分行显示,即表现为一列] column-reverse(Y倒序):主轴为垂直方向,起点在下沿。 [倒序的正常文档流] 前提:column和row设置都是给父然后针对内部子元素的. 通常是父column子row : 通常是父row子column :
3.2flex-wrap
①因为默认情况下,项目会都排在一条线(又称"轴线/行")上 , 跟boxing-size一样,会挤内容宽度.
②flex-wrap`属性定义,如果一条轴线排不下,如何换行。
.box{ flex-wrap: nowrap(默认) | wrap(最多使用) | wrap-reverse; }
③它的取值属性。
(1)nowrap
(默认):不换行(但会挤内容宽度)。
(2)wrap
:换行,第一行在上方(但是会尽量智能放一行上,就放一行上的)。
(3)wrap-reverse
:换行,第一行在下方。
3.3 flex-flow(前面dir和wrap的复合写法,鸡肋)
flex-flow
属性是flex-direction
属性和flex-wrap
属性的简写形式,默认值为row nowrap
。
.box { flex-flow: <flex-direction> || <flex-wrap>; }
3.4 justify-content属性(设置子元素的X轴水平排列方式,单行和多行一样)
justify-content
属性定义了项目在主轴上的对齐方式。
.box { justify-content: flex-start(默认) | flex-end | center | space-between | space-around | space-evenly; }
它可能取6个值,具体对齐方式与轴的方向有关。下面假设主轴为从左到右。
flex-start
(默认值):左对齐
flex-end
:右对齐
center
: 居中
space-between
(用最多):两端对齐,多余宽度让项目之间变为均分的间隔。
space-around
:每个项目两侧的间隔相等。(类似给每个盒子加左右的margin,因此相邻盒子margin会叠加)
所以,使用space-around项目之间的间隔比项目与边框的间隔大一倍。
space-evenly(PS:兼容不好):
彻彻底底让每个间隙距离相等. (不叠加左右外边距)
(兼容处理:用 space-between配合before+after使用)1.(
理解space-around
和`space-evenly的区别!!!)2.如何兼容处理达到`space-evenly效果: space-between + before/after
在使用该属性的盒子加个前后影分身即可;(前提是:得是单行才能这么使用)原理:因为space-between是按盒子人头来算间距的,因此很精妙,设置一个没有宽高的前后影分身盒子(记得设置为block,因为影分身默认是行内inline元素)去占位,这样就可以白嫖分间隙给你了,
3.但是注意这不是万能的,如果遇到多行flex-wrap,换行去显示的话,则上面方法错误的会让ul前后 ,只能通过给父容器加padding,类似内部凹陷,让整体扩大,如果不想扩大父盒子的总宽则加box-sizing即可
解决方法:
3.5 align-items属性(设置在单行上子元素Y轴垂直排列方式)
align-items
属性定义项目在交叉轴上,如何对齐。
PS:但其实这个很鸡肋的,因为父高度一般都不设置的,父高度不设置因此无法用该属性.都是给内部每个盒子加 margin-bottom: 8px; ,让下平均去垂直分配间隙的,这也是flex垂直排列的一个痛处来的,没有具体高度就不能分配的.(而宽度一定可以,宽度一定会给好的)
.box { align-items: flex-start | flex-end | center | baseline | stretch; }
它可能取5个值。具体的对齐方式与交叉轴的方向有关,下面假设交叉轴从上到下。
stretch
(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。flex-start
:交叉轴的起点对齐。flex-end
:交叉轴的终点对齐。center
:交叉轴的中点对齐。baseline
: 项目的第一行文字的基线对齐。
PS:aglin-item:center和align-content:center 的区别?
align-content 跟上面的 align-items 的区别就是:一个是操作单行的,一个是操作多行的。 参数都是一样的设置, 除了多了两个 space-betwwen ,space-around
①aglin-item:center
PS:正常的时候去使用align-items单行,是把整个父容器盒子高度看成一整行的,然后在这一整行上垂直居中
②align-content:center (切记 ! 多行时才会生效哦,多行当成整体,就像侧着的 justify-content)
③:如果有多行但使用这个单行aglin-item:center的话,则会变成类似line-height行高 , 即多行拆分成一行一行来各自排列,不是整体,即在每一行的垂直方式,如下图在分为两行即在多行下使用单行垂直居中方式aglin-item,则代表每一行垂直居中了 )
3.6 align-content属性(在设置了wrap多行基础上才有效的,设置在多行上的垂直对齐方式)
1.PS:设置direction-felx:column之后的分行,此时使用align-content的作用不会生效的,必须是wrap强制换行才有效,分行之后还是用aglin-items管各行
2.这个align-content属性一般也都是给内部每个子盒子加 margin-bottom: 具体的px;代替align-content的间隙 ,这也是flex垂直排列的一个痛处来的,没有具体高度就不能分配的.(而宽度一定可以,宽度一定会给好的)**
3.align-content
属性定义了多根轴线的对齐方式。
如果项目只有一根轴线,该属性不起作用失效。