flex的全称是FlexibleBox模型。顾名思义就是柔性盒,不过一般都叫柔性盒。PC和手机上的所有现代浏览器都支持它,所以不用担心它的兼容性。有了这东西,妈妈再也不用为我们的布局操心了。我先简单介绍一下。使用flex布局,需要给一个容器元素设置display:flex,使其成为flex容器,然后它的所有直接子元素都变成flex子元素。flex中有两个轴。它们被称为主轴和交叉轴,它们相互垂直。默认情况下,主轴是水平的。默认情况下,flex子元素沿主轴排列。您可以控制主轴上的flex子元素的扩展和收缩。设置了flex容器,为flex子元素设置了一个。本文介绍了一些典型的场景实现,也顺便解释了一些属性。当然更详细的内容你可以阅读MDN上的教程。单列布局单列布局是最简单的布局,从上到下排列,如图:可以用三个div分别代表head、content和tail,然后设置外层容器,也就是body作为一个flex容器,因为flex默认的主轴是水平的,我们需要将其设置为垂直,然后将元素设置为以横轴为中心:当然,更常见的情况是内容高度为不确定,所以我们往往希望底部内容在内容高度小于一屏时紧挨着底部,超过一屏时紧跟在末尾。这首先要求容器元素有固定的高度,否则底从何而来?我们可以把html和body的高度都设置成100%,然后去掉content元素Height的设置,给它添加一个带高度的子元素:接下来需要使用flex-grow属性,即flex子元素上的一个属性,用于控制flex子元素在容器中还有剩余空间时如何展开。默认值为0,即不展开,子元素将以默认大小显示。这个所谓的默认大小有几种情况:1.如果子元素的另一个属性flex-basis设置了一个特定的值,不是auto,那么不管这个元素有没有特定的大小,都会显示作为此属性定义的大小;2.如果子元素的flex-basis值为auto(默认值),那么如果该元素有特定的size设置,那么会显示为设置的size;3。否则,取决于元素内容的max-content大小;当flex-grow设置为正数时,每个子元素会根据设置的份数按比例分配剩余的可用空间,例如剩余空间为90px,如果三个子元素的属性值设置为1,那么每个元素都会在原来的尺寸基础上增加90/3=30px。根据上面的原则,我们只需要将content元素的flex-grow属性设置为1,其他都为0,这样剩余的空间就交给content元素:这样bottom就可以紧挨着内容不足时底边,但是当内容太多,多一屏时:可以看到头尾都没有了,这是因为flex-shrink,这也是flex子元素上的一个属性,用于控制当子元素的大小之和超过容器时如何收缩元素,默认值为1,即按比例减去要收缩的空间。理论上是这样的,但实际上并没有这么简单。接下来简单测试一下:容器元素body高800px,顶部、中部、底部高度分别为100+1000+100=1200px。按照1:1:1的flex-shrink计算,总重量为1*100+1*1000+1*100=1200。子元素的总高度超过容器的400px,即额外减去各自高度的比例为:(400*1*100)/1200=33.33px(400*1*1000)/1200=333.33px(400*1*100)/1200=33.33px,即分别减去以上数值。相减后,理论高度变成了66.67px、666.67.67px、66.67px,但实际上:可以看到head和tail都变成了0,content高度没有变化,为什么?我们在上面提到了max-content。同样,这对应于min-content的概念。虽然正常情况下应该变成我们计算出来的大小,但是缩小到元素内容的min-content后就不会改变了。小,content元素有一个高度为1000的子元素,这个高度就是它的min-content,所以不会收缩,一个元素比容器元素高,加上head和tail没有内容,所以虽然理论上它们不是0,但是为了更好的显示效果,浏览器直接将它们缩小为0,我们可以在头部和尾部加一点文字,文字的高度会变成它们的min-content,它们的高度不会变成0:所以这就是说不要去想精确的计算,交给浏览器,浏览器会给你最好的渲染方式。那么解决头尾不消失的问题就很简单了。你可以给它们添加一个固定高度的子元素,但是最简单的方法是将它们的flex-shrink设置为0,即不收缩:这就是我们实现需求的方式。如图,classicnavigationbar是一个经典的网站导航栏布局。左边是logo和导航,右边是用户信息。如果你不使用flex,你可以使用float。上图中使用浮动是可以的,但是如果右边有两个块,那么右边的浮动元素的显示顺序和书写顺序肯定是不一致的,或者换个元素包起来。使用flex就没有这种麻烦。这个场景可以用一个容器把左边的logo和navigation包裹起来,然后设置justify-content:space-between来实现,但是有一个小技巧可以避免这个包裹元素,就是使用auto的值margin,回想一下我们以前水平居中是怎么做到的?是这样的吗?margin:0auto,margin-left和margin-right的默认值为0,如果设置为auto,会根据剩余的可用空间来计算,这也是为什么可以水平居中的原因,因为left和right我们都是要多少,就只能平分了。对于这个例子,我们只为用户名flex子元素设置了margin-left:auto,那么剩下的空间全部给它,相当于把用户块往右挤已经:交错交叉显示有时为了顺序为避免排版过于单调,即使一个列表是同一类型的数据,也会在显示屏上显示上述交错的十字样式。这可以通过使用flex轻松完成。设置flex-directionfor2nrows:row-reverse可以让偶数行的主轴方向由默认的从左到右变为从右到左:另外还可以使用order属性,允许flex子元素按照order的值排序显示。我们默认左边可以设置为2,右边可以设置为3,然后在偶数行可以设置右边为1,这样自然会往前走:网格布局这个grid不是网格布局,虽然grid列表用grid是最好的,但是本文的主角是flex。假设我们要实现如下列表:上面的列表不擅长flex,因为它需要间距,所以我们不能简单的把子元素的宽度设置为25%。不然加上外边距,一行肯定显示不少于四,那你可能会想,那我的宽度应该小一点,比如设置为20%,然后允许展开,也就是flex-grow:1,没关系,你把子元素减去width和margin后剩下的空间还给子元素了吗?试试看:可以看到一切正常,但是最后一行被拉了,因为只有一个元素,并且设置了允许扩展整行都拉满了,这样的效果显然不是我们想要的。其实我们可以使用内边距来做间距,设置子元素的box-sizing:border-box,让内边距包含在宽度中,这样我们就可以放心的设置子元素的宽度了子元素到25%,当然这样做的缺点是你必须在里面嵌套另一个元素作为实际的内容容器。HolyGrailLayout所谓HolyGrail布局就是如上图,头部和尾部的高度是固定的,宽度是满的,中间的内容分为三列,两边的宽度是固定的,height是满的,中间的内容随着浏览器的宽度变化。上面提到的【单列布局】的中间部分就变成了三列,实现上也没有什么特别之处。在【单列布局】的基础上,在内容中添加三个子元素,设置两边宽度,不允许收缩,中间只允许扩展:垂直居中。不知道你当初为什么用flex。不管怎样,作者的目标是垂直居中。使用起来太简单了。flex是两步,一是将父元素做成弹性盒子,二是设置横轴的元素排列居中;如果还需要水平居中,那就把容器元素的主轴排列方式设置为justify-content:center,现在我连文字居中都用flex了,无情的舍弃了text-align和line-height。高度自动对齐有时同一列中的元素为了美观而希望它们的高度相同。如果内容是固定的,可以直接写高度,但是如果是可变的,就不能写死:这个场景根本不需要使用flex来设置额外的属性,只需要设置display:flex为container元素,因为flex容器有一个属性align-items,用来设置flex子元素在横轴上如何对齐。默认值为stretch,即如果flex子元素没有设置高度的话,它会占据整个容器的高度,因为我们还没有给容器设置高度,所以容器的高度是所有flex子元素中最大的高度。总结本文以题主党的名义总结了一些使用flex的常见布局的实现。要想灵活使用flex,还是需要了解它的一些属性的含义。另外,你还需要知道flex的边界在哪里,它不擅长什么。本文的总结难免不完整,或者可能有更好的实现。欢迎讨论。
