32

CSS Flexbox 可视化手册

 5 years ago
source link: https://segmentfault.com/a/1190000018056228?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

翻译:疯狂的技术宅

原文: https://medium.com/swlh/css-f...

本文首发微信公众号:jingchengyideng

欢迎关注,每天都给你推送新鲜的前端技术文章

介绍

Flexbox是 Flexible Box Module (弹性盒模型)的缩写。 是一种可以轻松控制html元素之间的空间分布和对齐的布局模型。

Flexbox同一时间只能控制行或列中的一个维度。对于二维控制需要 CSS 网格布局。

bYjqYvr.png!web

首先给出如下模板:

<body>
  <div class="container">
    <div class="box box-1">1</div>
    <div class="box box-2">2</div>
    <div class="box box-3">3</div>
    <div class="box box-4">4</div>
    <div class="box box-5">5</div>
    <div class="box box-6">6</div>
    <div class="box box-7">7</div>
    <div class="box box-8">8</div>
    <div class="box box-9">9</div>
    <div class="box box-10">10</div>
  </div>
</body>

以上 div 的默认行为遵循普通的html文档流,将会从上到下、从左到右呈现,并采用整个 body 的宽度,因为其 display 属性默认为 block

VJZF7f2.png!web

弹性项目

display: flex 应用于 .container div 时,所有直接子div都变为 flex-items ,并获得新的行为

  • 它们将显示在同一行中,因为 flex-direction 默认为 row
  • 它们将会从左到右显示

RrU3IjI.png!web

  • 其中的项目不会自动伸展来适应整个宽度(主轴),为了做到这一点,它们会缩小。

AruMVvq.gif

  • 项目会被拉伸以适合交叉轴(在此示例中为高度)。 如果这些项目的高度不一致,它们将会伸展到最高的那个高度
  • flex-basis 默认为 auto (项目宽度将由其内容决定)
  • flex-wrap 默认为 nowrap (如果容器的宽度不足以适合这些项目,它们不会换行,而是会溢出)

出于可视化的目的,让我们拉伸容器使其占据整个高度。

弹性容器

display:flex 使容器扩展至整个可用宽度。 这点与 display:inline-flex 相反,它使容器缩小到内容的宽度。

jAJN7jr.png!web

弹性方向

一旦被声明为 flex 容器,就可以认为该元素具有两个轴:主轴与交叉轴。 主轴由 flex-direction 属性定义。 交叉轴垂直于前者。

flex-direction 属性有四个值: rowrow-reversecolumncolumn-reverse

其默认值为 row ,它从左到右水平设置主轴,交叉轴从上到下垂直截取。 类似地, column 值从顶部到底部垂直设置主轴,从左到右设置交叉轴。 这两个选项的相反属性使主轴反转180°。 交叉轴保持不变。

可以通过下图观察这些值的 flex-items 行为:

fqmiUjU.gif

Flex Wrap

当容器中的空间不足以容纳其中的弹性项目时,可以用 flex-wrap 来处理。

在默认情况下, flex-wrap 被设置为 nowrap ,这意味着如果容器不能适应在其内的行中原始宽度的项目,则这些项目将会缩小来进行适应。 如果它们因为某种原因无法收缩,则会溢出容器。

把项目宽度设置为300px, nowrap 选项会输出以下结果:

YFNbaaI.png!web

其中,每个项目都会缩小到大约 70px 来适合容器。

当属性被更新为 wrap 时,现在项目的宽度实际上是原始值300px。 当第一行不足以容纳300px时,则该项目将换行到新的一行,而不是溢出容器。 应该把其中的每一行都视为单独的弹性容器。 一个容器中的空间分布不会影响到与其相邻的其他容器。

naMnmqV.png!web

但是为什么弹性项目会占据整个屏幕高度呢? 在第一部分中,容器高度设置为 100vh ,因此可用空间被平均分为四行,来适合 300px 项目的需要。 如果我们没有设置 100vh ,容器的高度则会遵循项目内容的高度,如下图所示:

2yaMneE.png!web

另一个选项是 wrap-reverse ,它会反转交叉轴。 通过 flex-direction 属性从上到下设置, wrap-reverse 将其转换为从下到上。

vEjA3aJ.png!web

通过使用 flex-direction:column 反转主轴,不适应的元素会被换到另一列,剩余空间被均匀分割。

nAvm2iU.png!web

wrap-reverse 选项会沿着列方向将交叉轴从右向左反转,产生以下输出:

m2Q3Yf6.png!web

