首页 前端知识 【学习CSS4】详解Flexbox

【学习CSS4】详解Flexbox

2024-09-01 23:09:23 前端知识 前端哥 594 314 我要收藏

曾经,我天真地认为,浏览过即等于掌握;然而,职场多年的洗礼后,我才深刻领悟到这一认知的浅薄。那些一闪而过的知识碎片,如细沙般从指缝滑落,待到真正需要之时,却寻觅无踪,宛如海市蜃楼,令人怅然若失。

形成了时刻笔记的习性,就像拥有了一个忠实的旅伴,在漫漫人生路上,它记录下每一次心跳,每一缕微笑,不让任何美好稍纵即逝。这是一种对生命的热爱,对细节的关注,让平淡生活因记录而精彩,因回忆而丰满。

废话结束,干货来了!

Flexbox 是一种非常强大的布局模式。当我们真正了解它是如何工作的时,我们可以构建自动响应的动态布局,并根据需要重新排列。

一、先看要实现的效果

 不废话,直接上干货

下面是相关的css

form {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 16px;
}
.name {
  flex-grow: 1;
  flex-basis: 160px;
}
.email {
  flex-grow: 3;
  flex-basis: 200px;
}
button {
  flex-grow: 1;
  flex-basis: 80px;
}

完整的例子

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="renderer" content="webkit" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
    />
    <title>详解Flexbox布局</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      .flex1 {
        padding: 10px;
        background: #1a1b1b;
      }
      form {
        display: flex;
        align-items: flex-end;
        flex-wrap: wrap;
        gap: 16px;
        padding: 8px;
        border: 1px solid #ccc;
        border-radius: 5px;
        color: #fff;
        width: 600px;
        margin: 0 auto;
      }
      .name {
        flex-grow: 1;
        flex-basis: 160px;
      }
      .email {
        flex-grow: 3;
        flex-basis: 200px;
      }
      button {
        flex-grow: 1;
        flex-basis: 80px;
      }
      input {
        width: 100%;
      }
    </style>
  </head>
  <body>
    <div class="flex1">
      <div style="color: #fff;width: 600px;margin: 0 auto;">
        <div>
          当前form的宽度:<span id="rangeWidth">600</span>
        </div>
        <input type="range" min="200" max="600" value="600" class="slider" id="myRange">
      </div>
      <form id="demo">
        <label class="name" for="name">
          姓名:<input type="text" id="name" />
        </label>
        <label class="email" for="email">
          邮箱:<input type="text" id="email" />
        </label>
        <button>提交</button>
      </form>
    </div>

    <script>
      window.onload = function () {
        const slider = document.getElementById('myRange');
        const output = document.getElementById('demo');
        const rangeWidth = document.getElementById('rangeWidth');

        slider.oninput = function() {
          output.style.width = this.value + 'px';
          rangeWidth.innerHTML = this.value;
        }
      }
    </script>
  </body>
</html>

我记得以前遇到这样的需求时,我完全感到困惑。当我学习了Flexbox 的基础知识后,这绝对是魔法 ,太神奇了!

在接下来的文中,我将继续分享详细的 Flexbox 知识。我们会通过每一个属性来学习 Flexbox 是如何工作的。无论你是CSS的初学者,还是已经使用Flexbox多年的人,我敢打赌你会学到很多东西!

让我们开始吧!

二、Flexbox 简介

CSS由许多不同的布局算法组成,官方称为“布局模式”。每种布局模式都是CSS中自己的子语言。默认的布局模式是 Flow 布局,但我们可以通过更改父容器上的display为 Flexbox。

当我们将 display 设置为 flex 时,我们创建了一个“flex formatting context”。这意味着,默认情况下,所有子项都将根据 Flexbox 布局算法进行定位。

每种布局算法都旨在解决特定问题。默认的“流”布局旨在创建流文档;它本质上是Microsoft Word布局算法。标题和段落作为块垂直堆叠,而文本、链接和图像等内容则不显眼地位于这些块中。

那么,Flexbox解决了什么问题呢?Flexbox 就是将一组项目排列成一行或一列,并让我们对这些项目的分布和对齐进行精准的控制。顾名思义,Flexbox 是关于灵活性的。我们可以控制内容是增长还是缩小,额外空间的分配方式等等。

你可能想知道:既然 CSS Grid 在现代浏览器中得到了很好的支持,那么 Flexbox 不是已经过时了吗?
CSS Grid 是一种很棒的布局模式,但它解决的问题与 Flexbox 不同。我们应该学习这两种布局模式,并使用正确的工具来完成这项工作。
Flexbox 在动态、流畅的 UI 中以垂直或水平列表排列项目时仍然占据主导地位。我们将在本文中看到一个示例,这是使用 CSS Grid 无法轻松完成的。

