当前位置: 首页 > news >正文

css | 总结一下flex布局

一维布局

flex布局只能处理主轴方向的布局, 其弹性也都是围绕主轴处理的,而交叉轴没有弹性,只能依次排布,如果需要2个方向的布局,需要使用 grid!

盒子开启flex的特性

1. flex-item 块状化 开启flex之后,flex-item的display计算值都为 block / table [ 匿名行内盒子/匿名块盒子 也会变成块盒子 ]

2. flex和浮动放在一起 浮动失效

3. flex和绝对定位放在一起 flex失效

4. flex-item 也支持 zindex

5. 没有margin合并

flex-direction 主轴方向 

flex-direction控制主轴的方向 默认 row

可以设置 row | row-reverse | column | column-reverse

flex-wrap

表示当宽度溢出的时候,是否换行 默认为 nowrap 即 flex容器中只会有一行item 不会换行

nowrap | wrap 溢出的时候自动换行

需要注意,开启wrap之后 flex-shrink 就没有效果了

flex-flow

为 flex-direction和flex-wrap的组合属性

比如 : flex-flow: row nowrap

交叉轴排布

弹性行盒子 flex-line

flex-line 在交叉轴方向排布,大小取决于内部弹性盒子,使用align-content可以设置flex lines的排布方式

与容器的关系:所有 flex lines 沿副轴方向排列(例如主轴水平时,行从上到下排列),容器的 align-content 属性可控制多行在副轴方向的对齐方式(如居中、分散等)。

行高(沿副轴的尺寸):每行的高度(或宽度,取决于主轴方向)由该行内最高(或最宽)的项目决定,或通过容器的 align-items 调整项目在该行内的对齐方式。

align-content

当副轴方向有额外空间时 align-content 用来控制 flex-lines在flex容器中的排布方式,其值包含

stretch: 延展,flex-line的高度尽可能大,占满flex容器 也是默认值

flex-start 从交叉轴开始位置排布

center 交叉轴中心位置排布

flex-end 交叉轴结束位置排布

space-between 空余空间只排布在两个flex-line之间

space-around 空余空间排布在所有flex-line周围

space-evenly 空余空间排布在所有flex-line周围, 并且等距 类似margin合并的效果

需要注意,align-content在flex-wrap: nowrap的情况下不生效!规范中,其设计目的是处理多个flex lines的排布。 当nowrap时,只产生一个flex-line 并且默认延伸占满整个flex容器。

e.g.  下面这个例子,flex-item都没设置高度,align-items默认是stretch, 在nowrap的状态下,即便设置了 align-content 也没任何效果,依旧是单flex-lines延展整个flex容器!

    <style>.container {height: 300px;width: 300px;background-color: lightslategray;display: flex;flex-wrap: nowrap;align-content: flex-start;}.box {border: 1px solid black;width: 100px;}</style><div class="container"><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div></div>

开启 wrap 查看一下 align-content不同属性的flex-lines排列

注意,flex-line的高度只有在 align-content: strtch (默认) 时,才会延伸扩展充满整个容器,其他属性状态下,其高度都是由内部的 flex-items撑开

CSS 规范对 align-content 的官方描述是:

“Aligns a flex container’s lines within the flex container when there is extra space in the cross-axis direction.”

(当副轴方向有额外空间时,将 flex 容器内的 “lines”(弹性行) 在容器内对齐。)

这里的 “lines” 是核心 —— 只有当 flex-wrap: wrap/wrap-reverse 产生 多个弹性行 时,才存在 “lines” 的集合;而 flex-wrap: nowrap 只有 1 个弹性行,不存在 “多个 lines 组成的整体”,自然没有 align-content 可作用的对象。

align-items

align-items 决定了 flex-items 如何在弹性行盒中排列 其值有 

stretch | flex-start | flex-end | center | baseline 

看下面例子,单行的情况下:

此时 flex-line的高度为容器高度 为了方便观看 粉色为flex-line的高度

在默认的 strtch状态下,flex-items会占满行高

其余情况下,flex-item 高度都由内容决定

如果设置了高度,那么stretch失效

