稀土掘金 稀土掘金

flex 布局的浏览器兼容性方案

前言

flex 布局在目前前端开发中使用到的概率还是蛮大的,尽管它从诞生到现在已经经历了 N 年了,但是从个人的工作圈子来看,有很多人其实对 flex 布局的理解还是很表面,比如一味地使用 flex: 1 或者 flex: auto 等,导致一旦出现一些样式问题或者浏览器兼容问题,马上就无法处理了。

因此,个人从 flex 布局基础知识和浏览器兼容性两个方面,结合个人工作经验,整理了一篇文章,希望对大家有帮助,如有阐述有误之处,还望不吝指教!

文章大体分为两个部分,第一块是 flex 的基础知识,包括布局特性、属性特征等,相对偏理论些。第二块是 flex 的浏览器兼容问题总结,以及 flex 使用建议,这源于个人工作场景中实际碰到的问题,经尝试解决后的总结,偏实际应用一点。

如果对 flex 布局原理比较了解,但遇到浏览器兼容问题的同学来说,可以直接看第二块内容。

flex 布局 - 一维布局

flexbox 是一种一维的布局,因为一个 flexbox 一次只能处理一个维度上的元素布局,一行或者一列

flex 布局 - 容器属性

display: flex vs display: inline-flex

相同点

  • 对于容器内部的子元素而言,没有任何区别

差异

  • 对于容器本身而言,flex 表现为 块级元素;inline-flex 表现为 块级内联元素
    • 因此未给容器设置宽度时,flex 容器默认宽度为100%(一行占满);inline-flex 默认宽度会根据子元素的宽度去自适应

图片.png

flex-direction

轴线 - 主轴 & 交叉轴

  • 主轴由 flex-direction 定义,可取 row(横向主轴)、column(纵向主轴)等值。
  • 交叉轴则为与主轴垂直的轴线。
  • flexbox 的特性是沿着主轴或者交叉轴对齐之中的元素。

图片.png
图片.png

起始线 & 终止线

起始线、终止线用于描述 flexbox 子元素的书写(排列)方向。

当主轴为 row(横向主轴)时:

  • 书写英文时,主轴起始线为左边;书写阿拉伯文时,主轴起始线为右边。
  • 交叉轴起始线是 flexbox 的顶部,终止线是底部,因为两种语言都是水平书写模式。

图片.png
图片.png
当主轴为 column(纵向主轴)时:

  • 主轴起始线为 flexbox 的顶部,终止线为 flexbox 的底部,因为两种语言都是水平书写模式。
  • 书写英文时,交叉轴起始线为左边;书写阿拉伯文时,交叉轴起始线为右边。

属性值与轴线、起始终止线的关系

假定以 row 为基准,那么取其他属性时的线位变化如下:

  • row-reverse:主轴 & 交叉轴不变;起始线 & 终止线 改变
    • 主轴的起始线、终止线互换;交叉轴的起始线、终止线不变
  • column:主轴 & 交叉轴互换;起始线 & 终止线 改变
    • 主轴的起始终止线,与交叉轴的起始终止线互换
  • column-reverse:主轴 & 交叉轴互换;起始线 & 终止线 改变
    • 主轴的起始终止线,与交叉轴的起始终止线互换
    • 交叉轴的起始线、终止线互换;主轴的起始线、终止线不变

justify-content

使子元素在主轴上对齐

  • 初始值是 flex-start,子元素从容器的起始线开始排列。
  • flex-end,元素从容器终止线开始排列
  • center,居中排列,每个元素紧邻
  • space-between,占满容器,并且元素之间间隔相等
  • space-around,占满容器,并且每个元素的左右空间相等

图片.png

align-items

使子元素在交叉轴上对齐

  • 初始值是 stretch
    • 未定义容器高度,容器会被拉伸到最高元素的高度;
    • 定义了容器高度,元素会被拉伸(收缩)到容器高度。
  • flex-start,按容器的起始线对齐
  • flex-end,按容器的终止线对齐
  • center,居中对齐

图片.png

align-content

使子元素在交叉轴方向对齐,但为多行对齐

  • 默认值是 stretch,剩余空间被所有行平分,以扩大它们的交叉轴尺寸
  • flex-start,所有行从容器的起始线排列
  • flex-end,所有行从容器终止线开始排列
  • center,所有行在容器中间,紧凑排列
  • space-between,所有行占满容器,并且每行之间间隔相等
  • space-around,所有行占满容器,并且每行的上下空间相等

图片.png

flex-wrap

换行方式

  • 默认 nowrap,不换行
  • wrap,换行
  • wrap-reverse,换行反向排列

图片.png

flex-flow

