前端知识库(lizh)
  • README
  • Bugs
    • 前端调试随笔
    • 浏览器常见问题概览
    • 浏览器兼容问题概览
    • HTML常见问题概览
    • CSS常见问题概览
    • JS常见问题概览
    • 移动端兼容性问题概览
    • 微信小程序开发
    • NodeJs常见问题概览
    • Mac常见问题概览
    • 微信开发遇坑指南
    • Npm包常见问题概览
    • 其他问题汇总
  • Css探索系列
    • CSS基础知识
    • CSS常见问答
    • CSS常见问答02
    • CSS应用示例
    • CSS应用示例02
    • 由Z Index引发的层叠上下文思考
    • 由浮动塌陷引发的块级格式上下文思考
    • CSS探索系列 Flex布局
    • CSS探索系列 Margin
    • CSS探索系列 Auto关键字
    • CSS探索系列 Gradient
    • CSS探索系列 Line Height
    • CSS探索系列 元素居中
    • CSS探索系列 动画
    • 为什么使用PostCSS处理CSS?
    • 重新认识伪类与伪元素
    • 自定义表单伪元素样式
    • 如何理解Css中的Display属性
    • 视口和软键盘对视口的影响
    • 关于Css
  • Frontend
    • 00 关于Web前端
    • 01 前端知识概览
    • 02 常用前端库概览
    • 基础 00 前端常见问题01
    • 基础 01 浏览器缓存
    • 基础 02 浏览器工作原理
    • 基础 03 谈谈前端跨源问题及解决方法
    • 进阶 01 Web性能优化
    • 进阶 02 搜索引擎优化(SEO)
    • 进阶 03 前端模块化编程
    • 进阶 04 规范代码:Linter、Prettier、EditorConfig
    • 进阶 11 前端自动化测试
    • 高级 01 前端安全
    • Vue2.X原理篇
    • Vue3初步了解及迁移指南
    • 重读Vue教程
    • React17.X原理篇
    • 你必须知道的React问题
    • 重读React教程
    • 聊一聊Cookie的一些问题
    • 如何理解HTTP响应的状态码
    • HTTP的历史演变及概述
    • Webpack4.X原理篇
    • Webpack基础入门篇
    • Webpack构建优化篇
    • TypeScript使用指南
    • 代码规范
      • 前端规范
      • HTML
      • CSS
      • JS
  • Html探索系列
    • HTML基础知识
    • HTML基础知识02
    • HTML常见问答
    • HTML经典实践用例
    • HTML元素的宽高及位置详解
    • Video元素的使用和常见问题总结
    • Html探索系列 Meta标签
    • DOCTYPE:文档类型与浏览器模式
    • DHTML(动态网页)简介
    • HTML标签详解
    • HTML布局的几种方式
    • HTML全局属性
    • 关于Html
  • Js探索系列
    • 基础知识
    • 常见问答
    • 应用示例
    • 趣味示例
    • 基础篇 05 AJAX
    • 基础篇 06 Window对象
    • 基础篇 07 Error、JSON、Math、Console对象
    • 基础篇 08 History、URL、Screen、Navigator、Location对象
    • 基础篇 09 文档对象模型(DOM)
    • 基础篇 10 Document对象
    • 基础篇 11 Element对象
    • 基础篇 12 Event对象
    • 基础篇 13 键盘、鼠标、触摸事件
    • 基础篇 15 CSS对象模型(CSSOM)
    • 进阶篇 01 Prototype对象和继承
    • 进阶篇 02 Promise对象
    • 进阶篇 07 迭代器(Iterator)
    • 进阶篇 08 Generator和Async函数
    • 进阶篇 09 JavaScript异步编程
    • Date对象和日期时间字符串格式
    • Canvas基础入门篇
    • Canvas进阶篇
    • SVG基础入门篇
    • 四种判断数据类型方法的优缺点
    • 深入理解JavaScript的浅拷贝和深拷贝
    • 谈谈JavaScript的作用域和上下文
    • 复制内容到剪贴板
    • 关于Javascript
  • NodeJs
    • 关于Node.Js
    • Node.Js:三种调试方法
    • Npm包管理器简介及一些机制
    • NPM:Package.Json详解(中文)
    • NPM:从零开始,开发一个软件包
    • NPM:常用命令
    • Node.Js:Fs(文件系统)
    • Node.Js:Global(全局变量)
    • Node.Js:HTTP
    • Node.Js:Module(模块)
    • Node.Js:Path(路径)
    • Node.Js:Readline(逐行读取)
  • Research
    • 极细边框(1px边框)实现方式
    • 如何监控前端异常?
    • H5页面跳转和刷新
    • Web主题切换和个性化定制方法总结
    • Vue SSR(服务端渲染)的简单实现
    • 基于Create React App打造代码规范化的React+Ts项目
    • H5可视化编辑
    • Web常用功能
    • Javascript加密混淆
    • Vue如何导入TypeScript
    • 移动端PDF预览
    • 纯CSS绘制箭头
    • 网站性能测量和优化方法
  • Tech
    • GOOGLE浏览器的搜索技巧
    • Curl的用法指南
    • Sublime3插件篇
    • Charles安装及使用
    • Nginx基础使用
    • 排序算法(Javascript)
    • 代码整洁之道(摘录笔记)
    • Java的24种设计模式与7大原则
    • 观察者和发布订阅模式
  • Tools
    • Git
      • Git基础教程
      • Git常见问题
    • Gitbook
      • Gitbook入门篇
      • Gitbook插件篇
      • Gitbook进阶篇