由于flexbox是单维度布局,所以在进行反转时,项目从下到上进行排列(对于行方向),但保持左右结构,只改变了交叉轴。

弹性流

flex-directionflex-wrap 可以在一个属性当中声明: flex-flow:[direction][wrap]

.flex-container {
  flex-flow : column wrap;
}

项目之间的缝隙

让我们回到row/wrap。 可以通过设置项目的 width:33.3333% 来填充整个容器:

uaUBVva.png!web

但是如果你希望在子div 之间有一个间隙,它们就不会按照你想的那样换行:

FZvaYza.png!web

这个小麻烦这可以通过 CSS 函数 calc() 来解决:

.flex-item {
  width: calc(33.33333% - 40px);
  margin: 20px;
}

Ibyyye2.png!web

为了消除容器边缘的空间,可以在容器上使用负边距:

.flex-container {
  margin: -20px;
}

YjmuY3Y.png!web

排序

order 属性允许更改出现的可视排序项目。排序被分配给组。 默认情况下所有的弹性项目都设置为 order: 0 ,这意味着所有项目都属于同一组,并且它们将按照原始顺序定位。 在两个或多个组的情况下,组会相对于它们的整数值进行排序。

在下面的例子中,有三个 ordinal groups-1 , 01 ,按此顺序进行排列。

.box-3 { order: 1; }
.box-7 { order: 1; }
.box-8 { order: -1; }

VR7JnyJ.png!web

此属性可视地重新分配项目,但在交互时保持其原始源位置,例如使用Tab键遍历它们。 如果物品订购对可访问性有影响,则可以考虑这一点。 flex-direction 也是如此。

B32emin.gif

对齐

eyQRJjj.png!web

(此图反复上传总是出错,请大家移步原文查看)

在Flexbox中,沿着轴的项目对齐和空间分布可以受到四个属性的控制:

justify-content
align-items
align-self
align-content

justify-content

mmQraa6.png!web

适用于容器, justify-content 处理项目在主轴上的对齐方式。六个最常用的选项包括: flex-startflex-endcenterspace-aroundspace-betweenspace-evenlyflex-start 是默认值。.

align-items

MVjMBn7.png!web

也适用于容器, align-items 属性处理交叉轴方向上的对齐。它的默认值是 stretch 其它的选项是 flex-startflex-endcenterbaseline

stretch 选项使所有项目伸展到容器高度(如果设置)或最高项目的高度[5]。 第一张图片显示容器高度设置为 100vh ,未设置第二个高度。

align-content

jiqy6v7.png!web

这是作用在 flex 容器的四个属性中的最后一个, align-content 在交叉轴中的弹性线之间分配空格。 作为后者,它的初始值是 stretchjustify-content ,它接受以下选项: flex-start , flex-end , center , space-around , space-between , space-evenly

align-self

67JJRz2.png!web

align-items 属性实际上通过在容器内的所有 flex 项目上设置 align-self 来实现。 通过单独设置 align-self ,可以覆盖全局值。 它接受与 align-items 和'auto'相同的值[5]。

auto 选项通过 align-itemsalign-self 重置为容器全局定义的值。

调整 Flexbox 的大小

项目的尺寸和伸展性可以通过三种属性来控制: flex-growflex-shrinkflex-basis 。 这三个都作用于主轴。

flex-grow
flex-shrink
flex-basis

flex-grow

由此属性设置的 flex grow factor (弹性增长因子)用来处理项目大小相对于彼此的比率。

默认值为 0 ,这意味着如果还有可用空间,就把它放在最后一个项目之后。

emIZJnY.png!web

在上面的例子中, direction 被设置为 row ,每个弹性项目的 width 被设置为 60px 。 由于容器宽是 980px ,所以剩余的可用空间为 680px 。 这个空间被称为 positive free space (正自由空间)。

如果将 flex-grow 设置为 1 ,正可用空间量会在弹性项目之间平均分配。 每个项目的宽度将会增加 136px ,总宽度为 196px

z22YbyI.png!web

通过将 flex-grow: 2 应用到第三个项目,它会得到比其它项目多出两倍的可用正自由空间,即 286px ,其他项目仍为 173px

下图显示了把项目的 flex-grow 属性值设置为其内容对应的数字时的情形。

u2I3aau.png!web

flex-shrink

当没有足够的可用空间来容纳所有容器时,用 flex-shrink 处理项目大小。 它通过缩小这些项目来划分它们之间的 negative free space (负自由空间)。