我们把 flex-wrap 改成 wrap 看多行的情况

当 align-content 不设置 默认 stretch的情况下,此时flex-lines充满容器高度,line高度为红色部分展示,可以看到align-items调整的是items在flex-line中的排布方式

修改 align-content的值,将其改成 flex-start / end /space-enely 

此时 flex-line的高度不再延展,而是由内容决定,此时align-item设置什么值都一样,因为lines高度由内容决定, 为所有flex-item最高的那个

W3c 对 align-items的解释

The align-items property sets the default align-self for all of the flex items in the flex container.

align-items defines how flex items are aligned along the cross axis of the current line of the flex container. // align-items决定 items如何在flex-line中排列

Values: stretch | flex-start | flex-end | center | baseline

align-self - 修改item在flex-line中的位置

使用 align-self 可以修改某个item在弹性行盒的排布方式 注意这是写在items上的样式

由于一维布局, 没有justify-self

主轴排布

flex是1维布局,只有行轴的概念,没有列轴的概念,也就是说,盒子只能在行中弹性排布,自适应延展,在纵向智能简单的 堆叠 

grid是2维布局,由行列轴的概念,盒子在两个方向上都可以自适应排布

justifty-content

规范里这么定义 justify-content

The justify-content property aligns flex items along the main axis of the current line of the flex container. This is done after any flexible lengths and any auto margins have been resolved. Typically it helps distribute extra free space leftover when either all the flex items on a line are inflexible, or are flexible but have reached their maximum size. It also exerts some control over the alignment of items when they overflow the line.

justify-content 属性用来在 flex 容器当前行的主轴方向 上对齐 flex 项目。这种对齐发生在 所有弹性长度(flexible lengths)和自动外边距(auto margins)都已经计算完成之后。

通常情况下,它的作用是 分配一行内多余的剩余空间 —— 这种剩余空间可能出现在:

  1 该行内所有 flex 项目都是不可伸缩的,或者

  2 虽然项目可伸缩,但已经达到了它们的最大尺寸

当项目在主轴方向 溢出行 时,justify-content 也会对它们的对齐方式产生一定影响。

总结一下,justify-content的作用是,在主轴方向的弹性长度和margin都计算完之后,如果还有剩余空间,此时justify-content才会起作用分配这些多余的空间 (若没有剩余空间则无效)

其属性值包含 

normal 默认 | flex-start | flex-end | center | space-around | spcae-between | space-evenly

主要说一下 normal,css中,当有列轴概念的时候 grid,此时normal解析为stretch 当没有列轴概念的时候 flex,此时normal解析为 flex-start。

需要注意规范的最后一点,即便宽度没有剩余,justify-content 依旧有可能影响横向排布 比如当items溢出时,flex-end center flex-start 有不一样效果

弹性布局三大属性 grow shrink basis

Flex 弹性布局依靠flex-grow flex-shrink flex-basis 这三个属性配置,分别对应有剩余空间时的增长,溢出时的缩小,基本尺寸

这三个属性都是写在 flex-item 上的

flex-grow

用来指定当flex-item盒子无法排满flex-line时,如何伸长item来利用剩余空间,其属性值为数字。默认值为 0 

分配原理为:

1. 计算flex-line中所有item的flex-grow值,如果总和<1 那么就把剩余空间 * 每个item的flex-grow属性

2. 如果计算结果 > 1 那么按照每个item的flex-grow大小计算比例,分配剩余空间

看例子

当flex-items的flew-grow总和 < 1 时       

 .container {padding: 20px;width: 400px;height: 100px;background-color: lightgray;display: flex;}.box {flex-grow: 0.2;border: 1px solid black;flex-basis: 100px;height: 100px;background-color: lightgoldenrodyellow;}.box2 {flex-grow: 0.2;border: 1px solid black;flex-basis: 100px;height: 100px;background-color: lightseagreen;}</style><div class="container"><div class="box"></div><div class="box2"></div></div>

空间没有占满

把 flex-grow 分别改成 2, 1

此时剩余空间分配比例为 2: 1 如下