由 GitBook 提供支持
在本页
  • 基本概念
  • 容器的属性
  • flex-direction属性
  • flex-wrap属性
  • flex-flow属性
  • justify-content属性
  • align-items属性
  • align-content属性
  • place-content属性
  • 项目的属性
  • order属性
  • flex-grow属性
  • flex-shrink属性
  • flex-basis属性
  • flex属性
  • align-self属性
  • 弹性项目尺寸的计算
  • 浏览器前缀
  • 相关问题
  • iPhone 设备兼容
  • 参考链接

这有帮助吗?

  1. Css探索系列

CSS探索系列 Flex布局

上一页由浮动塌陷引发的块级格式上下文思考下一页CSS探索系列 Margin

最后更新于1年前

这有帮助吗?

当对一个文档进行布局的时候,浏览器的渲染引擎会根据标准之一的 CSS 基础框盒模型(CSS basic box model),将所有元素表示为一个个矩形的盒子(box)。每个盒子由四个部分组成:内容 Content、内边距 Padding*、*边框 Border、外边距 Margin。CSS 决定这些盒子的大小、位置以及属性(例如颜色、背景、边框尺寸…)。

布局的传统解决方案,基于盒状模型,依赖 display 属性 + position属性 + float属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。

Flex 是 Flexible Box 的缩写,意为"弹性盒子",用来为盒状模型提供最大的灵活性。

**弹性盒子布局(Flexible Box Layout)**定义了一种针对用户界面设计而优化的 CSS 盒子模型。在弹性布局模型中,弹性容器的子元素可以在任何方向上排布,也可以弹性伸缩其尺寸,既可以增加尺寸以填满未使用的空间,也可以收缩尺寸以避免父元素溢出。子元素的水平对齐和垂直对齐都能很方便的进行操控。

基本概念

弹性盒子布局是一种一维的布局模型,一次只能处理一个维度上的元素布局,一行或者一列。作为对比的是另外一个二维布局 ,可以同时处理行和列上的布局。

image-20200612003555661
.container {
    display: flex | inline-flex; /**生成块或内联的弹性容器**/
}

弹性容器: display 属性的值为 flex | inline-flex 的元素。

**弹性项目:**弹性容器的每个子元素都称为弹性项目。

轴:每个弹性盒子布局包含两个轴。弹性项目沿其依次排列的那根轴称为主轴。垂直于主轴的那根轴称为侧轴(cross axis)。

