带你了解flex弹性布局

3,549 阅读12分钟

引言

在当今的网页开发中,响应式设计和灵活的布局方式变得越来越重要。而Flex 弹性布局(Flexbox)作为一种强大的 CSS 技术,为我们提供了一种简单而灵活的方式来创建复杂的布局结构。与传统的浮动布局和定位相比,Flexbox 更加直观、易于理解,并且能够更好地适应不同尺寸的屏幕和设备。

我们可以先来看看,为了实现一面这个水平垂直居中效果,不同的布局方式是如何实现的。

image.png

在html中我们添加一个父元素,一个子元素,用一个公共样式来设置他们的大小以及背景颜色
<body>
    <div class="parent">
        <div class="child">子元素</div>
    </div>
</body>
/* 公共样式 */
.parent {
            width: 300px;
            height: 300px;
            background-color: orange;
        }
        .child {
            width: 100px;
            height: 100px;
            background-color: skyblue;
        }

1. 定位 + margin

.parent {
            position: relative;
        }
        .child {
            position: absolute;
            top: 50%;
            left: 50%;
            margin-top: -50px;
            margin-left: -50px;
        }

2. 定位 + transform

.parent {
            position: relative;
        }
        .child {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
        }

3. flex

.parent {
            display: flex;
            justify-content: center;
            align-items: center;
        }

以上三种布局都能够实现元素的水平垂直居中,不难看出,flex布局是最简单的。

所以了解并学习flex布局对于前端学者来说是很有必要的。

一、Flex 布局简介

Flex 弹性布局(Flexbox)是一种用于网页布局的 CSS 技术,旨在使容器内的子元素能够自动调整大小和位置,以适应不同的屏幕尺寸和设备。与传统的布局技术相比,Flexbox 提供了更加灵活、简洁且强大的布局方式,使开发者能够更轻松地实现各种复杂的布局结构。

Flexbox 的核心思想是将容器内的子元素视为可伸缩的弹性盒子,可以根据需要自动调整其大小和位置,以填充可用空间。通过简单的 CSS 属性设置,开发者可以轻松地控制子元素的排列顺序、对齐方式以及相对大小的比例关系,而不需要依赖复杂的浮动和定位技术。

通过给父容器添加flex属性就能够开启弹性布局。子容器可以单独设置自身的排列方式,若果两者同时设置,以子容器的设置为准。

二、Flex 基础概念

flex的基础概念主要包含了容器项目主轴交叉轴

2.1 容器与项目

2.1.1 Flex 容器:

  • Flex 容器是应用了 display: flex;display: inline-flex; 属性的元素,也叫父容器。
  • 这些属性告诉浏览器将容器内的子元素视为 Flex 项目,从而启用 Flexbox 布局模型。
  • Flex 容器创建了一个新的布局上下文,影响其中的子元素的布局方式。

2.1.2 Flex 项目:

  • Flex 容器内的直接子元素被称为 Flex 项目,也就是子容器(item)。
  • 这些项目根据 Flexbox 的规则在容器内排列和布局。
  • Flex 项目的大小和位置可以根据 Flexbox 属性进行调整,以适应不同的布局需求。

2.2 主轴与交叉轴

2.2.1 主轴(Main Axis):

  • 主轴是 Flex 容器的主要方向,决定 Flex 项目的排列方式。
  • 默认情况下,主轴是水平方向(rowx轴),但可以通过设置 flex-direction 属性来改变。
  • Flex 项目沿着主轴排列,其大小和位置受到主轴方向的影响。

2.2.2 交叉轴(Cross Axis):

  • 交叉轴是与主轴垂直的方向,用于控制 Flex 项目在垂直方向上的布局。
  • 默认情况下,交叉轴是垂直方向(columny轴),但同样可以通过设置 flex-direction 属性进行更改。
  • 交叉轴上的对齐方式由 align-itemsalign-self 属性控制。
  • 在 flex 布局中,是分为主轴和交叉轴两个方向,同样的叫法有 : 行和列、x 轴和y 轴,主轴和侧轴
  • 主轴和交叉是会变化的,就看 flex-direction 设置谁为主轴,剩下的就是交叉轴。而我们的子元素是跟着主轴来排列的
flex-direction: 值含义:
row默认值,表示主轴从左到右,水平方向
row-reverse表示主轴从右到左,水平方向
column表示主轴从上到下,垂直方向
column-reverse表示主轴从下到上,垂直方向

三、主轴与交叉轴的设置

<div class="parent">
        <div class="child item1">子元素1</div>
        <div class="child item2">子元素2</div>
    </div>

3.1 flex-direction: row

flex-direction: row 为默认属性,主轴沿着水平方向向右,元素从左向右排列。

image.png

3.3 flex-direction: row-reverse

主轴沿着水平方向向左,子元素从右向左排列

image.png

3.3 flex-direction: column

主轴垂直向下,元素从上向下排列

image.png

3.4 flex-direction: column-reverse

主轴垂直向下,元素从下向上排列

image.png

四、父容器常用属性

