基础篇—CSS3中displex:flex弹性盒布局详解

举报
国服第二切图仔 发表于 2023/02/28 09:37:07 2023/02/28
【摘要】 ​前言:          长久以来,CSS 布局中唯一可靠且跨浏览器兼容的创建工具只有 float 和 position。这两个工具大部分情况下都很好使,但是在某些方面它们具有一定的局限性,让人难以完成任务。以下简单的布局需求是难以或不可能用这样的工具(float 和 position)方便且灵活的实现的:在父内容里面垂直居中一个块内容?使容器的所有子项占用等量的可用宽度/高度,而不管有多...


前言:


          长久以来,CSS 布局中唯一可靠且跨浏览器兼容的创建工具只有 float 和 position。这两个工具大部分情况下都很好使,但是在某些方面它们具有一定的局限性,让人难以完成任务。

以下简单的布局需求是难以或不可能用这样的工具(float 和 position)方便且灵活的实现的:

  • 在父内容里面垂直居中一个块内容?
  • 使容器的所有子项占用等量的可用宽度/高度,而不管有多少宽度/高度可用?
  • 使多列布局中的所有列采用相同的高度,即使它们包含的内容量不同?

正如你将在后面的章节中看到的一样,弹性盒子使得很多布局任务变得更加容易。让我们继续吧!

一个简单的例子

在本文中,我们将通过一系列练习来帮助你了解弹性盒子的工作原理。开始前,你可以拷贝示例代码到本地。在现代浏览器里打开它(比如 Firefox 或 Chrome),然后打开你的编辑器看一眼它的代码。

编辑
<!DOCTYPE html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>Flexbox 0 — starting code</title>
    <style>
      html {
        font-family: sans-serif;
      }

      body {
        margin: 0;
      }

      header {
        background: purple;
        height: 100px;
      }

      h1 {
        text-align: center;
        color: white;
        line-height: 100px;
        margin: 0;
      }

      article {
        padding: 10px;
        margin: 10px;
        background: aqua;
      }

      /* Add your flexbox CSS below here */


      
    </style>
  </head>
  <body>
    <header>
      <h1>Sample flexbox example</h1>
    </header>

    <section>
      <article>
        <h2>First article</h2>

        <p>Tacos actually microdosing, pour-over semiotics banjo chicharrones retro fanny pack portland everyday carry vinyl typewriter. Tacos PBR&B pork belly, everyday carry ennui pickled sriracha normcore hashtag polaroid single-origin coffee cold-pressed. PBR&B tattooed trust fund twee, leggings salvia iPhone photo booth health goth gastropub hammock.</p>
      </article>

      <article>
        <h2>Second article</h2>

        <p>Tacos actually microdosing, pour-over semiotics banjo chicharrones retro fanny pack portland everyday carry vinyl typewriter. Tacos PBR&B pork belly, everyday carry ennui pickled sriracha normcore hashtag polaroid single-origin coffee cold-pressed. PBR&B tattooed trust fund twee, leggings salvia iPhone photo booth health goth gastropub hammock.</p>
      </article>

      <article>
        <h2>Third article</h2>

        <p>Tacos actually microdosing, pour-over semiotics banjo chicharrones retro fanny pack portland everyday carry vinyl typewriter. Tacos PBR&B pork belly, everyday carry ennui pickled sriracha normcore hashtag polaroid single-origin coffee cold-pressed. PBR&B tattooed trust fund twee, leggings salvia iPhone photo booth health goth gastropub hammock.</p>

        <p>Cray food truck brunch, XOXO +1 keffiyeh pickled chambray waistcoat ennui. Organic small batch paleo 8-bit. Intelligentsia umami wayfarers pickled, asymmetrical kombucha letterpress kitsch leggings cold-pressed squid chartreuse put a bird on it. Listicle pickled man bun cornhole heirloom art party.</p>
      </article>
    </section>
  </body>
</html>

你可以看到这个页面有一个含有顶级标题的 <header> 元素,和一个包含三个 <article> 的 <section>。我们将使用这些来创建相当标准的三列布局。

1、指定元素的布局为 flex        

        首先,我们需要选择将哪些元素将设置为弹性的盒子。我们需要给这些 flexible 元素的父元素 display 设置一个特定值。在本例中,我们想要设置 <article> 元素,因此我们给 <section>(变成了 flex 容器)设置 display:

section {
  display:flex
}

结果如下:网页默认布局是竖向排列的,设置为弹性盒后,子节点默认横向排列了。