方向:弹性容器的主轴起点(main start)/主轴终点(main end)和侧轴起点(cross start)/**侧轴终点(cross end)**描述了弹性项目排布的起点与终点。它们具体取决于弹性容器的主轴与侧轴中,由 writing-mode 确立的方向(从左到右、从右到左,等等)。

尺寸:根据弹性容器的主轴与侧轴,弹性项目的宽和高中,对应主轴的称为主轴尺寸(main size) ,对应侧轴的称为 侧轴尺寸(cross size)。

由于弹性盒子使用了不同的布局算法,某些属性用在弹性容器上没有意义:

  • 多栏布局模块的 column-* 属性对弹性项目无效。

  • float 与 clear 对弹性项目无效。使用 float 将使元素的 display 属性计为block。

  • vertical-align 对弹性项目的对齐无效。

容器的属性

以下6个属性设置在容器上:

  • flex-direction

  • flex-wrap

  • flex-flow

  • justify-content

  • align-items

  • align-content

flex-direction属性

定义了主轴的方向(正方向或反方向),即弹性项目的排列方向。

初始值:row

取值:

  • row:主轴为水平方向,从左到右。

  • row-reverse:主轴为水平方向,从右到左。

  • column:主轴为垂直方向,从上往下。

  • column-reverse:主轴为垂直方向,从下往上。

请注意:

row 和 row-reverse 受 flex 容器的direction属性的影响。

css属性 direction 用来设置文本、表列水平排列的方向,初始值ltr。 ltr 表示从左到右 (类似汉语、英语等大部分语言), rtl 表示从右到左 (类似希伯来语或阿拉伯语)。

direction属性是 ltr,row 表示从左到右定向的水平轴,而 row-reverse 表示从右到左; 如果 dir 属性是 rtl,row 表示从右到左定向的轴,而 row-reverse 表示从左到右。

column和column-reverse受弹性容器的 writing-mode 属性的影响。

writing-mode 属性指定块流动方向,即块级容器堆叠的方向,以及行内内容在块级容器中的流动方向。

horizontal-tb:行内元素从左到右或从右到左(受direction属性的影响) ,块元素由上往下。 vertical-rl:行内元素由上往下或由下往上,块元素从左到右或从右到左。(受direction属性的影响) vertical-lr:行内元素由上往下或由下往上,块元素从左到右或从右到左。(受direction属性的影响)

flex-wrap属性

指定弹性项目单行显示还是多行显示 。如果允许换行,这个属性允许你控制行的堆叠方向。

初始值:nowrap

取值:

  • nowrap:弹性项目被摆放到到一行,这可能导致溢出弹性容器。 cross-start 会根据 flex-direction 的值 相当于 start 或 before。

  • wrap:弹性项目被打断到多个行中,行由上往下排列。

  • wrap-reverse:和 wrap 的行为一样,但是行由下往上排列。

flex-flow属性

flex-flow 属性是 flex-direction 和 flex-wrap 的简写。

初始值:row nowrap。

flex-flow: column-reverse wrap;

justify-content属性

定义了弹性项目在主轴上的对齐方式及其周围的空间的分配。

初始值:flex-start

取值:

  • flex-start:主轴起点对齐。

  • flex-end:主轴终点对齐。

  • center: 居中。

  • space-between:两端对齐,弹性项目之间的间隔都相等。

  • space-around:每个弹性项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。

  • space-evenly:弹性项目之间、弹性项目与边框之间的间隔都相等。

以上六个是常见取值,还有值start、left、right、baseline、first baseline、last baseline、stretch、safe、unsafe。??

align-items属性

属性定义弹性项目在侧轴上如何对齐。

初始值:normal。取决于我们处在什么布局模式中

取值:

  • flex-start:侧轴起点对齐

  • flex-end:侧轴终点对齐

  • center:中间对齐

  • baseline: 弹性项目的第一行文字的基线对齐

  • stretch:弹性项目将占满整个容器的高度(弹性项目未设置高度或设为auto)。

align-content属性

当弹性盒子分多行时,定义了行的对齐方式和周围分配空间。该属性对单行(即:未设置flex-wrap或 flex-wrap: nowrap)弹性盒子模型无效。

取值:

  • flex-start:侧轴起点对齐

  • flex-end:侧轴终点对齐

  • center:中间对齐

  • space-between:与侧轴两端对齐,轴线之间的间隔平均分布。

  • space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。

  • stretch(默认值):轴线占满整个侧轴(弹性项目未设置高度或设为auto)。

place-content属性

是 align-content 和 justify-content 的简写。第一个值为 align-content 属性, 第二个值为 justify-content 。

place-content: center start; 

非常重要:如果没有设置第二个值,那么第二个的值与第一个相等,此前提是第一个值对两个属性都是有效的。如果设置的这个值对两个属性都无效,那么整个设置的值就是无效的。

项目的属性

以下6个属性设置在项目上:

  • order

  • flex-grow

  • flex-shrink

  • flex-basis

  • flex

  • align-self

order属性

定义项目的排列顺序。数值越小,排列越靠前,默认为0。

flex-grow属性

指定了弹性项目扩展规则,即弹性容器中剩余空间的应该分配多少给弹性项目。

剩余的空间是弹性容器的主轴尺寸减去所有弹性项目的尺寸和。

默认为0,即如果存在剩余空间,也不放大;大于0,则弹性容器剩余空间的分配就会发生;负值无效。

具体规则如下:

  • 所有剩余空间总量是1

  • 只有一个弹性项目设置了 flex-grow属性值

    • 如果flex-grow值小于1,则扩展的空间就是总剩余空间 * flex-grow值

    • 如果flex-grow值大于1,则独享所有剩余空间

  • 有多个弹性项目设置了flex-grow属性值

    • 如果flex-grow值总和小于1,则每个子项扩展的空间就是总剩余空间 * flex-grow值。

    • 如果flex-grow值总和大于1,则所有剩余空间被利用,分配比例就是flex-grow属性值的比例。

      如:所有弹性项目都有相同的flex-grow系数,那么所有的项目将获得相同的剩余空间。

      如:三个弹性项目,有一个的flex-grow属性为2,其他项目都为1,即:1:2:1,则值为2的占据剩余空间的2/4,其他两个分别占1/4。

flex-shrink属性

指定了弹性项目的收缩规则。弹性项目仅在默认宽度之和大于容器,且未设置flex-wrap或者flex-wrap: nowrap的时候才会发生收缩。

不足空间是所有弹性项目的宽度和 - 弹性容器的宽度。

默认值为1,即如果空间不足,弹性项目将缩小;值为0表示不收缩;负值无效。

具体规则:

  • 只有一个弹性项目设置了flex-shrink

    • flex-shrink值小于1,则收缩的尺寸不完全,会有一部分内容溢出弹性容器。

    • flex-shrink值大于等于1,则收缩完全,正好填满弹性容器。

  • 多个弹性项目设置了flex-shrink

    • flex-shrink值的总和小于1,则收缩的尺寸不完全,每个弹性项目的收缩尺寸为不足空间 * flex-shrink值。

    • flex-shrink值的总和大于1,则收缩完全,每个弹性项目收缩尺寸的比例和flex-shrink值的比例一样。

      如:所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。

      如:一个弹性项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。

flex-basis属性

指定了弹性项目在主轴方向上的初始大小。浏览器根据这个属性,计算主轴是否有多余空间。

**注意:**弹性项目的最终尺寸,是由一系列盒模型属性和布局算法决定的,具体可查看下文【弹性项目尺寸的计算】章节。

初始值:auto

取值:

  • auto,即弹性项目的本来大小。

    最初 auto 的含义是 "参照width和height属性"。

  • <width>

    可以跟width或height属性的值一样(比如350px、2rem、30%),则弹性项目将占据固定空间。负值是不被允许的。

    Note: 当一个元素同时被设置了 flex-basis (除值为 auto 外) 和 width (或者在 flex-direction: column 情况下设置了height) , flex-basis 具有更高的优先级。

  • content

    基于弹性项目的内容自动调整大小。除火狐,其他大多数浏览器不支持。

  • 其他值。除火狐,其他大多数浏览器不支持。

    /* 固有的尺寸关键词 */
    flex-basis: fill;
    flex-basis: max-content;
    flex-basis: min-content;
    flex-basis: fit-content;