作为一个对 CSS Grid 和 Flexbox 都感到满意的人,我仍然发现自己经常接触 Flexbox!

三、Flex direction 布局方向

如上所述,Flexbox 就是控制一行或一列中元素的分布。默认情况下,项将并排堆叠成一行,但我们可以控制是行还是列显示。

flex-direction: row ,主轴从左到右水平延伸,块内的子项从左到右排列。

flex-direction: column ,主轴从上到下垂直运行,块内的子项从上到下排列。

先看效果:

在 Flexbox 中,一切都基于主轴。该算法不关心垂直/水平,甚至不关心行/列。所有规则都是围绕这个主轴和垂直运行的十字轴构建的。

当我们学习了 Flexbox 的规则时,我们可以从水平布局无缝切换到垂直布局。所有规则都会自动适应。此功能是 Flexbox 布局模式所独有的。

下图是这些规则的快速可视化效果:

在 Flexbox 中,我们决定主轴是水平运行还是垂直运行。这是所有 Flexbox 计算都与此挂钩的根。

四、Flex direction 对齐方式

我们可以使用属性 justify-content 更改子项沿主轴的分布布局方式。

当涉及到主轴时,我们通常不会从对齐单个子项的角度来考虑。相反,这完全与组的分布有关。

我们可以将所有项目集中在特定位置(有 flex-start 、 center 和 flex-end ),或者我们可以将它们分开(带有 space-between 、 space-around 和 space-evenly )。

先看下图(gif录制软件略有瑕疵):

对于十字轴,垂直方向,情况略有不同。我们使用该属性align-items

如图:

是不是挺有趣的,在align-items 中,我们有一些与 justify-content 相同的选项,但没有完全重叠,如下图。 

为什么他们不共享相同的选项?我们很快就会解开这个谜团,首先,我先分享另一个对齐属性: align-self 。

与 align-items 和justify-content不同 , align-self ,它应用于子元素,而不是容器。它允许我们更改特定子项沿十字轴的对齐方式,请看下图:

align-self 具有与 align-items 相同的所有值。事实上,它们改变了完全相同的事情。 align-items 是句法糖,一种方便的速记,可以自动一次在所有孩子上设置对齐方式。

没有 justify-self 。要理解为什么不,我们需要更深入地研究 Flexbox 算法。

五、Content vs items

根据我目前所了解的,Flexbox可能看起来相当随意。为什么是justify-contentalign-items,而不是justify-items,或者align-content?

就此而言,为什么有一个align-self,但没有justify-self??

这些问题触及了Flexbox最重要也是最容易被误解的地方。为了更好的理解,我用一个比喻。

在Flexbox中,项目沿主轴分布。默认情况下,它们很好地并排排列在一起。我们可以画一条水平直线穿过全部的孩子,这像不像一个烤肉串?如下图

然而横轴是不同的。一条直的垂直线只会和一个孩子相交。

这不太像烤肉串,而更像一群混合的香肠?看图:

这里有一个显著的不同。有了混合的香肠,每个项目都可以沿着它的签子移动而不干涉其他项目 

相比之下,我们沿着主轴移动每个兄弟姐妹,每个都不可以沿着它的签子移动,否则会撞到它的兄弟姐妹! 

这就是主轴/横轴之间的根本区别。当我们通过轴对齐时,每一项都可以为所欲为。在这里我们只能考虑如何分配每一项。

这就是为什么没有 justify-self.这对于中间的部分来说意味着什么justify-self: flex-start?那里已经有另一块了!

考虑到所有这些情况,让我们给我们一直在谈论的4个术语下一个正确的定义:

  • justify—沿主坐标轴放置某物.

  • align—沿横轴放置某物.

  • content—一组可以分发的“东西”。

  • items—可以单独定位的单个项目。

所以:我们有justify-content来控制群体在主轴上的分布,我们有align-items沿横轴单独定位每个项目。这是我们用来管理Flexbox布局的两个主要属性。

没有justify-items因为同样的原因justify-self;当谈到主轴时,我们必须把这些物品看作一个整体,作为可以分发的内容。

怎么样align-content?实际上,这个存在于Flexbox中!稍后,我们会谈到flex-wrap特性

六、设定尺寸

让我们来谈谈我对Flexbox最大的领悟。

假设我有下面的CSS:

.item {
  width: 2000px;
}

正常的话我们看到这个肯定会说:这简单,会得到一个2000像素宽的元素”。但这是真的吗?

让我们来测试一下,先看效果图

