likes
comments
collection
share

CSS学习-flex布局

作者站长头像
站长
· 阅读数 61

Flex布局

Flex 布局基本概念

Flex 布局即“弹性布局”,是一个一维的布局,每次只能处理一行或一列;传统方式对于垂直居中、对齐等特殊布局比较复杂,使用 Flex 可以简单、响应式的实现各种网页布局。

Flex 容器

给一个块级元素添加:display:flex;行内元素也可以设置 flex 容器 : display: inline-flex

.box {
	display: flex;
}

Flex 容器的所有子元素都成为(flex item) 成员;容器有两根轴:水平方向(主轴 main-axis)和 垂直方向(交叉轴 cross-axis);每个轴在方向上都有 start 和 end,它决定了 flex 元素依次排列的方向。

效果图:

CSS学习-flex布局

容器的属性

以下 7 个属性可以设置在容器上。

flex-direction

flex-direction 该属性决定了主轴 flex 元素的排列方向;

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

flex-wrap

flex 容器默认是不换行的;flex-wrap 该属性可以实现 flex 容器展示多行元素;

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

flex-flow

flex-flow 该属性是 flex-direction | flex-wrap 的缩写;

.box {
  flex-flow: <flex-direction> || <flex-wrap>;
}

justify-content

justify-content 指定容器内主轴的对齐方式;

  • space-between 均匀排列每个元素,首个元素放置于起点,末尾元素放置于终点;
  • space-around 每个元素周围分配相同的空间
  • space-evenly 每个元素之间的间隔相等
.box {
  justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
}

效果图:

CSS学习-flex布局

align-items

align-items 指定容器内交叉轴的对齐方式;

.box {
  align-items: stretch | flex-start | flex-end | center | baseline;
}
  • stretch 拉伸,如果项目中未设置高度或设为auto,将沾满整个容器的高度;即 flex 容器子项设置了高度,默认将不会拉伸高度到该行最高元素;

效果图:

CSS学习-flex布局

align-content

align-content 当容器有多行元素时指定交叉轴多行之间的对齐方式;

.box {
  align-content: stretch | flex-start | flex-end | center | space-between | space-around ;
}

效果图:

CSS学习-flex布局

gap

gap 该属性时 row-gap 和 column-gap 的缩写;

.box {
	gap: row-gap | column-gap;
}

flex 元素的属性

order

控制元素显示的顺序,数值越大排列越靠后;

.box-item {
	order: 0 | <integer>
}

align-self

决定单个 flex 元素的对齐方式,可以覆盖 align-items;默认 auto 等同于父元素的 align-items 属性;

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

flex-grow

flex 元素的增长系数,以 flex-basis为基础延主轴增长填满 flex容器;默认为 0 即不增长;

.box-item {
  flex-grow: <number>; /* default 0 */
}

flex-shirnk

flex 元素的缩写比列,默认为1,当父容器空间不足,该元素将缩写;

.box-item {
  flex-shrink: <number>; /* default 1 */
}

flex-basis

flex 元素的宽度大小,默认值为 auto 即项目的本来大小;

.box-item {
  flex-basis: <length> | auto; /* default auto */
}

flex

flex 属性是 flex-grow, flex-shrink, flex-basis 的简写;默认值 0 1 auto

  • flex: auto 表示1 1 auto
  • flex: 1 表示 1 1 0% 表示元素宽度从0%开始增长;
  • flex: none 表示 0 0 auto
.box-item {
  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}

常用案例

导航

在元素外部分布空间使用justify-content让多余空间分布在多个元素之间或周围;

效果图:

CSS学习-flex布局

让元素自己处理空间分布,使用flex: autoflex: 1 1 auto,所有元素在 flex-basis的基础上自动伸缩;

效果图:

CSS学习-flex布局

拆分导航

使用自动外边距,使得导航栏中的一组元素左对齐而另一组元素右对齐;

CSS学习-flex布局

垂直居中

使用align-items:center可以轻松的实现元素垂直居中;

效果图:

CSS学习-flex布局

卡片布局将页脚推到底部

在弹性盒内使用flex: 1flex: 1 1 0%,元素在 flex-basis为 0% 的基础上伸缩。它将是唯一能伸缩的元素将在容器中占据空余空间,同时将页脚推至底部。

效果图:

CSS学习-flex布局

媒体对象

这种模式下:当一侧具有图片,另一侧具有文本,图片可以在左边或右边;

  • 设置文本内容为 flex:1使得内容部分延伸
  • 设置图片max-width,不设置flex-basis的宽度为 auto 即图片本身的大小

效果图:

CSS学习-flex布局

可以实现悬挂布局,左边一个图片容器,右边一个文本容器,交叉进行排列;