flex属性

flex属性是flex-grow, flex-shrink 和 flex-basis的简写,后两个属性可选。

建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。

默认值:initial,0 1 auto。

flex 属性可以指定1个,2个或3个值:

  • 单值语法:值必须为以下其中之一

    • 一个无单位数值:它会被当作<flex-grow>的值。

    • 一个有效的宽度(width)值:它会被当作 <flex-basis>的值。

    • 关键字none,auto或initial。

      auto :1 1 auto

      none:0 0 auto

      initial:0 1 auto。即:flex-grow、flex-shrink、flex-basis的默认值。

  • 双值语法:第一个值必须为一个无单位数值,当作 <flex-grow> 的值。第二个值必须为以下之一

    • 一个无单位数:它会被当作 <flex-shrink> 的值。

    • 一个有效的宽度值:它会被当作 <flex-basis> 的值。

  • 三值语法

  • 第一个值必须为一个无单位数,并且它会被当作 <flex-grow> 的值。

  • 第二个值必须为一个无单位数,并且它会被当作 <flex-shrink> 的值。

  • 第三个值必须为一个有效的宽度值, 并且它会被当作 <flex-basis> 的值。

align-self属性

align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。

初始值:auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。

取值:可能取6个值,除了auto,其他都与align-items属性完全一致。