flex-directionflex-wrap 的合并写法

flex 布局 - 子元素属性

子元素默认样式

  • flex-direction: row,元素排列为一行,并从主轴的起始线开始
  • flex: 0 1 auto,元素不会在主轴方向拉伸,但会随可用空间会缩小
  • flex-wrap: nowrap,如果有太多元素超出容器,它们会溢出而不会换行
  • 如果一些元素比其他元素高,那么元素会沿交叉轴被拉伸来填满它的大小

图片.png

flex-basis

元素的初始(基准)空间大小

  • 默认值是 auto
    • 元素设置了宽度,flex-basis 为设置的宽度
    • 元素未设置宽度,flex-basis 为元素内容的尺寸
  • flex-basis 属性优先于 width 属性;
  • 设为 0 ,则子元素的大小不在空间分配计算的考虑之内

flex-grow

元素沿主轴方向的扩张尺寸,会占据主轴上的可用空间

  • 按比例分配空间(默认为 0 ),扩张值为 flex-basis 基准乘以 flex-grow 扩张比例
    • 设置一样的值,则平分可用空间
    • 设置不同的值,按比例平分可用空间

下图为不同 flex-basis 的情况下,flex-grow 均设为 1 的场景:
图片.png

flex-shrink

元素沿主轴方向的收缩尺寸,只有在子元素总和超出主轴才会生效

  • 按比例分配空间(默认为 1 ),收缩值为 flex-basis 基准乘以 flex-shrink 收缩比例
  • 随着盒子越来越小,小的子元素最终会以 min-content 的大小进行铺设,后续空间会一直从大的子元素中移除
    • 所谓 min-content ,即当前容器内部最小的不可断行元素的宽度
      • 下图 largeSizeContentWithoutWrap 是连续不可断行的,所以无法再压缩空间
      • 下图 middle-size-content-width-split-code 可以以横杠 - 断行,所以可以换行以压缩空间
      • 下图 content-content-content-content-content-content 已经被断行到不可再断行的宽度,因此无法再继续换行来压缩空间

下图为不同 flex-basis 的情况下,flex-shrink 均设为 1 的场景:
图片.png

order

项目的排列顺序

  • 数值越小,排列越靠前,默认为 0

align-self

允许单个项目有与其他项目不一样的对齐方式

  • 可覆盖 align-items 属性,默认值为 auto
  • 表示继承父元素的 align-items 属性
    • 如果没有父元素,则等同于stretch

几个 flex 样式的简写

flex: initial

相当于 flex: 0 1 auto

flex: auto

相当于 flex: 1 1 auto

flex: none

相当于 flex: 0 0 auto

flex: 1

相当于 flex: 1 1 0

flex: auto 与 flex: 1 的区别

flex: 1 1 auto

  • 在各元素初始宽度基础上,平均分配可用空间
  • 各元素宽度不相等,初始宽度大的分配后宽度也大

flex: 1 1 0

  • 在各元素 0 宽度的基础上,平均分配可用空间
  • 各元素宽度相等

图片.png

flex 布局 - 浏览器兼容性

浏览器兼容性概览

  • 红色部分为不支持 flex 规范
  • 黄色部分为只支持老的 09 版 flex 规范(display: box; )
  • 绿色部分为完全支持新的 12 版 flex 规范(display: flex; )

图片.png

flex 规范,09 版 vs 12 版

图片.png
图片.png
图片.png

支持少数低版本浏览器的方案

  • 联合使用支持 09 版和 12 版的 flex 布局
.container {
	display: box; 
	display: flex; 
}

注意
  • 浏览器兼容语法(-webkit- 等)可以通过postcss 等工具实现
  • 但 09 版 flex 不支持很多特性

chrome 49 的兼容性问题

问题描述

父元素 flex: 1 ,子元素 height: 100% ,因内容较少无法填充满父元素
图片.png

原因

父元素未设置 height,故子元素获取不到父元素的 height

解决方案一

通过父元素 absolute,子元素 relative,这样子元素的高度就会根据父元素的高度进行计算

解释

规范中有提到,如果包含块的高度没有显式地指定(高度由内容决定),并且不是绝对定位元素,则计算值为 auto,高度和百分比值是没办法进行计算的! auto * 100/100 = NaN

缺陷

子元素 absolute 带来的影响,比如需要再设置 width: 100%

解决方案二

子元素不使用 height: 100%,而使用 flex-grow 来占满空间

解决方案三

父元素不使用 flex: 1,而使用 display: flex; + height: 100%;

解释

应用于 display: flex 的元素,使其成为 flex 容器。
这会自动设置 align-items: stretch,会告诉 child(.item)扩展父级的完整高度。
图片.png

总结