效果图:

CSS学习-flex布局

    <div class="list">
      <div class="list-item">
        <div class="img"></div>
        <div class="description"></div>
      </div>
      <div class="list-item">
        <div class="img"></div>
        <div class="description"></div>
      </div>
      <div class="list-item">
        <div class="img"></div>
        <div class="description"></div>
      </div>
    </div>

      .list {
        display: flex;
        flex-direction: column;
        row-gap: 10px;
      }

      .list-item {
        display: flex;
        column-gap: 20px;
      }

      .list-item:nth-of-type(2n) {
        flex-direction: row-reverse;
      }

      .img {
        width: 200px;
        height: 100px;
      }

      .description {
        flex: 1;
      }

表单控件

搜索框,给 input 元素设置 flex: autoflex: 1 1 auto,使得 input 元素占据内容的剩余部分,可以随着可用控件的变化增长或缩写;

效果图:

CSS学习-flex布局

效果图:

CSS学习-flex布局

百分比布局

某个网格的宽度为固定的百分比flex-basis,其余网格利用 flex: 1增长平均分配剩余空间;

效果图:

CSS学习-flex布局

<div class="Grid">
  <div class="Grid-cell u-1of4">...</div>
  <div class="Grid-cell">...</div>
  <div class="Grid-cell u-1of3">...</div>
</div>
.Grid {
  display: flex;
}

.Grid-cell {
  flex: 1;
}

.Grid-cell.u-full {
  flex: 0 0 100%;
}

.Grid-cell.u-1of2 {
  flex: 0 0 50%;
}

.Grid-cell.u-1of3 {
  flex: 0 0 33.3333%;
}

.Grid-cell.u-1of4 {
  flex: 0 0 25%;
}

圣杯布局

圣杯布局 页面从上到下分为三个部分,页面从左到右分为3个部分,其中上下和左右两栏固定,中间自适应内容大小;

传统方式实现方法:

  • 左右float,中间margin
  • 左右absolute定位,中间margin左右两边的容器距离
  • 都使用float, 先写中间部分,左右两边用负margin

效果图:

CSS学习-flex布局 flex实现圣杯布局

<body class="HolyGrail">
  <header>...</header>
  <div class="HolyGrail-body">
    <main class="HolyGrail-content">...</main>
    <nav class="HolyGrail-nav">...</nav>
    <aside class="HolyGrail-ads">...</aside>
  </div>
  <footer>...</footer>
</body>

.HolyGrail {
  display: flex;
  min-height: 100vh;
  flex-direction: column;
}

header,
footer {
  flex: 1;
}

.HolyGrail-body {
  display: flex;
  flex: 1;
}

.HolyGrail-content {
  flex: 1;
}

.HolyGrail-nav, .HolyGrail-ads {
  /* 两个边栏的宽度设为12em */
  flex: 0 0 12em;
}

.HolyGrail-nav {
  /* 导航放到最左边 */
  order: -1;
}

当在小屏幕下使用媒体查询来调整 flex 容器内容排列:

@media (max-width: 768px) {
  .HolyGrail-body {
    flex-direction: column;
    flex: 1;
  }
  .HolyGrail-nav,
  .HolyGrail-ads,
  .HolyGrail-content {
    flex: auto;
  }
}

固定底栏

有时候网页内容不足没有满足一屏高度,导致底部上升到页面中间,可以设置页面容器min-height: 100vh保持整屏高度,页面内容使用flex:1增长;

效果图:

CSS学习-flex布局

<body class="Site">
  <header>...</header>
  <main class="Site-content">...</main>
  <footer>...</footer>
</body>
.Site {
  display: flex;
  min-height: 100vh;
  flex-direction: column;
}

.Site-content {
  flex: 1;
}

实战案例