弹性项目尺寸的计算

在弹性盒子布局中,一个弹性项目的最终尺寸是基础尺寸、弹性增长或收缩、最大最小尺寸限制共同作用的结果:

  • 基础尺寸:由CSS flex-basis、width等属性,内容尺寸以及box-sizing盒模型共同决定;

  • 弹性增长指的是flex-grow属性,弹性收缩指的是flex-shrink属性;

  • 最大最小尺寸限制指的是min-width/max-width等CSS属性,以及min-content最小内容尺寸。

#优先级
最大最小尺寸限制 > 弹性增长或收缩 > 基础尺寸

弹性项目尺寸的计算规则:

  • 如果没有设置 flex-basis 属性,那么 flex-basis 的大小就是弹性项目的 width 属性的大小;

  • 如果没有设置 flex-basis 、 width 属性,那么 flex-basis 的大小就是弹性项目内容的大小;

  • 默认情况下,flex-basis的大小不会收缩至小于内容尺寸。若想改变这一状况,可以设置 min-width、width 属性。

  • 主轴空间有剩余空间,遵循flex-grow规则;空间不足,遵循flex-shrink规则

以下在实际开发的项目中遇到的问题:使用了flex布局后,弹性项目中文本溢出自动省略号(...)的属性(即, text-overflow:ellipsis )失效。

<section>
    <div class="box_01">
        <div class="item_01">低眉含笑间</div>
        <div class="item_01 item_01_text01" style="flex: 1; ">
            <div class="text">寒灯纸上梨花雨凉 谁的深情绚烂了三生石上的一见倾心 灯烛依旧 无人执手。低眉含笑间 寒灯纸上梨花雨凉 谁的深情绚烂了三生石上的一见倾心 灯烛依旧 无人执手
            </div>
        </div>
    </div>
</section>
<style>
    .box_01 {
        display: flex;
        padding: 10px;
        border: 1px solid #0aa;
    }
    .box_01 .item_01 {
        margin-right: 15px;
        padding: 10px;
        color: #fff;
        text-align: center;
        background-color: #0aa;
        white-space: nowrap;
    }
    .box_01 .item_01 .text {
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
    }
    .box_01 .item_01_text01 {
        min-width: 0;
    }
    /*
    .box_01 .item_01_text02 {
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
    }
    */
</style>

从本质上来说,ellipsis失效的是因为.text元素中的文本没有溢出。

.text_parent元素是一个弹性项目,设置了flex: 1(即:flex-grow:1; flex-shrink:1; flex-basis: auto;,flex-basis: auto;),且没有设置width属性,它的宽度由内容宽度决定,即.text元素的宽度。