改成 10 : 10 最终也是按照比例分配

改成 0, 10 此时 box 宽度就为基础尺寸 不会增长, box1会占满所有剩余空间

flex-shrink

flex-shrink 用来控制,当一个flex-line中的flex-item总长度超过flex-line的长度时,如何缩放盒子,属性值为数字, 默认值为 1,默认情况下会收缩

其规则为

1. 如果flex-lines中所有的items的flex-items的flex-shrink值 之和 < 1 那么每个item的收缩长度为 flex-shrink * 超出长度,可能还会溢出

2. 如果超过 1, 那么就按照 flex-shrink的比例来收缩

看例子   

<style>.container {padding: 20px;width: 400px;height: 100px;background-color: lightgray;display: flex;}.box {/* flex-shrink: 0; */border: 1px solid black;flex-basis: 300px;height: 100px;background-color: lightgoldenrodyellow;}.box2 {/* flex-shrink: 0; */border: 1px solid black;flex-basis: 300px;height: 100px;background-color: lightseagreen;}</style><div class="container"><div class="box"></div><div class="box2"></div></div>

box box2 的基础宽度和为 600px 超出了容器的400px宽度,此时flex-shrink生效,由于默认值为1 所以默认就有收缩效果

强制都设置flex-shrink为0 则溢出

都设置为 0.2 会发现,收缩了,但是还有溢出

改成 2, 1 会发现没有溢出了 因为flex-shrink之和 > 1 收缩比例,会发现box1 收缩的多一点

收缩会收到最小宽度限制 我们设置 min-width: 300px

   .box {flex-shrink:2;border: 1px solid black;flex-basis: 300px;min-width: 300px;height: 100px;background-color: lightgoldenrodyellow;}

此时 box1无法收缩,只能由box2收缩

flex-basis

先说几个尺寸,弹性布局中,有几个尺寸

1. 基础尺寸, item盒子在不收缩/延展的情况下的尺寸,这个尺寸主要由 flex-basis 设置,也由width或首选最大宽度影响

2. 最大尺寸,item盒子可以增长到的最大尺寸, 受到max-width影响

3. 最小尺寸,item盒子可以收缩到的最小尺寸,受到 min-width width 首选最小尺寸 overflow裁切 影响

4. 增长/收缩尺寸

其计算过程如下

[ Step 1 ] 基础尺寸 base size

    ↓

    来源:flex-basis > width > 内容尺寸 (intrinsic size)

[ Step 2 ] 弹性分配

    ↓

    如果总和 < 容器宽度 → flex-grow 分配剩余空间

    如果总和 > 容器宽度 → flex-shrink 按比例收缩

    → 得到 “假设尺寸” hypothetical size

[ Step 3 ] min/max 约束 (最高优先级)

    ↓

    final size = clamp(min-width, hypothetical size, max-width)

clamp(min, value, max) = 

    if value < min → min

    if value > max → max

    else → value

总结一下就是,先忽略最大最小值,根据grow shrink basis的配置,计算出每个item盒子的尺寸,然后拿这个尺寸和最大值 最小值的尺寸去比较,进行 clamp计算,在满足尺寸的情况下,才作为盒子的最终尺寸,不满足的话就按照 min max 调整

flex-basis就是用来设置基础尺寸的,其接受尺寸值,百分比,或者 auto

基础尺寸

计算方式如下:

1. 如果flex-basis 不为 auto 就将其值作为 基础尺寸

2. 如果flex-basis为 auto 则width作为基础尺寸

3. 如果 flex-basis和width 都是auto,那么将 首选最大尺寸 作为基础尺寸(设置了white-space: nowrap的效果 文本不换行 一行展开的长度)

看例子

   <style>.container {padding: 20px;width: 400px;height: 100px;background-color: lightgray;display: flex;}.box {flex-shrink: 0;border: 1px solid black;flex-basis: 100px;height: 100px;background-color: lightgoldenrodyellow;}.box2 {flex-shrink: 0;border: 1px solid black;flex-basis: 100px;height: 100px;background-color: lightseagreen;}</style><div class="container"><div class="box"></div><div class="box2"></div></div>