小米商城固定底部导航栏

  • position: fixed;固定定位可以让元素固定在页面的某个位置(脱离文档流)
  • margin-top: -1px;负边距可以解决重复边框问题
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>小米固定导航栏</title>
    <style>
      * {
        padding: 0;
        margin: 0;
        box-sizing: border-box;
      }

      body {
        background-color: #eee;
        font-size: 16px;
      }

      ul {
        list-style: none;
      }

      a {
        color: #777;
        text-decoration: none;
      }

      .nav-fixed {
        position: fixed;
        bottom: 70px;
        right: 20px;
      }

      .nav-box {
        display: flex;
        flex-direction: column;
      }

      .nav-item {
        padding: 20px 10px;
        border: 1px solid #f5f5f5;
        background-color: #fff;
        /* 解决边框重复问题 */
        margin-top: -1px;
      }

      .nav-item a {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        row-gap: 10px;
      }

      .nav-item a:hover {
        color: coral;
      }

      .nav-item img {
        width: 30px;
        height: 30px;
      }

      .item-mgtop {
        margin-top: 20px;
      }
    </style>
  </head>
  <body>
    <div class="nav-fixed">
      <ul class="nav-box">
        <li class="nav-item">
          <a href="#">
            <img
              src="https://i8.mifile.cn/b2c-mimall-media/98a23aae70f25798192693f21c4d4039.png"
              alt=""
            />
            <span>手机APP</span>
          </a>
        </li>
        <li class="nav-item">
          <a href="#">
            <img
              src="https://i8.mifile.cn/b2c-mimall-media/98a23aae70f25798192693f21c4d4039.png"
              alt=""
            />
            <span>手机APP</span>
          </a>
        </li>
        <li class="nav-item">
          <a href="#">
            <img
              src="https://i8.mifile.cn/b2c-mimall-media/98a23aae70f25798192693f21c4d4039.png"
              alt=""
            />
            <span>手机APP</span>
          </a>
        </li>
        <li class="nav-item">
          <a href="#">
            <img
              src="https://i8.mifile.cn/b2c-mimall-media/98a23aae70f25798192693f21c4d4039.png"
              alt=""
            />
            <span>手机APP</span>
          </a>
        </li>
        <li class="nav-item">
          <a href="#">
            <img
              src="https://i8.mifile.cn/b2c-mimall-media/98a23aae70f25798192693f21c4d4039.png"
              alt=""
            />
            <span>手机APP</span>
          </a>
        </li>
        <li class="nav-item item-mgtop">
          <a href="#">
            <img
              src="https://i8.mifile.cn/b2c-mimall-media/98a23aae70f25798192693f21c4d4039.png"
              alt=""
            />
            <span>手机APP</span>
          </a>
        </li>
      </ul>
    </div>
  </body>
</html>

效果图:

CSS学习-flex布局

小米商城产品列表

  • 头部使用justify-content:space-between实现标准的导航栏;
  • 内部使用flex-direction:column来实现 flex 列容器;
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>小米card列表</title>
    <style>
      * {
        padding: 0;
        margin: 0;
        box-sizing: border-box;
      }

      ul {
        list-style: none;
      }

      body {
        background-color: #eee;
      }

      img {
        /* 图片填满容器 */
        width: 100%;
        height: 100%;
        object-fit: cover;
      }

      .box {
        max-width: 1226px;
        margin: 0 auto;
      }

      .flex {
        display: flex;
        gap: 14px;
      }

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

      .flex-wrap {
        flex-wrap: wrap;
      }

      .box-card {
        height: 300px;
        width: 234px;
        border: 1px solid #d7d7d7;
        background-color: #fff;
      }

      .box-card--gray {
        border: none;
        background-color: #eee;
      }

      .box-card-sm {
        background-color: #fff;
        border: 1px solid #d7d7d7;
        height: 143px;
      }

      .box-hd {
        padding: 20px 0;
        align-items: center;
        justify-content: space-between;
      }

      .more-list {
        gap: 20px;
      }

      .more-list li {
        padding: 6px 0px;
      }

      .more-active {
        color: #ff6700;
        border-bottom: 2px solid #ff6700;
      }
    </style>
  </head>
  <body>
    <div class="box">
      <div class="box-hd flex">
        <h4 class="box-title">智能家居</h4>
        <ul class="more-list flex">
          <li class="more-active">小爱音响</li>
          <li>门锁门铃</li>
          <li>路由器</li>
          <li>智能设备</li>
        </ul>
      </div>
      <div class="box-bd flex">
        <div class="box-left flex flex-column">
          <div class="box-card">
            <img
              src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/ec383d223d9f38f442268df684c526f6.png?thumb=1&w=234&h=300&f=webp&q=90"
              alt=""
            />
          </div>
          <div class="box-card"></div>
        </div>
        <div class="box-right flex flex-wrap">
          <div class="box-card"></div>
          <div class="box-card"></div>
          <div class="box-card"></div>
          <div class="box-card"></div>
          <div class="box-card"></div>
          <div class="box-card"></div>
          <div class="box-card"></div>
          <div class="box-card box-card--gray flex flex-column">
            <div class="box-card-sm"></div>
            <div class="box-card-sm"></div>
          </div>
        </div>
      </div>
    </div>
  </body>
</html>

效果图:

CSS学习-flex布局

总结

使用 flex 布局可以响应式的进行布局,它能使得排列方式、对齐方式、空间分布都变得简单,且可以利用 flex 元素的属性可以实现各种复杂布局属性;

参考链接

转载自:https://juejin.cn/post/7379423024556539939
评论
请登录