在父容器上的属性:

  • display: flex;display: inline-flex;:定义元素为 Flex 容器。
  • flex-direction:指定主轴方向,决定 Flex 项目的排列方向。
  • flex-wrap:定义 Flex 项目在容器中是否换行。
  • justify-content:控制 Flex 项目在主轴上的对齐方式。
  • align-items:控制 Flex 项目在交叉轴上的对齐方式。
  • align-content:控制多行 Flex 项目在交叉轴上的对齐方式。
  • 这些属性作用于父容器,用于控制容器内的 Flex 项目的布局和对齐方式。
<div class="parent">
        <div class="child item1">子元素1</div>
        <div class="child item2">子元素2</div>
        <div class="child item3">子元素3</div>
    </div>

父容器常用属性设置:

4.1 justify-content:主轴上的对齐方式

justify-content 属性用于定义主轴上子元素的排列方式

4.1.1 flex-start

默认值,子元素向 Flex 容器的起始位置靠齐。

image.png

4.1.2 flex-end

子元素向 父 容器的结束位置靠齐。

image.png

4.1.3 center

子元素在 父 容器的中间位置居中对齐。

image.png

4.1.4 space-around

子元素会平均分布在 父 容器内,项目之间的间距相等,且首尾项目距离 父 容器的边缘的距离是其他子元素之间的一半。

image.png

4.1.5 space-between

子元素会平均分布在 父 容器内,首尾项目分别靠近 父 容器的起始和结束位置。

image.png

4.1.6 space-evenly

子元素会平均分布在 父 容器内,包括首尾项目和 父 容器的边缘之间的空间。

image.png

4.2 align-items:交叉轴上的对齐方式

align-items 是用于控制 单行 子元素在交叉轴上的对齐方式。。

以下默认主轴为水平方向向右,记住交叉轴是与主轴垂直哦,默认为垂直向下。

4.2.1 flex-start

默认值,子元素在交叉轴的起始位置对齐。

image.png

4.2.2 flex-end

子元素在交叉轴的结束位置对齐。

image.png

4.2.3 center

子元素在交叉轴的中间位置居中对齐,这里是y轴,y轴默认垂直向下。

image.png

4.2.4 stretch

子元素被拉伸以适应容器的高度或宽度。这是默认的行为,如果子元素没有设置高度或者宽度的话。

image.png

4.3 align-content: 交叉轴上多行子元素的对齐方式

align-content 是应用于 父 容器的属性,用于控制 多行 子元素在交叉轴上的对齐方式。具体来说,当容器内有 多行 子元素时才会生效。

因此需要在 父 容器中添加一个属性flex-wrap: wrap;即当所有子元素的宽度超过父容器时,换行显示。

.parent {
            display: flex;
            flex-wrap: wrap; //换行显示
        }

4.3.1 flex-start

默认值,多行子元素向 父 容器的起始位置靠齐。

image.png

4.3.2 flex-end

多行子元素向 父 容器的结束位置靠齐。

image.png

4.3.3 center

多行子元素在交叉轴的中间位置居中对齐,这里是y轴,y轴默认垂直向下。

image.png

4.3.4 space-around

多行子元素会平均分布在 父 容器内,行与行之间的间距相等,且首尾行距离 父 容器的边缘的距离是其他行之间距离的一半

image.png

4.3.5 space-between

多行子元素目会平均分布在 父 容器内,首尾行分别靠近 父 容器的起始和结束位置。

image.png

4.3.6 stretch

默认行为,多行子元素会被拉伸以填充 父 容器的整个交叉轴。如果子元素具有固定的高度,则会被拉伸至容器高度;否则会根据子元素的最大高度进行拉伸。

image.png

4.4 flex-wrap: 是否换行

flex-wrap 是用于控制子元素是否换行。具体来说,它指定了 父 容器内的子元素是否在一行上排列,或者是否允许它们换行到下一行。

4.4.1 nowrap

默认值,不换行,尽可能地排在一行上。

image.png

4.4.2 wrap

自动换行到下一行,以适应 父 容器的宽度。

image.png

五、子容器常用属性

在子容器上的属性:

  • order:定义 Flex 项目的排列顺序。
  • flex-grow:指定 Flex 项目在空间分配时的放大比例。
  • flex-shrink:指定 Flex 项目在空间不足时的收缩比例。
  • flex-basis:定义 Flex 项目在主轴上的初始大小。
  • flexflex-grow, flex-shrink, 和 flex-basis 的缩写属性。
  • align-self:覆盖父容器的 align-items 属性,单独控制某个 Flex 项目在交叉轴上的对

子容器常用属性设置:

5.1 order 属性

作用:定义子元素的排列顺序,决定了子元素在 父 容器中的显示顺序。数值越小,越靠前。

默认值:0。

.item2 {
    order: -1; //默认值为0,那么给第二个子元素设为-1,它就跑到第一的位置了
}

image.png

5.2 flex 属性

flex 属性定义子元素分配剩余空间,用flex来表示占多少份数。

默认值:0