参考代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>验证设置width=2000px的效果</title>
  <style>
    .flex-wrapper {
      display: flex;
    }
    .item {
      width: 2000px;
      height: 200px;
      background: #ccc;
      border: 1px solid #000;
      margin-bottom: 20px;
    }
  </style>
</head>
<body>
  <div class="item">display: block</div>
  
  <div class="flex-wrapper">
    <div class="item">display: flex</div>
  </div>
</body>
</html>

这是不是很有趣?

这两个项目应用了完全相同的CSS。他们都有width: 2000px。然而,第一项比第二项宽得多!

不同之处在于布局模式。第一个项目是使用流布局呈现的,在流布局中,width是一个硬约束。当我们设置width: 2000px时,我们将得到一个2000像素宽的元素。

然而在Flexbox里,在width属性的实现方式是不同的。与其说是硬性约束,不如说是建议。

该规范为此命名为假设尺寸。这是一个元素的大小在一个完美的乌托邦世界里,没有任何阻碍。

事情貌似就是这么简单。在这种情况下,限制因素是父元素没有那么宽的空间能放下一个2000px宽的孩子。所以,孩子的尺寸被缩小了,这样才合适。

这是Flexbox理念的核心部分。事物是流动的,灵活的,可以适应世界的限制。

算法的输入

我们倾向于认为CSS语言是属性的集合,但是我认为这是错误的思维模式。正如我们已经看到的width属性的行为因所使用的布局模式而异!

相反,我喜欢把CSS看作是布局模式的集合。每种布局模式都是一种算法,可以实现或重新定义每个CSS属性。我们用CSS声明(键/值对)提供一个算法,算法决定如何使用它们。

换句话说,我们编写的CSS是这些算法的输入,就像传递给函数的参数。如果我们想真实地;诚挚地;准确地对CSS感到舒服,光学属性是不够的;我们必须了解算法是如何使用这些属性。

这是我这篇博客的中心思想,
面向JavaScript开发人员的CSS。我不会让你记住一堆难以理解的CSS片段,而是打开这门语言的思路,学习所有布局模式是如何工作的。

 七、伸缩属性

我们已经在上面的例子了解了,Flexbox算法具有一些内置的灵活性,包括设定尺寸宽度实际中为了要了解Flexbox的流动性,我们需要讨论3个属性:flex-growflex-shrink,以及flex-basis.

让我们来看看每个属性。

弹性基础:flex-basis

我承认:在过去的很长一段时间,我真的不明白flex-basis是干什么的。😅

简单来说:在柔性行中,flex-basiswidth做同样的事情。在柔性柱中,flex-basisheight做同样的事情.

正如我们所了解的,Flexbox中的一切都是盯住主轴/横轴。举个例子,justify-content将沿着主轴分布子对象,无论主轴是水平还是垂直,其工作方式都完全相同。

但是widthheight不会遵循这个规则!

width总是会影响水平尺寸。当我们翻转flex-directionrowcolumn时,它不会突然变成height。

因此,Flexbox的作者创建了一个通用“大小”的属性,称为flex-basis。这就像width或者height,但它盯住了主坐标轴。像其他属性一样。它允许我们设置假设尺寸无论是水平还是垂直方向。

在这里试一试。每个孩子都得到了flex-basis: 50px,但是当调整第一个子项时会发生什么?

先看动图效果:

就像我们看到的widthflex-basis与其说是硬约束,不如说是建议。在某一点上,没有足够的空间来容纳所有的元素,所以他们不得不妥协,以避免溢出。

一个不确定的事物

一般来说,我们可以使用widthflex-basis在弹性行中可以互换,但也有一些例外。

例如,在width属性对图像等被替换元素的影响不同于flex-basis

还有,width可以将项目缩小到其以下最低限度尺寸,而flex-basis不能。

这已经超出了这篇博文的范围,但是我想提一下,因为您可能偶尔会遇到这两种属性具有不同效果的边缘情况。

灵活增长:flex-grow

默认情况下,Flex上下文中的元素将沿着主轴收缩到它们最小的舒适尺寸。这通常会产生额外的空间。

我们可以指定如何使用该空间flex-grow属性:

先看动图效果:

 

flex-grow的默认值为0,这意味着增长是选择加入的。如果我们想让孩子吃掉容器中任何多余的空间,我们需要明确地告诉他。

如果有多个孩子设置了flex-grow在这种情况下,额外的空间会根据孩子的flex-grow价值进行计算。

用文字不太好描述,我觉得还是用实例直观地解释会更容易。我们看下图中尝试增加/减少每个孩子的glex-grow值。

 

未完待续.......

转载请注明出处或者链接地址:https://www.qianduange.cn//article/17477.html
标签
display flex
评论
发布的文章
大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!