此时的基础尺寸为 flex-basis的尺寸 即 100px 关闭了收缩和增长 如下

去掉 flex-basis默认为 auto 改成width:100px      .

box {flex-shrink: 0;border: 1px solid black;width: 100px;height: 100px;background-color: lightgoldenrodyellow;}.box2 {flex-shrink: 0;border: 1px solid black;width: 100px;height: 100px;background-color: lightseagreen;}

此时 基准尺寸还是 100px

弃掉 width 此时 flex-basis width都是 auto

box内部加入可以在任何位置换行的中文 

    <div class="container"><div class="box">这是一行中文</div><div class="box2">可以随意位置换行</div></div>

此时,基础尺寸就是首选最大宽度

最大尺寸 

最大尺寸只由max-width属性决定

最小尺寸

受到 width minwidth 首选最小宽度 和 overflow裁切影响,计算方式为

1. 如果设置了 min-width 不为auto的情况下,直接把min-width组为最小尺寸

2. min-with为auto的情况下,如果设置了width不为auto,则 计算 min(width, 首选最小宽度) 作为最小宽度 (即文本产生换行的最小尺寸 whitespace:wrap)

3. 如果 min-width width都为 auto 则把首选最小宽度作为最小尺寸

4. 如果设置了 overflow: hidden(auto scroll 发生裁切) 且 最小尺寸由首选最小宽度决定 (规则3) 则最小尺寸无效 为 0px

看例子       

.container {padding: 20px;width: 400px;height: 100px;background-color: lightgray;display: flex;}.box {flex-shrink:2;border: 1px solid black;flex-basis: 300px;min-width: 300px;height: 100px;background-color: lightgoldenrodyellow;}.box2 {flex-shrink: 1;border: 1px solid black;flex-basis: 300px;height: 100px;background-color: lightseagreen;}</style><div class="container"><div class="box"></div><div class="box2"></div></div>

由于设置了 box min-width: 300px 此时其最小尺寸为 300px,收缩的时候最小只能收缩到300px,其余的收缩尺寸都由box2完成

去掉 min-width 增加连续不能换行的英文

   <div class="container"><div class="box">xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</div><div class="box2"></div></div>

可以看到尾了满足首选最小宽度的最小尺寸,box2直接收缩没了,但是还是溢出了,因为box的最小尺寸就大于container了

给 box增加宽度 300px

        .box {flex-shrink:2;border: 1px solid black;flex-basis: 300px;width: 300px;height: 100px;background-color: lightgoldenrodyellow;}

此时最小尺寸为 min (首选最小宽度,width) = 300px 如图

width: 300px 改成 overflow: hidden;

此时由于 最小尺寸由首选最小宽度决定,所以最小尺寸无效

auto scroll也可以 只要裁切就可以

flex 快捷属性

flex属性可以用来快捷设置 flex-grow , flex-shrink , flex-basis

flex 默认值为 initial 对应 flex-grow: 0 flex-shrink: 1 flex-basis: auto

flex:如果设置一个数字,对应flex-grow, 此时fkex-shrink: 1 flex-basis: 0%

flex 如果设置一个尺寸px 对应 flex-basis 此时 flex-grow 1 flex-shrink 1 

flex 设置2个数字,对应flex-grow flex-shrink 此时flex-basis为 0%

flex 设置一个数字,一个尺寸,对应flex-grow flex-basis 此时flex-shrink: 1

flex: auto ( 注意 auto不是默认值 ) 此时 flex-grow 1 flex-shrink 1 flex-basis: auto item会自适应放大或缩小

flex:none 此时 flex-grow: 0 flex-shrink: 0 flex-basis: auto 此时item会保持基本尺寸 不会变化 

文本打点案例

我们一般会用

overflow: hidden

text-overflow: ellipsis

white-space: nowrap 

三件套给溢出文字的位置增加 ... 效果