编辑

所以,就这样一个简单的声明就给了我们所需要的一切—非常不可思议,对吧?我们的多列布局具有大小相等的列,并且列的高度都是一样。这是因为这样的 flex 项(flex 容器的子项)的默认值是可以解决这些的常见问题的。后面还有更多内容。

为了更清晰的表述,让我们重申这里发生的事情。关于它如何与页面其余部分交互,我们给的 display 值为 flex 的元素就像一个块级元素,但是它的子元素布局为 flex 项。下个部分将更详细地描述这些意味着什么。请注意,如果你希望该元素的子元素作为 flex 项,你也可以使用 display 值为 inline-flex,但是该元素的行为类似于行内元素。


2、flex 模型说明

当元素表现为 flex 框时,它们沿着两个轴来布局:

编辑
  • 主轴(main axis)是沿着 flex 元素放置的方向延伸的轴(比如页面上的横向的行、纵向的列)。该轴的开始和结束被称为 main start 和 main end
  • 交叉轴(cross axis)是垂直于 flex 元素放置方向的轴。该轴的开始和结束被称为 cross start 和 cross end
  • 设置了 display: flex 的父元素(在本例中是 <section>)被称之为 flex 容器(flex container)。
  • 在 flex 容器中表现为弹性的盒子的元素被称之为 flex 项flex item)(本例中是 <article> 元素。

了解这些术语以便你阅读后续章节。如果你对使用的任何术语感到困惑,你可以随时返回这里。


3、弹性盒怎么恢复竖向排列?

弹性盒子提供了 flex-direction 这样一个属性,它可以指定主轴的方向(弹性盒子子类放置的地方)——它默认值是 row,这使得它们在按你浏览器的默认语言方向排成一排(在英语/中文浏览器中是从左到右)。

尝试将以下声明添加到 <section> 元素的 css 规则里:

flex-direction: column;//恢复成列排列

编辑

 你会看到,这会将那些元素设置为列布局,就像我们添加这些 CSS 之前。在继续之前,请从示例中去掉此规则。

备注: 你还可以使用 row-reverse 和 column-reverse 值反向排列 flex 项。用这些值试试看吧!

4、超出换行

当你在布局中使用定宽或者定高的时候,可能会出现问题即处于容器中的弹性盒子子元素会溢出,破坏了布局。你可以看一下示例(你也可以拷贝到本地),如下所示:

编辑
<!DOCTYPE html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>Flexbox wrap 0 — children overflowing</title>
    <style>
      html {
        font-family: sans-serif;
      }

      body {
        margin: 0;
      }

      header {
        background: purple;
        height: 100px;
      }

      h1 {
        text-align: center;
        color: white;
        line-height: 100px;
        margin: 0;
      }

      article {
        padding: 10px;
        margin: 10px;
        background: aqua;
      }

      /* Add your flexbox CSS below here */

      section {
        display: flex;
        flex-direction: row;
      }

      article {
        
      }


    </style>
  </head>
  <body>
    <header>
      <h1>Sample flexbox example</h1>
    </header>

    <section>
      <article>
        <h2>First article</h2>

        <p>Tacos actually microdosing, pour-over semiotics banjo chicharrones retro fanny pack portland everyday carry vinyl typewriter. Tacos PBR&B pork belly, everyday carry ennui pickled sriracha normcore hashtag polaroid single-origin coffee cold-pressed. PBR&B tattooed trust fund twee, leggings salvia iPhone photo booth health goth gastropub hammock.</p>
      </article>

      <article>
        <h2>Second article</h2>

        <p>Tacos actually microdosing, pour-over semiotics banjo chicharrones retro fanny pack portland everyday carry vinyl typewriter. Tacos PBR&B pork belly, everyday carry ennui pickled sriracha normcore hashtag polaroid single-origin coffee cold-pressed. PBR&B tattooed trust fund twee, leggings salvia iPhone photo booth health goth gastropub hammock.</p>
      </article>

      <article>
        <h2>Third article</h2>

        <p>Tacos actually microdosing, pour-over semiotics banjo chicharrones retro fanny pack portland everyday carry vinyl typewriter. Tacos PBR&B pork belly, everyday carry ennui pickled sriracha normcore hashtag polaroid single-origin coffee cold-pressed. PBR&B tattooed trust fund twee, leggings salvia iPhone photo booth health goth gastropub hammock.</p>

        <p>Cray food truck brunch, XOXO +1 keffiyeh pickled chambray waistcoat ennui. Organic small batch paleo 8-bit. Intelligentsia umami wayfarers pickled, asymmetrical kombucha letterpress kitsch leggings cold-pressed squid chartreuse put a bird on it. Listicle pickled man bun cornhole heirloom art party.</p>
      </article>

      <article>
        <h2>Fourth article</h2>

        <p>Tacos actually microdosing, pour-over semiotics banjo chicharrones retro fanny pack portland everyday carry vinyl typewriter. Tacos PBR&B pork belly, everyday carry ennui pickled sriracha normcore hashtag polaroid single-origin coffee cold-pressed. PBR&B tattooed trust fund twee, leggings salvia iPhone photo booth health goth gastropub hammock.</p>
      </article>

      <article>
        <h2>Fifth article</h2>

        <p>Tacos actually microdosing, pour-over semiotics banjo chicharrones retro fanny pack portland everyday carry vinyl typewriter. Tacos PBR&B pork belly, everyday carry ennui pickled sriracha normcore hashtag polaroid single-origin coffee cold-pressed. PBR&B tattooed trust fund twee, leggings salvia iPhone photo booth health goth gastropub hammock.</p>
      </article>

      <article>
        <h2>Sixth article</h2>

        <p>Tacos actually microdosing, pour-over semiotics banjo chicharrones retro fanny pack portland everyday carry vinyl typewriter. Tacos PBR&B pork belly, everyday carry ennui pickled sriracha normcore hashtag polaroid single-origin coffee cold-pressed. PBR&B tattooed trust fund twee, leggings salvia iPhone photo booth health goth gastropub hammock.</p>

        <p>Cray food truck brunch, XOXO +1 keffiyeh pickled chambray waistcoat ennui. Organic small batch paleo 8-bit. Intelligentsia umami wayfarers pickled, asymmetrical kombucha letterpress kitsch leggings cold-pressed squid chartreuse put a bird on it. Listicle pickled man bun cornhole heirloom art party.</p>
      </article>

      <article>
        <h2>Seventh article</h2>

        <p>Tacos actually microdosing, pour-over semiotics banjo chicharrones retro fanny pack portland everyday carry vinyl typewriter. Tacos PBR&B pork belly, everyday carry ennui pickled sriracha normcore hashtag polaroid single-origin coffee cold-pressed. PBR&B tattooed trust fund twee, leggings salvia iPhone photo booth health goth gastropub hammock.</p>
      </article>

      <article>
        <h2>Eighth article</h2>

        <p>Tacos actually microdosing, pour-over semiotics banjo chicharrones retro fanny pack portland everyday carry vinyl typewriter. Tacos PBR&B pork belly, everyday carry ennui pickled sriracha normcore hashtag polaroid single-origin coffee cold-pressed. PBR&B tattooed trust fund twee, leggings salvia iPhone photo booth health goth gastropub hammock.</p>
      </article>

      <article>
        <h2>Ninth article</h2>

        <p>Tacos actually microdosing, pour-over semiotics banjo chicharrones retro fanny pack portland everyday carry vinyl typewriter. Tacos PBR&B pork belly, everyday carry ennui pickled sriracha normcore hashtag polaroid single-origin coffee cold-pressed. PBR&B tattooed trust fund twee, leggings salvia iPhone photo booth health goth gastropub hammock.</p>

        <p>Cray food truck brunch, XOXO +1 keffiyeh pickled chambray waistcoat ennui. Organic small batch paleo 8-bit. Intelligentsia umami wayfarers pickled, asymmetrical kombucha letterpress kitsch leggings cold-pressed squid chartreuse put a bird on it. Listicle pickled man bun cornhole heirloom art party.</p>
      </article>

      <article>
        <h2>Tenth article</h2>

        <p>Tacos actually microdosing, pour-over semiotics banjo chicharrones retro fanny pack portland everyday carry vinyl typewriter. Tacos PBR&B pork belly, everyday carry ennui pickled sriracha normcore hashtag polaroid single-origin coffee cold-pressed. PBR&B tattooed trust fund twee, leggings salvia iPhone photo booth health goth gastropub hammock.</p>
      </article>

      <article>
        <h2>Eleventh article</h2>

        <p>Tacos actually microdosing, pour-over semiotics banjo chicharrones retro fanny pack portland everyday carry vinyl typewriter. Tacos PBR&B pork belly, everyday carry ennui pickled sriracha normcore hashtag polaroid single-origin coffee cold-pressed. PBR&B tattooed trust fund twee, leggings salvia iPhone photo booth health goth gastropub hammock.</p>
      </article>

      <article>
        <h2>Twelfth article</h2>

        <p>Tacos actually microdosing, pour-over semiotics banjo chicharrones retro fanny pack portland everyday carry vinyl typewriter. Tacos PBR&B pork belly, everyday carry ennui pickled sriracha normcore hashtag polaroid single-origin coffee cold-pressed. PBR&B tattooed trust fund twee, leggings salvia iPhone photo booth health goth gastropub hammock.</p>

        <p>Cray food truck brunch, XOXO +1 keffiyeh pickled chambray waistcoat ennui. Organic small batch paleo 8-bit. Intelligentsia umami wayfarers pickled, asymmetrical kombucha letterpress kitsch leggings cold-pressed squid chartreuse put a bird on it. Listicle pickled man bun cornhole heirloom art party.</p>
      </article>
    </section>
  </body>
</html>

在这里我们看到,子代确实超出了它们的容器。解决此问题的一种方法是将以下声明添加到 section css 规则中:

flex-wrap: wrap;

同时,把以下规则也添加到 <article> 规则中:

flex: 200px;

现在尝试一下吧;你会看到布局比原来好多了:

编辑

我们现在有多个行。每行都安装了尽可能多的 flex 项。任何溢出都会向下移动到下一行。在 article 上设置的 flex:200px 声明意味着每个声明将至少为 200px 宽。我们稍后会更详细地讨论这个属性。你可能还注意到,最后一行上的最后几个项每个都变得更宽,以便把整个行填满。

但是这里我们可以做得更多。首先,改变 flex-direction 属性值为 row-reverse——你会看到仍然有多行布局,但是每一行元素排列的方向和原来是相反的了。

5、flex-flow 缩写

到这里,应当注意到存在着 flex-direction 和 flex-wrap——的缩写 flex-flow。比如,你可以将

flex-direction: row;
flex-wrap: wrap;

替换为

flex-flow: row wrap;


6、flex 项的动态尺寸

现在让我们回到第一个例子,看看是如何控制 flex 项占用空间的比例的。打开你本地的第一个示例代码

第一步,将以下规则添加到 CSS 的底部:

article {
  flex: 1;
}


这是一个无单位的比例值,表示每个 flex 项沿主轴的可用空间大小。本例中,我们设置 <article> 元素的 flex 值为 1,这表示每个元素占用空间都是相等的,占用的空间是在设置 padding 和 margin 之后剩余的空间。因为它是一个比例,这意味着将每个 flex 项的设置为 400000 的效果和 1 的时候是完全一样的。

现在在上一个规则下添加:

article:nth-of-type(3) {
  flex: 2;
}


现在当你刷新,你会看到第三个 <article> 元素占用了两倍的可用宽度和剩下的一样——现在总共有四个比例单位可用。前两个 flex 项各有一个,因此它们占用每个可用空间的 1/4。第三个有两个单位,所以它占用 2/4 或者说是 1/2 的可用空间。

你还可以指定 flex 的最小值。尝试修改现有的 article 规则:

article {
  flex: 1 200px;
}

article:nth-of-type(3) {
  flex: 2 200px;
}

这表示“每个 flex 项将首先给出 200px 的可用空间,然后,剩余的可用空间将根据分配的比例共享”。尝试刷新,你会看到分配空间的差别。

编辑

弹性盒子的真正价值可以体现在它的灵活性/响应性,如果你调整浏览器窗口的大小,或者增加一个 <article> 元素,这时的布局仍旧是好的。

7、flex:缩写与全写

flex 是一个可以指定最多三个不同值的缩写属性:

  • 第一个就是上面所讨论过的无单位比例。可以单独指定全写 flex-grow 属性的值。
  • 第二个无单位比例——flex-shrink——一般用于溢出容器的 flex 项。这指定了从每个 flex 项中取出多少溢出量,以阻止它们溢出它们的容器。这是一个相当高级的弹性盒子功能,我们不会在本文中进一步说明。
  • 第三个是上面讨论的最小值。可以单独指定全写 flex-basis 属性的值。

我们建议不要使用全写属性,除非你真的需要(比如要去覆盖之前写的)。使用全写会多写很多的代码,它们也可能有点让人困惑。

8、弹性盒怎么设置水平和垂直对齐

还可以使用弹性盒子的功能让 flex 项沿主轴或交叉轴对齐。让我们一起看一下新例子——我们将会有一个整洁,灵活的按钮/工具栏。此时,你看到了一个水平菜单栏,其中一些按钮卡在左上角,就像下面这样:

编辑

<!DOCTYPE html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>Flexbox align 0 — starting code</title>
    <style>
      html {
        font-family: sans-serif;
      }

      body {
        width: 70%;
        max-width: 960px;
        margin: 20px auto;
      }

      button {
        font-size: 18px;
        line-height: 1.5;
        width: 15%;
      }

      div {
        height: 100px;
        border: 1px solid black;
      }

      /* Add your flexbox CSS below here */

      
    </style>
  </head>
  <body>
    <div>
      <button>Smile</button>
      <button>Laugh</button>
      <button>Wink</button>
      <button>Shrug</button>
      <button>Blush</button>
    </div>
  </body>
</html>

首先,拷贝一份到本地。

然后,将下面的 CSS 添加到例子的底部:

div {
  display: flex;
  align-items: center;
  justify-content: space-around;
}

编辑

刷新一下页面,你就会看到这些按钮很好的垂直水平居中了。我们是通过下面所说的两个新的属性做到的。

align-items 控制 flex 项在交叉轴上的位置。

  • 默认的值是 stretch,其会使所有 flex 项沿着交叉轴的方向拉伸以填充父容器。如果父容器在交叉轴方向上没有固定宽度(即高度),则所有 flex 项将变得与最长的 flex 项一样长(即高度保持一致)。我们的第一个例子在默认情况下得到相等的高度的列的原因。
  • 在上面规则中我们使用的 center 值会使这些项保持其原有的高度,但是会在交叉轴居中。这就是那些按钮垂直居中的原因。
  • 你也可以设置诸如 flex-start 或 flex-end 这样使 flex 项在交叉轴的开始或结束处对齐所有的值。查看 align-items 了解更多。

你可以用 align-self 属性覆盖 align-items 的行为。比如,你可以这样:

button:first-child {
  align-self: flex-end;
}

带有 Smile、Laugh、Wink、Shrug & Blush 标签的五个按钮排在一个弹性容器中。除第一个项外,所有 flex 项都通过将对齐项属性设置为中心,位于十字轴的中心或垂直居中。第一项与交叉轴末端的弹性容器底部齐平,对齐自属性设置 flex 端。flex 项沿着容器的主轴或宽度均匀间隔。

去看看它产生的效果,然后删除它。

justify-content 控制 flex 项在主轴上的位置。

  • 默认值是 flex-start,这会使所有 flex 项都位于主轴的开始处。
  • 你也可以用 flex-end 来让 flex 项到结尾处。
  • center 在 justify-content 里也是可用的,可以让 flex 项在主轴居中。
  • 而我们上面用到的值 space-around 是很有用的——它会使所有 flex 项沿着主轴均匀地分布,在任意一端都会留有一点空间。
  • 还有一个值是 space-between,它和 space-around 非常相似,只是它不会在两端留下任何空间。

在继续下面之前,多多使用提到过的属性吧,看看它们的效果。

9、flex 项排序

弹性盒子也有可以改变 flex 项的布局位置的功能,而不会影响到源顺序(即 dom 树里元素的顺序)。这也是传统布局方式很难做到的一点。

代码也很简单,将下面的 CSS 添加到示例代码下面。

button:first-child {
  order: 1;
}


刷新下,然后你会看到“Smile”按钮移动到了主轴的末尾。下面我们谈下它实现的一些细节:

  • 所有 flex 项默认的 order 值是 0。
  • order 值大的 flex 项比 order 值小的在显示顺序中更靠后。
  • 相同 order 值的 flex 项按源顺序显示。所以假如你有四个元素,其 order 值分别是 2,1,1 和 0,那么它们的显示顺序就分别是第四,第二,第三,和第一。
  • 第三个元素显示在第二个后面是因为它们的 order 值一样,且第三个元素在源顺序中排在第二个后面。

你也可以给 order 设置负值使它们比值为 0 的元素排得更前面。比如,你可以设置“Blush”按钮排在主轴的最前面:

button:last-child {
  order: -1;
}

11、跨浏览器兼容性

        大多数浏览器都支持弹性盒子,诸如 Firefox、Chrome、Opera、Microsoft Edge 和 IE 11,较新版本的 Android/iOS 等等。但是你应该要意识到仍旧有被人使用的老浏览器不支持弹性盒子(或者支持,但是只是支持非常非常老版本的弹性盒子)。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。