CSS Flex弹性盒子布局全解析

笔记哥 / 04-16 / 46点赞 / 0评论 / 323阅读
flex 作为现代布局方案中最常用的手段,有必要拉出来细说。 ## flex 相关的 CSS 属性 ### 容器(父元素)相关的 CSS 属性 以下的 CSS 属性,在 flex 布局中需喂给父元素,设置 flex 布局中的盒子相关样式。 `display` 启用 flex 布局 `flex-direction` 主轴方向 `flex-wrap` 控制子元素是否换行 `flex-flow` 简写属性(flex-direction + flex-wrap) `justify-content` 主轴对齐方式 `align-items` 交叉轴对齐方式(单行) `align-content` 交叉轴对齐方式(多行) `gap` 子元素间距 ### 子元素相关的 CSS 属性 以下 CSS 属性,在 flex 布局中喂给子元素,用于设置单个子元素的特殊样式。 `order` 排列顺序 `flex-grow` 放大比例 `flex-shrink` 缩小比例 `flex-basis` 初始大小 `flex` 简写属性(flex-grow + flex-shrink + flex-basis) `align-self` 覆盖容器的 align-items ## 开篇 flex 多用于一维布局,即横向或纵向排列,二维布局是 flex 短板,也不是说不能用,只是没那么灵活。 flex 布局第一步,必须设置容器的 display 属性为 flex 或 inline-flex,这样子元素才会按照弹性盒子的方式进行排列。 ## 容器 ### flex 与 inline-flex 的区别 `display: flex` 是让容器显示为块级弹性盒子独占一行,而 `display: inline-flex` 是让容器显示为内联块弹性盒子,可以与其他元素并排显示。 它们与 `display: block` 和 `display: inline-block` 类似,都是块级元素与内联块元素区别。 **`display: flex`** ![](https://cdn.res.knowhub.vip/c/2504/16/fd0c4f1e.png?G1QAAETn9LyUQkDHvtMdbIlTE20GJKoIKvWs13vO2jfR94dAND%2bj9Rn7wx9an0HmBV5JIAZF8lzgLMIGTXx5dQfXvEYA) **`display: inline-flex`** ![](https://cdn.res.knowhub.vip/c/2504/16/dbfd26d6.png?G1QAAMTsdJxI8kSq26hD2jvFHc2ARBVBpZ71es9Z%2byb6fgcjx2e0Pn1%2f%2bEPr00lr4WoEhnJG8FK4CmCar6BWEsNE4hoO) ### flex-direction 控制子元素排列方向 默认情况下,flex 布局是横向排列的,即子元素从左到右排列(需特别注意,如果设置了 `direction: ltr;` ,则显示方向相反)。 可通过 `flex-direction` 控制子元素排列方向。不同值的效果区别如下: ![](https://cdn.res.knowhub.vip/c/2504/16/c81c546b.png?G1QAAMT0bJzoqarUNvqh%2f4lHQjMgUUVQqWe93nv3aUTf7wyW%2bMw%2blp8Pf%2bhjORVTWCUGFwiCTwpLnMVgoSqysAFxTwc%3d) `reverse` 都表示反向排列。 ### flex-wrap 控制子元素换行 默认情况 flex 子元素在超出容器时,会被挤压到同一行里面显示,如果需要元素换行,可派 `flex-wrap` 上场。不同值区别: ![](https://cdn.res.knowhub.vip/c/2504/16/1857417c.png?G1UAAETn9LyUwhDDvtMdbIlTE20GKtIIKvWs13vO2jfR94dAND%2bj9Rn7wy9an0HFDV5JIAWKFNjgLIqLNTF7VZia5DUC) `wrap-reverse` 是 `wrap` 的反向版本,会将行的顺序反向显示。 ### flex-flow 简写属性,可单独设置某一个值,也可同时设置 `flex-direction` 和 `flex-wrap`,值的顺序无影响,`flex-direction` 和 `flex-wrap` 都能放在第一位。 使用 `flex-flow` 设置 `flex-direction`: ```csharp .box { flex-flow: row; flex-flow: column; } ``` 使用 `flex-flow` 设置 `flex-wrap`: ```csharp .box { flex-flow: nowrap; flex-flow: wrap; } ``` 使用 `flex-flow` 同时设置 `flex-direction` 和 `flex-wrap`: ```csharp .box { flex-flow: row nowrap; flex-flow: wrap column; /* 顺序不影响渲染 */ flex-flow: column-reverse wrap-reverse; } ``` ### justify-content 主轴对齐方式 3 组看起来没啥区别的值 [`start`, `end`] 、 [`flex-start`, `flex-end`] 、 [`left`, `right`] ![](https://cdn.res.knowhub.vip/c/2504/16/fa300c19.png?G1UAAMTsdJxIfCOh26hD2jvFHc1ARRpBpZ71es9Z%2byb6fgdD4jNan74%2f%2fKL16ZSrcjUCI7MghKRcE6RALYD1KiImGtdw) 添加 `direction: rtl;` 之后,可以看出 left 、 right 区别: ![](https://cdn.res.knowhub.vip/c/2504/16/32f058cb.png?G1UAAOQ5d14KIJD0nXZQm6mbNgMVaQSVetbrPWftG%2bD7g5ElP6P1GfvDL1qfAeqGfgEjKwpSIEMn1oJGibhaFSXRvEYA) [`start`, `end`] 和 [`flex-start`, `flex-end`] 没找到有啥区别,可能唯一不同 [`start`, `end`] 是后来新增的 CSS 规则,由于规范较新,Chrome 2021年之后才支持。 **其他值区别:** ```csharp justify-content: center; /* 居中对齐 */ justify-content: space-between; /* 两边留白 */ justify-content: space-around; /* 每个子元素左右间距都相同 */ justify-content: space-evenly; /* 每个留白的空间等分相同 */ ``` ![](https://cdn.res.knowhub.vip/c/2504/16/9d873afa.png?G1QAAMS22TiVp6Rh29gP%2fkNfQTUDElUElXrW6713n0b0%2fSGQkp%2fZx4rz4Q99rCB1g1cSiKIgeTY4i7q5JQWjOtjzngE%3d) `stretch` 也是看起来跟默认值没啥区别~~ **safe 与 unsafe** 按照 MDN 说法: `safe` 如果元素溢出对齐容器,则元素将按照对齐模式为 start 进行对齐。所期望的对齐将不会被实现。 `unsafe` 即使元素溢出对齐容器,也会实现所需的对齐方式。与 safe 不同,safe 会忽略所要求的对齐方式以防止溢出。 使用方法: ```csharp justify-content: safe center; justify-content: unsafe center; ``` 效果: ![](https://cdn.res.knowhub.vip/c/2504/16/034bec49.png?G1QAAMT0bJzotVBsox%2f6n3gkNAMSVQSVetbrvXefRvT9JpDon9nHsvPhD30so1QzqpJAEiKc54zKAcoFTgsrh5iC39MA) ### align-items 交叉轴对齐方式(单行) 定位对齐几种方式: ![](https://cdn.res.knowhub.vip/c/2504/16/38ee07e8.png?G1QAAOQ5d14KoED0nXZQm6mbNgMSVQSVetbrPWftG%2bD7g5FrfkbrM%2faHP7Q%2bA8QV3YCRBSuSJ0WnQmxWkijKRWac1wg%3d) 跟 justify-content 一样,几个 start 和 end 没找到有啥区别~~ 其他几个值: ![](https://cdn.res.knowhub.vip/c/2504/16/905311fb.png?G1UAAOQ5d14KIGD0nXZQm6mbNgMVaQSVetbrPWftG%2bD7g5ElP6P1GfvDL1qfAeqGXoGRFQUpkKFTITctiS4TFzekvEYA) 设置 `stretch` 会把未设置高度的元素拉伸撑满容器。 `safe` 和 `unsafe` 与 `justify-content` 一样 ### align-content 交叉轴对齐方式(多行) 与 justify-content 属性一样,只是对齐方式换成了垂直方向。 就不再一一列举了,直接看几个常用的属性: ![](https://cdn.res.knowhub.vip/c/2504/16/a4a99948.png?G1UAAMTsdJxI8kSj26hD2jvFHc1ARRpBpZ71es9Z%2byb6fgcjx2e0Pn1%2f%2bEXr00lr4XoRGMoZIUjhKgkK0yDJWM0AxDUc) ### gap 子元素间距 `gap` 用于设置子元素水平间距和垂直间距,可将任何 CSS 支持的单位值喂给它,比如:`10px`、`10%`、`10em`、`10rem`、`10vw`、`10vh`。 ```csharp gap: 20px; /* 等价于 gap: 20px 20px; */ gap: 50%; /* 等价于 gap: 50% 50%; 表示相对于容器大小的宽度50% 高度50% */ ``` ![](https://cdn.res.knowhub.vip/c/2504/16/91e03873.png?G1UAAOQ5d14KIEj0nXZQm6mbNgMVaQSVetbrPWftG%2bD7g5ElP6P1GfvDL1qfAeoV3YCRFQUpUEWnUtCNE6kJXkJkeY0A) ## 子元素 ### order 排列顺序 可使用 `order` 控制元素顺序: 值越小,越靠前,默认值是 0,可为负数。 ```csharp .box .item:nth-child(1) { order: 3; } .box .item:nth-child(2) { order: 1; } .box .item:nth-child(3) { order: -1; } ``` 显示效果: ![](https://cdn.res.knowhub.vip/c/2504/16/a8f9be28.png?G1UAAOQ8bZy413O2UYdrE0VCM1CRRlCpZ73ee%2fdpAN%2fvjKzxmX0sPx9%2b0cdySJbRCjByQkUIlNFIpErJgZIyk4nVuKcD) ### flex-grow 控制元素放大比例 默认值为 `0` 元素不会放大,可通过设置 `flex-grow` 控制放大系数,不可为负数。 其放大比例是所有子元素 `flex-grow` 值相加平分剩余空间,比如: 所有子元素都是 1,那就是所有子元素平分。 第一个子元素是 1,那就是第一个元素占剩余空间的 100%。 第一个子元素是 1,第二个子元素是 2,那么第一个子元素占 1 等份,第二个子元素占 2 等份。 ![](https://cdn.res.knowhub.vip/c/2504/16/4d9679b3.png?G1QAAMTXsx8n%2blTrt41u6F3ikNAMSFQRVOpZr%2ffefRrR9xuDxT%2bzj2Xnwx%2f6WEZaE2omBisEzoeEGqJwEbiQi2hEVL%2bnAQ%3d%3d) ### flex-shrink 控制元素缩小比例 默认值为 `1`,在元素溢出容器时,所有子元素都等比例缩小,可通过设置 `flex-shrink` 控制缩小系数,不可为负数,设置为 `0` 表示禁止元素缩放。 计算方式与 `flex-grow` 一致。 ![](https://cdn.res.knowhub.vip/c/2504/16/c3316eb5.png?G1MAAOTcVkxwP3i2iOF0Q2CDZkCiiqBSz3q956x9A3x%2fMLLmZ7Q%2bY3%2f4Q%2bszwLygV2BkQ0XSVNBJtJpookvEiTivEQ%3d%3d) ### flex-basis 控制元素大小 默认 `flex-basis` 控制元素宽度,`flex-direction: column` 则控制元素高度。 `flex-basis` 默认值 `auto`,表示元素大小由 `width` 或 `height` 控制,可食用所有 CSS 支持的单位值。 如果同时设置了 `width` 和 `flex-basis` ,flex-basis 优先级更高。 ![](https://cdn.res.knowhub.vip/c/2504/16/de95f070.png?G1UAAMTsdJxI8hKq26hD2jvFHc1ARRpBpZ71es9Z%2byb6fgdD4zNan74%2f%2fKL16WQ1cy0EhrEiBMlcJRnKhSAsKKJQjWs4) `content` 根据弹性项的内容自动调整大小。 `max-content` 元素内容"自然舒展"时的理想宽度。 `min-content` 元素内容"紧巴巴"排列时的最小宽度。 `fit-content` 设定包含块内容区域的最大可能尺寸,该尺寸受最小内容(min-content)和最大内容(max-content)值的约束,并根据当前元素的实际内容动态计算得出。 ### flex 简写属性,可同时包含 `flex-grow` 、 `flex-shrink` 、 `flex-basis`,用法: 完整写法顺序为 `flex: grow shrink basis;` 分别表示:放大比例,缩小比例,元素大小。 ```csharp flex: 2; /* 等价于 flex: 2 1 0; */ flex: 1; /* 等价于 flex: 1 1 0; */ flex: 10px; /* 等价于 flex: 1 1 10px; */ flex: 1 30px; /* 等价于 flex: 1 1 30px; */ flex: 2 2; /* 等价于 flex: 2 2 0; */ flex: 2 2 10%; /* 写全属性 */ ``` ### align-self 控制单个元素的对齐方式 `align-self` 可覆盖容器的 `align-items` 属性,其属性值与 align-items 相同: ![](https://cdn.res.knowhub.vip/c/2504/16/24c5d865.png?G1QAAOQ5d14KIEj0nXZQm6mbNgMSVQSVetbrPWftG%2bD7g5ElP6P1GfvDH1qfAeoV3YCRFQXJU0WnouYi6bKiQs6e1wg%3d) ## 总结 就目前来看 flex 布局比 grid 布局应用得更多,虽然 grid 是终极手段,但由于兼容性问题,反而是 flex 应用更广泛。 虽然 flex 规范出现的时间较早,但由于 CSS 版本不停迭代,目前也有一些较新的 `属性值`,如果要求兼容低版本浏览器,建议使用前先查阅相关兼容性文档。