但是下面的例子却不生效

   <style>.container {display: flex;width: 400px;background-color: lightgray;}.ellipsis {overflow: hidden;white-space: nowrap;text-overflow: ellipsis;}</style><div class="container"><item>宽度不确定项</item><item style="background-color: yellow"><p class="ellipsis">文字内容文字内容文字内容文字内容文字内容文字内容文字内容</p></item></div>

原因也很简单,第二个 item的最小尺寸为首选最小宽度(内容宽度),此时内部的p设置了nowrap 其宽度是内部文本的宽度 (首选最大宽度) 所以此时item的最小尺寸就是p的尺寸,item盒子不会被收缩,也不存在文本裁切,不会打点

解决办法就是给第二个item设置更小的最小宽度,让其收缩,可以item设置min-width: 0

最后一行元素不足导致的排列问题

方法1。补足空的flex-item 

   <style>.container {width: 550px;height: 550px;background-color: lightslategray;display: flex;justify-content: space-between;flex-wrap: wrap;align-content: space-between;}.box {flex: none;width: 100px;height: 100px;background-color: lightseagreen;border: 1px solid black;}</style><div class="container"><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box" style="height: 0px;border-style: none;"></div><div class="box" style="height: 0px;border-style: none;"></div><div class="box" style="height: 0px;border-style: none;"></div><div class="box" style="height: 0px;border-style: none;"></div><div class="box" style="height: 0px;border-style: none;"></div></div>

2. 如果元素用的是百分比宽度  可以动态计算 margin   

<style>.container {width: 550px;background-color: lightslategray;display: flex;justify-content: space-between;flex-wrap: wrap;align-content: flex-start}.box {flex: none;width: 24%;height: 100px;background-color: lightseagreen;border: 1px solid black;}.box:last-child:nth-child(4n-1){margin-right: calc( 24% + 4% / 3 );}.box:last-child:nth-child(4n-2){margin-right: calc( 48% + 8% / 3 );}</style><div class="container"><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div></div>

http://www.dtcms.com/a/389961.html

相关文章:

  • c#里面的catch (Exception e)
  • 浅谈 CDN
  • 125、【OS】【Nuttx】【周边】效果呈现方案解析:分号与换行
  • CBB21-MPP电子元器件 RC容钏 金属化聚丙烯薄膜电容器 电子元器件技术解析
  • Day02 递归 | 46. 全排列、226. 翻转二叉树
  • [Spring Cloud][6] Eureka Server 搭建详解,与 Zookeeper 的区别
  • 前端性能优化完全指南:从入门到实战
  • 国产组态软件对工控行业的影响及作用
  • Databend 亮相 RustChinaConf 2025,分享基于 Rust 构建商业化数仓平台的探索
  • 从把python里的一个函数变成接口到自动化测试平台的实现
  • LibreTV+cpolar:打造私人云影院的智能方案
  • 软考高级系统架构设计师之架构设计扩展篇(一)
  • 宝德PR1710P服务器安装Anolis8.6系统
  • ABAP读写SAP服务器文件
  • 无人机操控核心:智能飞行的技术引擎
  • H5页面在真机移动端1px边框处理方案总结
  • 本地大模型部署与应用: Dify 与 Ollama 集成
  • 从 “盲调” 到 “精准优化”:SQL Server 表统计信息实战指南
  • ffmpeg.dll是什么?4步彻底解决ffmpeg.dll丢失报错问题
  • ROS2C++核心基础
  • 第二篇:搭建现代C++开发环境:VS2022 / CLion / VSCode实战
  • 【群晖NAS】一键脚本搭建frp内网穿透,在外轻松远程访问内网设备|远程桌面
  • 【HTML】 第一章:HTML 基础
  • 【RAG】知识库问答不是只有 RAG
  • 前端缓存深度解析:localStorage 到底是同步还是异步?
  • Vue2 基础知识点二:事件绑定 (Event Binding)
  • ​​[硬件电路-250]:LDO电源核心指标、典型问题与工程实践指南
  • 论文笔记(九十二)RLVR-World: Training World Models with Reinforcement Learning
  • 驾校培训办公管理系统 专属驾校的OA系统 驾培管理行业
  • 绿色纺织品的国际通行证:GRS认证的深度解析