下图显示的是宽度为 980px 的容器,它容纳了5个宽度为 300px 的物品。 由于没有空间容纳所需的总宽度 1500px ,所以默认的 flex shrink factor (弹性收缩系数)的值为 1 ,这样会使每个项目的宽度均匀缩小到 196px

JFNRzi7.png!web

通过将第三项的比率设置为 2 ,它缩小为其余项目大小的二分之一。

qMfqquM.png!web

本节的最后一张图显示了将每个项目的内容值对应的数字设定为 flex-shrink 的值时的情形。

flex-basis

flex-basis 是在实际设置可用空间之前,检查每个项目本来应具有的大小的属性。 默认值为 auto ,项宽度由 width 属性显式设置,或者取其内容宽度。 它也接受像素值。

下面的动图显示了一个 800px 宽的容器和五个设置为 flex-basis:160px 的弹性项目。 这告诉浏览器:如果在理想状态下,有足够的空间来放置所有的项目,就遵循它们的 160px 宽度,并且没有正/负可用空间;如果没有足够的空间的话,那么 flex-shrink 默认为 1 ,所有项目均匀收缩; 如果有额外的空间, flex-grow 默认为 0 ,并且剩余的空间放在最后一个项目之后。

bYFJRvY.gif

下一个动图展示了把项目1设置为 flex-shrink:10 ,项目4设置为 flex-grow:10 。对于负自由空间,项目1的宽度减少10倍。 对于正空闲空间,第4项的宽度是其他空间的10倍。

JBJbueq.gif

flex-basis 也接受值 content ,此时无论其宽度是否被设置,计算自由空间时所考虑的宽度依据是项目中的内容。

flex

flex 属性是按顺序排列的 flex-growflex-shrinkflex-basis 的简写,它接受以下预定义值:

  • initial :重置为 flexbox 的默认值,等同于 flex: 0 1 auto
  • auto :flex-items能够根据需要增长/缩小,等同于 flex: 1 1 auto
  • none :固定项目,等同于 flex: 0 0 auto
  • flex: 1 :flex-items 具有伸缩的能力, flex-basis 设置为零,等同于 flex: 1 1 0

Autoprefixer

对于跨浏览器的兼容性问题,设置具有具有必要前缀的属性是非常重要的,以确保能够支持所有浏览器。

手动自动为每个属性添加前缀可能是一项非常繁琐的任务,也使样式很难维护。使用 Gulp 能够替你自动执行这些任务。

为了能够使用Gulp,我们必须将它作为依赖添加到项目当中。 这项工作是在 package.json 文件中完成的,它负责跟踪项目依赖及其版本。 在终端中输入下列命令来创建文件:

nmp init

系统将提示你输入项目信息,可以一直按回车键直到完成。 输出的文件内容将是这样的:

{
  "name": "project-name",
  "version": "1.0.0",
  "description": "Project description",
  "main": "index.js",
  "scripts": { "test": "echo \"Error: no test specified\" && exit 1" },
  "author": "Author Name",
  "license": "ISC"
}

全局安装gulp:

npm install gulp -g

安装 gulp 和 gulp-autoprefixer 作为项目依赖项:

npm install gulp --save-dev
npm install gulp-autoprefixer --save-dev

它们将会出现在 package.json 文件中的 devDependencies 下。

创建一个gulpfile.js文件:

touch gulpfile.js

添加以下内容:

// gulpfile.js

var gulp = require('gulp');
var autoprefixer = require('gulp-autoprefixer');
var options = { browsers: ['last 2 versions'], cascade: false };

gulp.task('styles', function() {
  return gulp.src('./styles.css')
             .pipe(autoprefixer(options))
             .pipe(gulp.dest('build'));
});

gulp 会从 styles.css 中提取内容并通过 gulp-autoprefixer 传递它。 处理结果会保存在 build 文件夹下。

参考

  1. What the Flexbox Course
  2. Basic concepts of flexbox — 25/03/2018
  3. Mastering Wrapping of Flex Items — 26/03/2018
  4. Ordering Flex Items — 26/03/2018
  5. Aligning Items in a Flex Container — 26/03/2018
  6. StackOverflow — 27/03/2018
  7. Controlling Ratios of Flex Items Along the Main Axis — 28/03/2018
  8. Gulp
  9. Gulp Autoprefixer

本文首发微信公众号:jingchengyideng

YB3iQbY.jpg!web

欢迎扫描二维码关注公众号,每天都给你推送新鲜的前端技术文章


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK