前端大杂烩Web开发基础知识

Flex 布局

2021-03-29  本文已影响0人  lio_zero

Flex 是 Flexible Box 的缩写,意为"弹性布局",它旨在提供一种更有效的方式来布局、对齐和分配容器中项目之间的空间,即使这些项目的大小未知或是动态(因此称为 "flex")。

Flex 布局背后的主要思想是让容器能够改变其项目的宽度/高度(和顺序),以最好地填充可用空间(主要是为了适应各种显示设备和屏幕大小)。flex 容器扩展项目以填充可用空间,或收缩项目以防止溢出。

最重要的是,Flexbox 布局与常规布局(基于垂直的块和基于水平的内联)相比是方向无关的。虽然这些方法对页面很有效,但它们缺乏灵活性来支持大型或复杂的应用程序(尤其是在方向改变、调整大小、拉伸、收缩等方面)。

Flex 布局在2009年由 W3C 提出的。它在所有的浏览器都支持。

Flex 兼容情况

注意:Flexbox 布局最适合应用程序的组件和小规模布局,而 Grid 布局则适用于大规模布局。我们将在下一篇讲解 Grid 布局。

以下内容参考 Flexbox30,图片截自 A Complete Guide to Flexbox

基础概念

为了使 Flexbox 正常工作,您需要设置父子关系。父级是 Flex 容器,其中的所有内容都是子级或 Flex 项。

Flex 容器仅环绕其直接子容器。因此,没有孙子或孙子孙辈的关系。只有父母↔️直系子女!只要存在父子关系,就可以建立 Flexbox。因此,孩子也可以成为其孩子的伸缩容器。但这将是一个单独的 flex 容器。而且它不会继承祖父母的 flex 属性。

这里有一篇关于不能将文本容器设置为 flexbox 容器 Never make your text container a flexbox container

img

Flexbox 在2轴系统中运行:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴是您将伸缩项目如何放置在伸缩容器中的定义方向。确定横轴非常简单,它是在垂直于主轴的方向上进行的。

记住不要把他比作数学上的 xy 轴。因为 x 轴并不总是主轴。这可能会让你出错。

在每个轴上都有一个起点和终点。如果在主轴上,则将起始位置称为 main start,将结束位置称为 main end。相同的概念适用于交叉轴。知道开始和结束很重要,因为您可以控制弹性项目的放置位置。

项目默认沿主轴排列。单个项目占据的主轴空间叫做 main size,占据的交叉轴空间叫做 cross size

属性

父容器和子项目都有自己的一套属性。

父容器

子项目

父容器

父容器

flex 容器有2种类型:flex 将创建一个块级 flex 容器,inline-flex 将创建一个 inline 级 flex 容器。

.parent {
  display: flex /* default */ | inline-flex;
}

很简单地解释,块元素占据了容器的整个宽度。它们看起来像构建块,其中每个构建块彼此堆叠。内联元素仅占用其所需的空间。因此,它们似乎排成一行,或者彼此并排。

flex-wrap

默认情况下,弹性项目将尝试使其自身收缩以适合一行,换句话说,不进行换行。但是,如果您希望 flex 项保持其大小并在容器中的多行中溢出,则可以使用 flex-wrap: warp;。此属性将使容器中的弹性项目占用多行。

.parent {
  flex-wrap: nowrap /* default */ | wrap | wrap-reverse;
}
flex-wrap

flex-wrap 允许 flex 项在单独的行上进行包装。但有了 align-content,我们可以控制那些项目行在横轴上的对齐方式。由于这仅适用于包装的项目,所以如果只有一行 flex 项,则此属性不会有任何效果。

flex-flow

flex-flowflex-directionflex-wrap 的简写。默认值为 row nowrap。如果仅设置一个值,则未设置的属性将采用默认值。

.parent {
  flex-flow: row nowrap /* default */ | <flex-direction> <flex-wrap> | <flex-direction> | <flex-wrap>;
}

flex-direction

定义主轴的属性。记住主轴可以是水平或垂直的。因此,如果我们希望主轴水平,则称为行。如果我们希望它是垂直的,那就叫做专栏。另外,请记住我们有一个主要的起点和终点。我们只需添加一个反向后缀即可将我们的“主要起点”设置为反向。

.parent {
  flex-direction: row /* default */ | row-reverse | column | column-reverse;
}
flex-direction

justify-content

justify-content 设置沿主轴对齐的属性。align-items 设置沿横轴对齐的属性。记住横轴始终垂直于主轴。

.parent {
  justify-content: flex-start /* default */ | flex-end | center | space-around | space-between | space-evenly;
}
justify-content

主轴也可以垂直放置。在这种情况下,将 flex-direction 设置为 column。

.parent {
  flex-direction: column;
  justify-content: flex-start /* default */ | flex-end | center | space-around | space-between | space-evenly;
}

align-items

.parent {
  align-items: stretch /* default */ | flex-start | flex-end | center | baseline;
}
align-items

现在,让我们看一下如果交叉轴水平放置,则弹性项目如何对齐。换句话说,伸缩方向是列。

.parent {
  flex-direction: column;
  align-items: stretch /* default */ | flex-start | flex-end | center | baseline;
}

align-content

align-content 属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。

.parent {
  align-content: stretch /* default */ | flex-start | flex-end | center | space-between | space-around;
}
align-content

space-evenly 和 space-around

space-evenly 中,弹性项目之间的空白空间始终相等。

space-evenly

但是,在 space-around 上,只有内部项目之间的间距相等。第一项和最后一项将仅分配一半的间距。使它的视觉外观更加散布

space-around

子项目

子项目

order

默认情况下,弹性项目的显示顺序与在代码中显示的顺序相同。但是,如果您要更改该怎么办?没问题!使用 order 属性更改商品的顺序。

.child {
  order: 0 /* default */ | <number>;
}
order

flex-grow

Flexbox 非常适合响应式设计。flex-grow 属性允许我们的 flex 项在必要时增长。因此,如果我的容器中有多余的可用空间,我可以告诉某个特定项目按一定比例将其填满。

.child {
  flex-grow: 0 /* default */ | <number>;
}
flex-grow

flex-shrink

如果有伸缩空间,flex-grow 将会扩展以填充额外的空间。相反 flex-shrink 当空间不足时将会控制 flex 项目缩小到适合的程度。请注意,数字越大,缩小幅度越大。

.child {
  flex-shrink: 1 /* default */ | <number>;
}

你可以在 flex-grow-calculationflex-shrink-calculation 查看浏览器如何帮我们自动处理 flex-growflex-shrink

flex-basis

使用 flex-basis 属性,可以设置项目的初始大小。您可以将此属性视为 flex 项目的宽度。

因此,您的下一个问题可能是 widthflex-basis 之间的区别是什么。当然,您仍然可以使用 width,它将仍然有效。

它起作用的原因是,如果未设置 flex-basis,它将默认为 width。因此,您的浏览器将始终尝试将 flex-basis 值用作大小指示器。如果找不到它,那就别无选择,只能使用您的 width 属性。不要让浏览器做额外的工作。以正确的 flex 方法进行操作,并使用flex-basis

.child {
  flex-basis: auto /* default */ | <width>;
}

当一个项目具有 flex-basiswidth 时,浏览器将始终使用 flex-basis 设置的值。但要注意,如果同时设置了 min-widthmax-width。在这些情况下,flex-basis 将丢失,并且不会用作宽度。

flex

flex 是上面所提到的 flex-growflex-shrinkflex-basis 的简写形式。如果你足够了解它们的特性,请使用简写吧!!!

.child {
  flex: 1 0 auto /* default */ |
      <flex-grow> <flex-shrink> <flex-basis> |
      <flex-grow> |
      <flex-basis> |
      <flex-grow> <flex-basis> |
      <flex-grow> <flex-shrink>;
  
  /* 相当于: */
  flex-grow: 1;
  flex-shrink: 0;
  flex-basis: auto;
}

align-self

align-items 属性可以沿着横轴设置 flex 项。align-items 的问题是它强制所有 flex 项使用规则。

但是如果你想让他们中的一个打破规则,你可以使用 align-self。此属性接受为 align-items 提供的所有相同值,因此您可以轻松脱离包装😎

.child-1 {
  align-self: stretch /* default */ | flex-start | flex-end | center | baseline;
}
align-self

技巧

垂直水平居中元素

方式一

.container {
  display: flex;
  justify-content: center; /* horizontal */
  align-items: center;     /* vertical */
}

方式二

.container {
  display: flex;
}

.container > div {
  margin: auto;
}
水平垂直居中

对齐 Flexbox 子元素的另一种方法是使用自动页边距。尽管这不是 Flexbox 属性,但要意识到这一点仍然很重要,因为它与 Flexbox 有非常有趣的关系。Bonus: Aligning with Auto Margins

重新排序

.container > .top {
 order: 1;
}

.container > .bottom {
 order: 2;
}

截断文本

.parent {
  display: flex;
  align-items: center;
  padding: 10px;
  margin: 30px 0;
}

.child {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.child > h2 {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.truncated {
  flex: 1;
  h2 {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

查看效果

移动布局

创建固定高度的顶栏和动态高度的内容区域。

.container {
  display: flex;
  flex-direction: column;
}

.container > .top {
  flex: 0 0 60px;
}

.container > .content {
  flex: 1 0 auto;
}

流式布局

自动用适当数量的盒子填充可用空间。

.container {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: 1rem;
}

.container > * {
  flex: 1 1 10ch;
}
流式布局

查看效果

响应导航栏

.nav {
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-end;
  
  list-style: none;
  margin: 0; 
  background: deepskyblue;
}

.nav a {
  text-decoration: none;
  display: block;
  padding: 1em;
  color: white;
}

.nav a:hover {
  background: #1565C0;
}

@media all and (max-width: 800px) {
  .nav {
    justify-content: space-around;
  }
}

@media all and (max-width: 600px) {
  .nav {
    flex-flow: column wrap;
    padding: 0;
  }
  .nav 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); 
  }
  .nav li:last-of-type a {
    border-bottom: none;
  }
}

类似于表

.container {
  display: flex;
}

.container > .checkbox { 
  flex: 1 0 20px;
}
.container > .subject { 
  flex: 1 0 400px;
}
.container > .date { 
  flex: 1 0 120px;
}

这将创建宽度不同的列,但大小会根据具体情况而相应调整。

固定脚部

HTML 结构

<section>
  <header></header>
  <main></main>
  <footer></footer>
</section>

方式一

section {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

main {
  flex: 1;
}

方式二

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

footer {
  margin-top: auto;
}

砌体布局

.masonry-container {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  max-height: 600px;
  .masonry-brick {
    margin: 0 .825rem .825rem 0;
    
    border-radius: 1rem;
  } 
}

/* or */

.masonry-container {
  display: flex;
  flex-wrap: wrap;
  .masonry-brick {
    flex: 1 0 auto;
    height: 150px;
    margin: 0 .825rem .825rem 0;
    border-radius: 1rem;
  } 
}
砌体布局

查看效果

圣杯布局

html 结构

<div class="container">
  <header class="header">Header</header>
  <article class="main">lorem</article>
  <aside class="aside aside-1">Aside 1</aside>
  <aside class="aside aside-2">Aside 2</aside>
  <footer class="footer">Footer</footer>
</div>

css

.container {
  display: flex;  
  flex-flow: row wrap;
  text-align: center;
}

.container > * {
  padding: 10px;
  flex: 1 100%;
}

.main {
  text-align: left;
}

@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; }
}

双飞翼布局

双飞翼布局其实是根据圣杯布局演化出来的一种布局。

.container {
  display: flex;
  flex-flow: row nowrap;
  justify-content: space-around;
  height: 100%;
}

.left,
.right {
  width: 200px;
  flex-shrink: 1;
}

.main {
  flex-grow: 1;
}
双飞翼布局

查看效果

两列布局

.container {
  display: flex;
}

.left {
  width: 200px;
  height: 100%;
}

.right {
  flex: 1;
  height: 100%;
}
两列布局

查看效果

更多资料

上一篇下一篇

猜你喜欢

热点阅读