现在父容器宽度为400px,子元素1和子元素3宽度为100px,剩余宽度给子元素2

.item2 {
    flex: 1; //默认值为0
}

image.png

5.3 align-self 属性

  • align-self:覆盖父容器的 align-items 属性,单独控制某个子元素在交叉轴上的对齐方式。

5.3.1 flex-start

.parent{
    display: flex;
    align-items: center; //父容器我们设置子元素交叉轴上居中
}
.item1 {
    align-self: flex-start; //子元素1我们单独设置起始端对齐
}

image.png

5.3.2 flex-end

.parent{
    display: flex;
    align-items: flex-start; //父容器我们设置子元素交叉轴上起始端对齐
}
.item1 {
    align-self: flex-end; //子元素1我们单独设置末端对齐
}

image.png

5.3.3 center

.parent{
    display: flex;
    align-items: flex-start; //父容器我们设置子元素交叉轴上起始端对齐
}
.item1 {
    align-self: center; //子元素1我们单独设置交叉轴上居中
}

image.png

5.3.4 stretch

.parent{
    display: flex;
    align-items: flex-start; //父容器我们设置子元素交叉轴上起始端对齐
}
.item1 {
    align-self: strtch; //子元素1我们单独设置交叉轴上拉伸
}

item1没有设置高度

image.png

六、实例

实现一个菜单功能,有新增和删除功能,在进行菜单整体布局时,我们会用到flex弹性布局。

//将todoData中的数据渲染出来
function render() { 
    var str = '';
    //遍历
    todoData.forEach(function (item) {
        str += `<li class="item">
        <div class="flex">
            <input type="checkbox" class="item-check">
            <p class="item-content">${item.title}</p>
            <span class="close" data-action="remove" data-id="${item.id}">x</span>
        </div>
    </li>`
    })

    todoList.innerHTML = str
}

  1. todoData.forEach(function (item) { ... }
  • 使用 forEach 方法遍历 todoData 数组中的每个待办事项对象。
  • 对于每个待办事项对象,执行一个匿名函数,参数 item 是当前正在处理的待办事项对象。
  1. str += <li class="item"> ... </li>
  • 在循环中,将每个待办事项对象转换为 HTML 列表项,并追加到 str 变量中。
  • 每个列表项包含一个类名为 item<li> 元素,其中包含一个 Flex 容器 div,包含一个复选框、一个文本段落和一个关闭按钮。
  • 关闭按钮通过 data-action="remove"data-id="${item.id}" 属性附加了删除待办事项所需的动作和标识符。
  1. todoList.innerHTML = str;
  • 在循环结束后,将包含所有待办事项列表项的 HTML 字符串赋值给 todoList 元素的 innerHTML 属性。
  • 这样就将渲染好的待办事项列表插入到页面的相应位置中。
* {
    margin: 0;
    padding: 0;
}
li {
    list-style: none;
}

body {
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
}

.container {
    width: 500px;
    height: 500px;
    margin-top:300px;
    /* border: 1px solid black; */
}
.title {
    text-align: center;
    margin: 10px;
}
.input-group {
    display: flex;
}
.label {
    padding: 5px 10px 5px 10px; /* 上右下左 */
}
.btn {
    padding: 5px 10px;
    margin-left: 10px;
}
.content {
    flex: 1;
}
.item:first-child {
    margin-top: 20px;
}
.item {
    border-bottom: 1px solid #eee;
}
.flex {
    display: flex;
    width: 90%;
    margin: 0 auto;
    align-items: center;

}
.item-check {
    margin-right: 20px;
}
.item-content {
    flex: 1;
}
.close {
    width: 30px;
    height: 30px;
    border: 1px solid gray;
    font-style: 20px;
    text-align: center;
    border-radius: 10px;
    cursor: pointer;
}
  1. .input-group { display: flex; }
  • 这将输入框组内的元素设置为 Flex 布局,使其在水平方向上排列。
  1. .flex { display: flex; ... }
  • 这将具有 flex 类的元素设置为 Flex 布局,使其内部元素在水平方向上居中对齐。
  • width: 90%; 设置了该元素的宽度为父容器宽度的 90%。
  • margin: 0 auto; 让该元素在水平方向上居中对齐。
  • align-items: center; 设置了元素内部元素在交叉轴上的居中对齐。
  1. .item-content { flex: 1; }
  • 这将具有 item-content 类的元素设置为 Flex 布局,使其在主轴上占据剩余空间。

最后

Flex 布局是一种强大的 CSS 布局技术,用于创建灵活的、响应式的布局。通过简单的属性设置,可以实现元素的自动调整大小、对齐和分布,适应不同的屏幕尺寸和设备。核心概念包括弹性容器和弹性项目,通过控制主轴和交叉轴的方向、对齐方式以及弹性增长和收缩,实现各种布局需求。Flex 布局简化了布局代码,提高了开发效率,是构建现代网页布局的首选技术之一。

希望能够帮助你了解flex弹性布局,未来继续学习更加灵活的布局方式,我们拭目以待。