花了几个小时整合的"A Complete Guide to Flexbox"最新版本,介绍了flexbox的所有属性,外带几个实用的例子。

传统布局、Flexbox

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

Flex布局,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能。

Flex是Flexible Box的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为Flex布局。

背景

Flexbox提供了一种有效的方式来对容器内的元素布局、对齐、分配空间。能在不知道子元素大小或动态变化情况下分配好各个子元素间的间隙。(正如其名flex

Flex布局的主要思想是给父元素动态调整子元素的高度宽度的能力,使各元素适应可用布局空间。(能够适应不同的设备和不同大小的屏幕),一个flex容器可以放大子元素来填充可用空间,也可以缩小子元素来防止溢出。

最重要的是,与常规布局相比(垂直的块布局和水平的内联布局)Flexbox布局是方向未知的。传统布局对大型复杂应用的灵活性不是很好(特别是在改变方向,大小,伸展,收缩方面)

注:Flexbox布局适合应用组件或小规模的布局。Grid布局适合大规模的布局。

基本概念

Flex布局是一个完整的模块而不是一个单独的属性,它包括了完整的一套属性。其中有的属性是设置在容器(container,也可以叫做父元素,称为flex container)上,有的则是设置在容器的项目上(item,也可以叫做子元素,称为flex items)上。

如果我们可以说传统布局是建立在块状元素垂直流和行内元素水平流上的,那么flex布局就是建立在”flex-flow方向”上的,通过下图解释flex布局的主要思想。

在flex布局中,子元素要么按照主轴也就是main axis(从main-start到main-end)排布,要么按照交叉轴,也就是cross axis(从cross-start到cross-end)排布。

  • main axis: Flex 父元素的主轴是指子元素布局的主要方向轴,注意主轴不一定是水平的,它由属性flex-direction来确定主轴是水平还是垂直的。
  • main-start|main-end: 分别表示主轴的开始和结束,子元素在父元素中会沿着主轴从main-start到main-end排布。
  • main size: 子元素在主轴方向上的大小。包括长度和宽度。
  • cross axis: 交叉轴,与主轴垂直。
  • cross-start|cross-end: 分别表示交叉轴的开始和结束。子元素在交叉轴的排布从cross-start开始到cross-end。
  • cross size: 子元素在交叉轴方向上的大小。包括长度和宽度。

属性介绍

.container 是设置在容器上的,.item 是设置在子元素上的。

display 设置布局容器

.container {
display: flex; /* or inline-flex */
}

用来定义父元素是一个flex布局容器。如果设置为flex则父元素为块状元素,设置为inline-flex父元素呈现为行内元素。它为它所有的直接子元素启用了一个伸缩上下文。

flex-direction 主轴排列方向

.container {
flex-direction: row | row-reverse | column | column-reverse;
}

flex-direction定义flex布局的主轴方向。flex布局是单方向布局,子元素主要沿着水平行或者垂直列布局。

  • row(默认):在LTR排版方式下从左到右; RTL从右到左
  • row-reverse:LTR 从右到左; RTL 从左到右
  • column:从上到下
  • column-reverse:从下到上

flex-warp 是否换行

.container {
flex-wrap: nowrap | wrap | wrap-reverse;
}

默认情况下,flex布局中父元素会把子元素尽可能地排在同一行,通过设置flex-wrap来决定是否允许子元素这行排列。

  • nowrap(默认值): 不折行,所有的子元素会排在一行。
  • wrap: 折行,子元素会从上到下根据需求折成多行。
  • wrap-reverse: 折行,子元素会从下到上根据需求折成多行。

flex-flow 缩写形式

.container {
flex-flow: row nowrap; /* column wrap */
}

flex-flow是flex-direction和flex-wrap属性的缩写形式。默认值是row nowrap

justify-content 内容对齐、主轴

.container {
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly | start | end | left | right ... + safe | unsafe;
}

justify-content属性定义了子元素沿主轴方向的对齐方式,当子元素大小最大时(如长度最大化不可再增加),分配主轴上的剩余空间(如宽度)。也可以当子元素超出主轴的时候用来控制子元素的对齐方式。

  • flex-start (默认值):项目位于容器的开头。
  • flex-end:项目位于容器的结尾。
  • center:项目沿着线居中
  • space-between:物品均匀分布在线上; 第一项是在起始行,最后一项是在结束行
  • space-around:项目均匀分布在线条周围,空间相等。请注意,视觉上空间不相等,因为所有项目在两侧都有相等的空间。第一个项目将在容器边缘上有一个空间单位,但在下一个项目之间有两个单位的空间,因为下一个项目有自己适用的间距。
  • space-evenly:项目是分布的,以便任何两个项目之间的间距(和边缘的空间)相等。

align-items 单行元素对齐、交叉轴

.container {
align-items: stretch | flex-start | flex-end | center | baseline | first baseline | last baseline | start | end | self-start | self-end + ... safe | unsafe;
}

align-items定义了所在行的子元素在交叉轴方向的对齐方向。可以将其视为justify-content竖轴的版本(垂直于主轴)。

  • stretch(默认值): 拉伸子元素使之填充整个父元素。(遵守min-width,max-width

  • flex-start / start / self-start: 按照交叉轴的起点对齐。

  • flex-end / end / self-end: 按照交叉轴的终点对齐。

  • center: 沿交叉轴方向居中。

  • baseline: 按照项目的第一行文字的基线对齐。

align-content 各行对齐、交叉轴

.container {
align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch | start | end | baseline | first baseline | last baseline + ... safe | unsafe;
}

align-content是当父元素所包含的行在交叉轴方向有空余部分时如何分配空间。与justify-content在主轴上如何对齐子元素很相似。

注意:当只有一行或flex-wrap为默认值的时候,该属性并不起作用。

  • stretch (默认值):线条拉伸以占用剩余空间

  • flex-start:元素位于容器的开头

  • flex-end:元素位于容器的末尾

  • center:元素位于容器的中心

  • space-between:线条均匀分布; 第一行是容器的开头,而最后一行是在容器的最后

  • space-around:线条均匀分布,每条线周围的空间相等

gap 子元素行列间距

.container {
display: flex;
...
gap: 10px;
gap: 10px 20px; /* row-gap column gap */
row-gap: 10px;
column-gap: 20px;
}

gap 属性明确控制子元素之间的空间。(边缘与子元素之间没效果)

order 子元素排列顺序

.item {
order: 5; /* default is 0 */
}

默认情况下,子元素按照代码书写的先后顺序布局,但order属性可以更改子元素出现的顺序。

注:order值一样的子元素会按照默认按照代码书写的先后顺序布局。

flex-grow 子元素扩展比例

.item {
flex-grow: 4; /* default 0 */
}

flex-grow规定在空间允许的情况下,子元素如何按照比例分配可用剩余空间。如果所有的子元素的属性都设定为1,则父元素中的剩余空间会等分给所有子元素。如果其中某个子元素的flex-grow设定为2,则在分配剩余空间时该子元素将获得其他元素二倍的空间(至少会尽力获得)。

注:flex-grow不接受负值。

flex-shrink 子元素缩小比例

.item {
flex-shrink: 3; /* default 1 */
}

与flex-grow属性类似,flex-shrink定义了空间不足时项目的缩小比例。

注:flex-shrink不接受负值。

flex-basis 子元素理想大小

.item {
flex-basis: | auto; /* default auto */
}

flex-basis表示在flex items被放入flex容器之前的大小,也就是items的理想或者假设大小,但是并不是其真实大小,其真实大小取决于flex容器的宽度,如min-width,max-width等。

flex-basis:auto指子元素基本尺寸根据其自身的尺寸决定。而这个自身尺寸与下面这几个方面有关

  • box-sizing 盒模型(flex-basis的尺寸是作用在content-box上的)
  • width/min-width/max-width等
  • content内容(min-content)
  • flex-grow产生的额外空间

flex-basis设置特定值时,同时设定width,最小内容宽度较大的时候,会按照了最小内容宽度显示,而不是被width限制死尺寸。flex-basis优先级是比width高

  • width:100px + flex-basis:auto = 元素自身100px
  • content + flex-basis:100px = max(content, flex-basis) = 大于等于100px
  • content + width:100px + flex-basis:100px = content + flex-basis:100px = max(content, flex-basis) = 大于等于100px

width只是flex-basis为auto时候间接生效,其余时候使用优先级更高的flex-basis属性值;

/* 根据flex子项的内容自动调整大小 */
flex-basis: content; 尺寸根据内容决定 /* 内部尺寸关键字 */
flex-basis: fill;
flex-basis: max-content; 最大内容宽度。
flex-basis: min-content; 最小内容宽度。
flex-basis: fit-content;

注:由于浏览器兼容性的问题,flex-basis数值属性值和width数值属性值不要同时使用。

flex 缩写形式

.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}

flex是flex-grow、flex-shrink、flex-basis三个属性的缩写。其中第二个和第三个参数(flex-grow,flex-basis)是可选的。默认值为0 1 auto。

推荐使用缩写形式而不是单独地设置每一个属性,缩写形式中会智能地计算出相关值。

align-self 单个元素对齐、交叉轴

.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

通过设置某个子元素的align-self属性,可以覆盖align-items所设置的对齐方式。

注:float、clear、vertical-align 对flex子元素无影响。

例子

水平垂直居中

.parent {
display: flex;
height: 300px; /* Or whatever */
} .child {
width: 100px; /* Or whatever */
height: 100px; /* Or whatever */
margin: auto; /* Magic! */
}

弹性容器中设置 marginauto,可以吸收额外的空间。使元素在两个轴上完美居中。

响应式初体验

考虑有6个子元素,有固定的大小,希望能够在改变浏览器宽度的时候仍然可以在水平轴上完美地显示。

<ul class="flex-container">
<li class="flex-item">1</li>
<li class="flex-item">2</li>
<li class="flex-item">3</li>
<li class="flex-item">4</li>
<li class="flex-item">5</li>
<li class="flex-item">6</li>
</ul>
.flex-container {
/* 设置flex容器 */
display: flex; /* Then we define the flow direction
and if we allow the items to wrap
* Remember this is the same as:
* flex-direction: row;
* flex-wrap: wrap;
*/
flex-flow: row wrap; /* Then we define how is distributed the remaining space */
justify-content: space-around; padding: 0;
margin: 0;
list-style: none;
} .flex-item {
background: tomato;
padding: 5px;
width: 200px;
height: 150px;
margin-top: 10px;
line-height: 150px;
color: white;
font-weight: bold;
font-size: 3em;
text-align: center;
}

https://codepen.io/css-tricks/embed/EKEYob

响应式导航栏

一个向右对齐的导航栏在网页的最上端,我们希望它在中屏上显示时为居中,在小屏上以单列显示。

<ul class="navigation">
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Products</a></li>
<li><a href="#">Contact</a></li>
</ul>
.navigation {
display: flex;
flex-flow: row wrap;
justify-content: flex-end; list-style: none;
margin: 0;
background: deepskyblue;
} .navigation a {
text-decoration: none;
display: block; /* 变成块级元素撑起整个navigation */
padding: 1em;
color: white;
} .navigation a:hover {
background: #1565C0;
} /* 往中屏切换 */
@media all and (max-width: 800px) {
.navigation {
justify-content: space-around;
}
} /* 往小屏切换 */
@media all and (max-width: 600px) {
.navigation {
flex-flow: column wrap;
padding: 0;
}
.navigation a {
text-align: center;
padding: 10px;
border-top: 1px solid rgba(255, 255, 255,0.3);
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
.navigation li:last-of-type a {
border-bottom: none;
}
}

https://codepen.io/css-tricks/embed/YqaKYR

网页结构布局

<div class="wrapper">
<header class="header">Header</header>
<article class="main">
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
</article>
<aside class="aside aside-1">Aside 1</aside>
<aside class="aside aside-2">Aside 2</aside>
<footer class="footer">Footer</footer>
</div>
.wrapper {
display: flex;
flex-flow: row wrap;
font-weight: bold;
text-align: center;
} .wrapper > * {
padding: 10px;
flex: 1 100%;
} .header {
background: tomato;
} .footer {
background: lightgreen;
} .main {
text-align: left;
background: deepskyblue;
} .aside-1 {
background: gold;
} .aside-2 {
background: hotpink;
} @media all and (min-width: 600px) {
.aside { flex: 1 0 0; }
} @media all and (min-width: 800px) {
.main { flex: 3 0px; }
.aside-1 { order: 1; }
.main { order: 2; }
.aside-2 { order: 3; }
.footer { order: 4; }
} body {
padding: 2em;
}

https://codepen.io/anon/embed/vWEMWw

更美观的标题

使用绝对定位的方式将文本放置在右边,因为不在文档流中,无法智能地决定何时换行。

使用float,在换行时不会有很好的左对齐效果。

使用表格,不会进行换行。

<h3 class="title abs-title">
<span class="title-main">Main Title Here</span>
<span class="title-note">This is absolutely positioned.</span>
</h3> <h3 class="title float-title">
<span class="title-main">Main Title Here</span>
<span class="title-note">This subtitle is floated.</span>
</h3> <h3 class="title table-title">
<span class="title-main">Main Title Here</span>
<span class="title-note">I am a table cell.</span>
</h3> <h3 class="title flex-title">
<span class="title-main">Main Title Here</span>
<span class="title-note">This is a good look, right here.</span>
</h3>
body {
padding: 100px;
font-size: 21px;
} .title {
border-bottom: 1px solid #ccc;
max-width: 500px;
margin: 40px auto;
}
.title-note {
font-size: 60%;
color: #999;
} .abs-title {
position: relative;
.title-note {
position: absolute;
bottom: 2px;
right: 0;
}
} .float-title {
.title-note {
float: right;
position: relative;
top: 12px;
}
} .table-title {
display: table;
width: 100%;
> span {
display: table-cell;
white-space: nowrap;
}
.title-main {
width: 99%;
}
} .flex-title {
display: flex;
align-items: flex-end;
flex-wrap: wrap;
> span {
white-space: nowrap; /* 强制在同一行内显示所有文本 */
}
.title-main {
flex-grow: 1; /* 让标题利用多余空间进行扩展,从而使副标题紧靠右边 */
}
}

https://codepen.io/chriscoyier/embed/doVXLV

使用海报

下载:https://xiaonenglife.oss-cn-hangzhou.aliyuncs.com/static/pic/2022/09/20220916125123_css-flexbox-poster.png

参考资料

Flex 布局语法教程 | 菜鸟教程

A Complete Guide to Flexbox | CSS-Tricks - CSS-Tricks

flex-basis_奔跑吧、GZB的博客

我的Vue之旅、01 深入Flexbox布局完全指南的更多相关文章

  1. 我的Vue之旅、04 CSS媒体查询完全指南(Media Quires)

    什么是SCSS Sass: Sass Basics (sass-lang.com) SCSS 是 CSS 的预处理器,它比常规 CSS 更强大. 可以嵌套选择器,更好维护.管理代码. 可以将各种值存储 ...

  2. 我的Vue之旅 06 超详细、仿 itch.io 主页设计(Mobile)

    第二期 · 使用 Vue 3.1 + TypeScript + Router + Tailwind.css 仿 itch.io 平台主页. 我的主题 HapiGames 是仿 itch.io 的 in ...

  3. flexbox布局神器

    前言 2009年,W3C提出了一种新的方案----Flexbox布局(弹性布局),可以简便.完整.响应式地实现各种页面布局.Flex布局模型不同于块和内联模型布局,块和内联模型的布局计算依赖于块和内联 ...

  4. 【前端攻略】最全面的水平垂直居中方案与flexbox布局

    最近又遇到许多垂直居中的问题,这是Css布局当中十分常见的一个问题,诸如定长定宽或不定长宽的各类容器的垂直居中,其实都有很多种解决方案.而且在Css3的flexbox出现之后,解决各类居中问题变得更加 ...

  5. Flexbox布局(转)

    Flexbox布局( Flexible Box 或CSS3 弹性布局),是CSS3中的一种新的布局模式,是可以自动调整子元素的高和宽,来很好的填充任何不同屏幕大小的显示设备中的可用显示空间,收缩内容防 ...

  6. 互动教程,让你5分钟掌握 Flexbox 布局模式

    Flexbox 布局模块目前是 W3C 候选标准,旨在提供一个更有效的方式进行布局,对齐和为容器里的项目分配空间,即使它们的大小是未知的或者动态的.这里分享一个基于 Knockout.js 构建的互动 ...

  7. React Native 开发之 (05) flexbox布局

    一  flexbox布局 1 flex布局 flexbox是ReactNative 应用开发中必不可少的内容,也是最常用的内容. 传统的页面布局是基于盒子模型,依赖定位属性,流动属性和显示属性来解决. ...

  8. flexbox布局的兼容性

    http://ayqy.net/blog/flexbox布局的兼容性/ 写在前面 flex布局早在2009年就有了,而现在是2015年6月8日,使用最新的flex语法会发现支持程度并不好,即使是在“高 ...

  9. CSS3弹性盒模型flexbox布局基础版

    原文链接:http://caibaojian.com/using-flexbox.html 最近看了社区上的一些关于flexbox的很多文章,感觉都没有我这篇文章实在,最重要的兼容性问题好多人都没有提 ...

随机推荐

  1. colab运行.py文件

    !python split_data.py

  2. NC200190 矩阵消除游戏

    NC200190 矩阵消除游戏 题目 题目描述 牛妹在玩一个名为矩阵消除的游戏,矩阵的大小是 \({n}\) 行 \({m}\) 列,第 \({i}\) 行第 \({j}\) 列的单元格的权值为 \( ...

  3. nw.js的cookie操作

    在实战中,我遇到nw.js cookie一个奇怪的现象. 当我写入cookie(非httponly)后,关闭nw.js.然后再打开nw.js发现cookie没有写入成功.经过摸索,发现 nw.js的c ...

  4. Tapdata 携手精诚瑞宝,共拓 Real Time DaaS 蓝海市场

      2021年10月22日,深圳钛铂数据有限公司「Tapdata」 与精诚瑞宝计算机系统有限公司「精诚瑞宝」战略合作签约仪式在深圳举行,Tapdata 创始人唐建法先生与精诚瑞宝副总经理余灿雄先生签署 ...

  5. python 生成Windows快捷方式

    此处以虚拟机镜像快捷方式为例 link_filepath:快捷方式的生成路径 win32_cmd:需要执行的应用程序 arg_str:exe的参数 快捷方式的目标:由win32_cmd + arg_s ...

  6. 【洛谷P1754 球迷购票问题】题解

    传送门 卡特兰数经典 \(\texttt{AB}\) 分拆问题. 分析: 题意相当于排列 \(n\) 个 \(\texttt A\) 和 \(n\) 个 \(\texttt B\),使得相邻 \(\t ...

  7. PHP正则替换函数收集

    preg_replace() $msg = preg_replace("/<style>.+<\/style>/is", "", $ms ...

  8. 快速体验Spring Boot了解使用、运行和打包 | SpringBoot 2.7.2学习系列

    SpringBoot 2.7.2 学习系列,本节内容快速体验Spring Boot,带大家了解它的基本使用.运行和打包. Spring Boot 基于 Spring 框架,底层离不开 IoC.AoP ...

  9. Blazor和Vue对比学习(进阶2.2.3):状态管理之状态共享,Blazor的依赖注入和第三方库Fluxor

    Blazor没有提供状态共享的方案,虽然依赖注入可以实现一个全局对象,这个对象可以拥有状态.计算属性.方法等特征,但并不具备响应式.比如,组件A和组件B,都注入了这个全局对象,并引用了全局对象上的数据 ...

  10. Java开发学习(二十三)----SpringMVC入门案例、工作流程解析及设置bean加载控制

    一.SpringMVC概述 SpringMVC是隶属于Spring框架的一部分,主要是用来进行Web开发,是对Servlet进行了封装.SpringMVC是处于Web层的框架,所以其主要的作用就是用来 ...