Chrome49 浏览器针对子元素设置 height: 100% 后因内容较少无法填充满父元素的情况,
建议父元素使用 display: flex; + height: 100%;

chrome 79 以上的兼容性问题

问题描述

当父元素设置 flex: 1 填充满容器,子元素设置 height: 100% 后,子元素内容过多会超出父元素
图片.png

解决方案

对于一个设置了 flex: 1 的元素,再对其设置 min-height:0,保证内容不超出外层容器

解释

父元素设置 min-height: 0 相当于告诉子元素父元素 height > 0,子元素可以由此间接地拿到父元素的高度,然后设置 height: 100% 保持父元素同样的高度,避免溢出
图片.png

注意

要兼容 chrome49 的话还需使用 display: flex; + height: 100%; 替换 flex: 1

总结

Chrome79 以上浏览器,针对子元素设置 height: 100% 因内容过多超出父元素的情况,建议父元素使用 min-height: 0;(Chrome 79) + display: flex; + height: 100%; (Chrome 49)

chrome 49 与 chrome 79 以上的另一个差异点

差异描述

  • flexbox 一个子元素设置了 flex,另一个子元素设置了很高的高度
  • 当 flexbox 高度不足以容纳两者时,两者高度都会受到压缩
  • 但在 chrome49 下设置了 flex 的子元素,会被压缩到连其子元素都无法完整展示
  • 而 chrome79 下设置了 flex 的子元素,则会尽可能保留其子元素的展示

chrome 49
图片.png
chrome 79 以上
图片.png

解决方案

若要保持设置了 flex 的子元素的完整展示,最好设置 flex 的同时设置 flex-shrink: 0;

QQ 浏览器 10 下 flex: auto 不生效的兼容问题

问题描述

QQ 浏览器 10.6 chromium 70,父元素 flex: auto,子元素 height: 100% 的情况下,无法撑开或收缩子元素
图片.png

解决方案

需要将 flex: auto 改成 flex: 1 而且要带上 min-height: 0

flex 布局使用建议

针对横向布局

按照一般写法即可

.container {
	display: flex;
	flex-direction: row;
}

针对纵向布局

需要增加兼容 chrome49 以及 chrome79 以上的样式

.container {
	display: flex;
	flex-direction: column;
	height: 100%;
	min-height: 0;
}

针对子元素

视情况灵活使用 flex-basisflex-growflex-shrink 的组合,而不是一味地全部使用 flex:1 或者 flex: auto

最后

附上案例项目的 git 地址:

github.com/hezhikai/bl… (案例可能写的不是很好-0-)

重申几点

  • 上面 flex 布局的基础知识是基于自己看过的很多文档归纳的,可能有些描述摘录了其他地方的文章的用词或片段,如有侵权请告知,我会删掉。
    • 因为整理的时候查的资料比较多,现在很多地方已经想不起来参考了哪里的文章,所以不大好去附加参考资料,请见谅。
  • 后面 flex 布局的兼容性问题,更多的是基于工作场景遇到并解决后整理的。当然也有查各方面资料(虽说目前网上这块的资料不够详尽),但是也有个人经验的总结在里面。
    • 因此后面如果个人再遇到其他 flex 的浏览器兼容性问题,还会再总结补充进来。
  • 虽说这篇文章不能算是完全原创,但是毕竟也是个人花了时间和精力整理、基于实际工作场景尝试和总结的,因此如需转载,还请附上此出处哈!
    • 也算是对个人总结的一些认可吧 -.-

玻璃钢生产厂家浙江玻璃钢卡通水果雕塑大型玻璃钢花盆图片特色玻璃钢雕塑摆件采购商场美陈ppt模板商场内潮街美陈泰州玻璃钢雕塑定制价格橙子玻璃钢雕塑厂家青海玻璃钢牌匾雕塑渭南玻璃钢花盆熊大熊二玻璃钢雕塑山西步行街玻璃钢雕塑制作商场美陈活动佛山树脂玻璃钢雕塑供应商平凉玻璃钢雕塑公司贵阳商场美陈布置山东特色商场美陈市场报价沧州玻璃钢雕塑设计阜新玻璃钢雕塑定制广东玻璃钢花盆厂家直销信阳抽象玻璃钢仿铜雕塑贵州玻璃钢雕塑订做玻璃钢牛图片雕塑湖州玻璃钢海豚雕塑定制北京特色商场美陈制作沧州卡通玻璃钢雕塑厂家玻璃钢雕塑在城市景观中的应用铜陵景观雕塑玻璃钢安徽卡通玻璃钢雕塑淮南玻璃钢公仔人物雕塑玻璃钢香蕉雕塑哪里好香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化