.text元素默认情况下width: 100%,宽度与父元素.text_parent一样。父元素宽度不固定的情况下,.text元素的宽度取内容宽度,即文本的宽度。

最终结果:.text_parent的宽度 = .text的宽度 = 文本宽度,所有文本没有溢出

要使ellipsis启效,首先我们可以想到的方法是给.text元素设置一个小于文本宽度的width值,但这种方法显然不适用于响应式开发。

**另一种思路是:**给.text_parent指定一个小于文本宽度的width值。

方法一:.text_parent设置overflow属性

.text_parent {
    overflow: hidden;
}

弹性项目在弹性容器中,有一个可用宽度。设置overflow后,表示弹性项目宽度不超出可用宽度。

方法二:.text_parent设置width属性

.text_parent {
    width: 0;
}

弹性项目的width属性的作用是告诉浏览器:我有自己的宽度,不需要取内容的宽度。注意:弹性项目的最终尺寸不一定是css中的width值,它会根据一系列的盒模型属性来计算。

方法三:.text_parent设置min-width属性

/**
根据CSS规范草案,一般情况下min-width属性默认值是0,但弹性项目的min-width属性默认值是auto,这样能为弹性盒子布局指明更合理的默认表现。
**/
.text_parent {
    min-width: 0;
}

弹性项目设置了min-width属性,浏览器将采用如下算法(shrink-to-fit算法 ??):

弹性项目宽度 = min ( max (最小宽度, 可用宽度) , 首选宽度)

最小宽度:min-width的值

可用宽度:弹性项目在弹性容器中的允许宽度

首选宽度:内容不发生换行的时的宽度。(示例中的文本宽度)

以上是个人对弹性项目width计算的理解,如有不对,敬请指正。

参考文章:

浏览器前缀

flex布局需要一些浏览器前缀来最大力度地兼容大多数的浏览器。Flex布局的前缀不只是在属性前面添加浏览器前缀,不同浏览器下的属性名和属性值都不同,这是因为Flexbox布局的标准一直在变,一共有old, tweener, new 三个版本。

另外,这里有一个Sass中 @mixin 来处理一些前缀,也可以给你一些处理前缀的启发:

@mixin flexbox() {
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -webkit-flex;
  display: flex;
}

@mixin flex($values) {
  -webkit-box-flex: $values;
  -moz-box-flex:  $values;
  -webkit-flex:  $values;
  -ms-flex:  $values;
  flex:  $values;
}

@mixin order($val) {
  -webkit-box-ordinal-group: $val;  
  -moz-box-ordinal-group: $val;     
  -ms-flex-order: $val;     
  -webkit-order: $val;  
  order: $val;
}

.wrapper {
  @include flexbox();
}

.item {
  @include flex(1 200px);
  @include order(2);
}

相关问题

iPhone 设备兼容

iPhone 11pro、iPhone 不支持 justify-content: right,请用 justify-content: flex-end 代替。

参考链接

**行:**根据 属性指定弹性项目单行显示还是多行显示 。如果允许换行,这个属性允许你控制行的堆叠方向(从左到中、从右到左)。

image-20200612004410287
image-20200612011228246
image-20200612225416483
image-20200612232910010

image-20200613141809054
image-20200613143309096

在此之后,auto 的含义变成了自动尺寸, 而 main-size 变成了 "参照width和height属性"。实际执行于 .

然后呢,这个更改又在 中被撤销了, 所以 auto 变回了原来的含义;而一个新的关键字 content 变成了自动尺寸。 ( 包括了增加这个关键字)。

image-20200613154244372
image-20200613203317491

可能处理前缀的最好方法是使用新的语法书写CSS并通过运行CSS,能够很好地处理这个问题。

flex-wrap
bug 1032922
bug 1093316
bug 1105111
查看DEMO
张鑫旭 - Oh My God,CSS flex-basis原来有这么多细节
flexbox 布局中 flex 项的宽度计算原理
Autoprefixer
MDN CSS 布局
mdn CSS 弹性盒子布局
Flex 布局教程:语法篇
张鑫旭 写给自己看的display: flex布局教程
网格布局
image-20200613000900833