介绍
记录现代css对布局和功能的实现
# grid垂直居中
- 现代css居中 可以通过 Grid (opens new window) 或 Flexbox (opens new window) 实现垂直居中
- grid (opens new window) 配合 place-items (opens new window) 简写属性(
align-items
(opens new window) 和justify-items
(opens new window)的简写) 实现快速垂直居中 - 注意: place-items (opens new window) 十分具有诱导性 通常在
flex
实现垂直居中 使用的是justify-content
并非justify-items
所以这个简写属性 在flex
布局中需要注意 但在Grid
可以放心直接使用
- grid (opens new window) 配合 place-items (opens new window) 简写属性(
展示效果
实现代码
<template>
<div class="allBox">
<div class="inBox" />
</div>
</template>
<style lang="scss" scoped>
.allBox {
// 核心代码
display: grid;
place-items: center;
// 辅助代码
width: 100%;
height: 100vh;
background-color: #abe2e5;
.inBox {
width: 200px;
height: 200px;
background-color: #eabda3;
}
}
</style>
# 煎饼式布局
- 有一行 3 个项目,通常带有图像、标题,然后是一些描述产品某些功能的文本。在移动设备上,我们希望它们能够很好地堆叠,并随着我们增加屏幕尺寸而扩展。
- 通过使用
Flexbox
实现此效果,您不需要在屏幕尺寸发生变化时通过媒体查询来调整这些元素的位置。
# 了解flex相关属性
- flex (opens new window)属性是
flex-grow
(opens new window),flex-shrink
(opens new window) 和flex-basis
(opens new window)的简写,默认值为0 1 auto
。后两个属性可选。
flex-grow属性
flex-grow
(opens new window)属性定义项目的放大比例,默认为0
,即如果存在剩余空间,也不放大。
.item {
flex-grow: <number>; /* default 0 */
}
- 如果所有项目的
flex-grow
属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow
属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。
flex-shrink属性
flex-shrink
(opens new window)属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
.item {
flex-shrink: <number>; /* default 1 */
}
- 如果所有项目的
flex-shrink
属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink
属性为0,其他项目都为1,则空间不足时,前者不缩小。 - 负值对该属性无效。
flex-basis属性
flex-basis
(opens new window)属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto
,即项目的本来大小。
.item {
flex-basis: <length> | auto; /* default auto */
}
- 它可以设为跟
width
或height
属性一样的值(比如350px
),则项目将占据固定空间。
flex属性
- flex (opens new window)属性是
flex-grow
,flex-shrink
和flex-basis
的简写,默认值为0 1 auto
。后两个属性可选
.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
- 该属性有三个快捷值:
auto
(1 1 auto
)none
(0 0 auto
)initial
(flex: 0 1 auto
)auto
元素会根据自身的宽度与高度来确定尺寸,但是会伸长并吸收 flex 容器中额外的自由空间,也会缩短自身来适应 flex 容器。这相当于将属性设置为 "flex: 1 1 auto
"none
元素会根据自身宽高来设置尺寸。它是完全非弹性的:既不会缩短,也不会伸长来适应 flex 容器。相当于将属性设置为"flex: 0 0 auto
"。initial
元素会根据自身宽高设置尺寸。它会缩短自身以适应 flex 容器,但不会伸长并吸收 flex 容器中的额外自由空间来适应 flex 容器 。相当于将属性设置为"flex: 0 1 auto
"。
- 建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
# 实现煎饼式布局
- 如果您想让您的框填充到它们的
<flex-basis>
大小,缩小到更小的尺寸,但不拉伸以填充任何额外的空间,请写入:flex: 0 1<flex-basis>
。在这种情况下,您的<flex-basis>
是150px
,也就是flex: 0 1 150px;
展示效果
实现代码
<template>
<div class="parent">
<div class="child" />
<div class="child" />
<div class="child" />
</div>
</template>
<style lang="scss" scoped>
.parent {
// 核心代码
display: flex;
flex-wrap: wrap;
justify-content: center;
// 辅助代码
gap: 30px;
background-color: #abe2e5;
width: 100%;
height: 300px;
.child {
flex: 0 1 150px;
background-color: #eabda3;
}
}
</style>
- 如果您确实希望框在换到下一行时拉伸并填充空间,请将
<flex-grow>
设置为 1 ,也就是flex: 1 1 150px;
- 当您增加或减少屏幕尺寸时,这些
flex
项目会缩小和增长。
展示效果
实现代码
.child {
flex: 1 1 150px;
background-color: #eabda3;
}
# 侧边栏布局
- 通过grid (opens new window)布局 使用 minmax() (opens new window) 函数和grid-template-columns (opens new window) 定义每一列的列宽。我们在这里做的是将最小侧边栏大小设置为
150px
,但在更大的屏幕上,让它伸展出25%
。侧边栏将始终占据其父级水平空间的25%
,直到25%
变得小于150px
。minmax()
函数产生一个长度范围,表示长度就在这个范围之中都可以应用到网格项目中。它接受两个参数,分别为最小值和最大值- 也就是说最大不会超过最大值,最小不能小过最小值 可以把他理解为
min-width
max-width
展示效果
实现代码
<template>
<div class="allBox">
<div class="left" />
<div class="right" />
</div>
</template>
<style lang="scss" scoped>
.allBox {
// 核心代码
display: grid;
grid-template-columns: minmax(150px, 25%) 1fr;
.left {
// 辅助代码
height: 500px;
background-color: #abe2e5;
}
.right {
// 辅助代码
height: 500px;
background-color: #eabda3;
}
}
</style>
# 煎饼堆栈布局
- 和解构煎饼式布局 不同,当屏幕尺寸改变时,本例不会包含它的子元素。通常称为粘性页脚,这种布局通常用于网站和应用程序,跨多个移动应用程序(页脚通常是工具栏)和网站(单页应用程序通常使用这种全局布局)
- 通过
grid
布局 设置grid-template-rows (opens new window) 属性 设置其内部每个元素的行高 1fr
页眉和页脚内容设置为自动采用其子项的大小fr
可以将容器等分当只存在一个1fr
为占满效果,并将剩余空间 (1fr
) 应用于主区域,而auto调整大小的行将采用其子项的最小内容的大小,以便该内容大小增加,行本身将增长以进行调整。
展示效果
实现代码
<template>
<div class="allBox">
<header>
<h1>头部</h1>
</header>
<main>主要内容</main>
<footer>页尾</footer>
</div>
</template>
<style lang="scss" scoped>
.allBox {
// 核心代码
display: grid;
grid-template-rows: auto 1fr auto;
// 辅助代码
height: 100vh;
}
// 煎饼堆栈布局内部元素
header {
background: lightpink;
padding: 2rem; // 或者设置height 撑开容器
}
main {
background: coral;
}
footer {
background: wheat;
padding: 2rem; // 或者设置height 撑开容器
text-align: center;
}
</style>
# 经典圣杯布局
- 通过
grid
布局 设置grid-template (opens new window) 设置父元素的行和列的值 在给内部的子元素设置grid-column (opens new window) 指定其自身大小和位置grid-template
和grid-column
设置两个值需要/
分隔符- 属性和值对为:
grid-template: auto 1fr auto / auto 1fr auto
。第一个和第二个以空格分隔的列表之间的斜线是行和列之间的分隔符。
展示效果
实现代码
<template>
<div class="allBox">
<header>
<!-- contenteditable可以允许用户选中 并进进行编辑 -->
<h1 contenteditable>头部</h1>
</header>
<div class="left-sidebar" contenteditable>左边栏</div>
<main contenteditable />
<div class="right-sidebar" contenteditable>右边栏</div>
<footer contenteditable>页尾</footer>
</div>
</template>
<style lang="scss" scoped>
.allBox {
// 核心代码
display: grid;
grid-template: auto 1fr auto / auto 1fr auto;
// 辅助代码
height: 100vh;
}
// 圣杯布局的内部元素
header {
background: lightpink;
padding: 2rem;
grid-column: 1 / 4; // 设置他的列宽 从网格线1到网格线3 也就是到横着第二个单元格的右侧
}
.left-sidebar {
background: lightblue;
grid-column: 1 / 2;
}
main {
background: coral;
grid-column: 2 / 3;
}
.right-sidebar {
background: yellow;
grid-column: 3 / 4;
}
footer {
background: wheat;
padding: 2rem;
text-align: center;
grid-column: 1 / 4;
}
.left-sidebar,
.right-sidebar {
padding: 1rem;
}
</style>
# 12 跨网格布局
- 12 跨网格。您可以使用repeat() (opens new window) 函数在 CSS 中快速编写网格(省略重复片段)。对网格模板列使用
repeat(12, 1fr)
将为每个1fr
提供 12列。- 通过grid-template-columns (opens new window) 定义父元素一行 均分12列
repeat(12, 1fr)
然后子元素通过grid-column
定义其占比 grid-column: 1 / 13
将跨越从第一到最后一行(第 13 行)并跨越 12 列。grid-column: 1 / 5
将跨越前四个列(有点类似于 js中的索引0 和 长度1的概念)- 使用
span
关键字。使用span
,您可以设置起始线,然后设置从该起点跨越的列数。在这种情况下,grid-column: 1 / span 12
将等效于grid-column: 1 / 13
,而grid-column: 2 / span 6
将等效于grid-column: 2 / 8
。
- 通过grid-template-columns (opens new window) 定义父元素一行 均分12列
实现效果
实现代码
<template>
<div class="allBox">
<!-- 设置均分元素 -->
<div class="span-12">Span 12</div>
<div class="span-6">Span 6</div>
<div class="span-4">Span 4</div>
<div class="span-2">Span 2</div>
</div>
</template>
<style lang="scss" scoped>
.allBox {
// 核心代码
display: grid;
grid-template-columns: repeat(12, 1fr);
}
// 均分元素
div {
display: grid;
padding: 2rem;
place-items: center;
}
.span-12 {
background: lightpink;
grid-column: 1 / 13;
}
.span-6 {
background: lightblue;
grid-column: 1 / 7;
}
.span-4 {
background: coral;
grid-column: 4 / 9;
}
.span-2 {
background: yellow;
grid-column: 3 / 5;
}
</style>
- 使用
span
关键字。使用span
,您可以设置起始线,然后设置从该起点跨越的列数。在这种情况下,grid-column: 1 / span 12
将等效于grid-column: 1 / 13
,而grid-column: 2 / span 6
将等效于grid-column: 2 / 8
。
.span-12 {
background: lightpink;
grid-column: 1 / span 12;
}
.span-6 {
background: lightblue;
grid-column: 1 / span 6;
}
.span-4 {
background: coral;
grid-column: 4 / span 4;
}
.span-2 {
background: yellow;
grid-column: 3 / span 2;
}
# RAM 子响应式布局
创建具有自动放置且灵活的子项的响应式布局。漂亮整齐。这里要记住的关键点是
repeat
、auto-(fit|fill)
和minmax()
(opens new window),可以记住它们的首字母缩写词 RAM。repeat(长度/自身属性, 长度单位并支持minmax()长度范围)
(opens new window) 函数复写 帮我们实现等分复写 支持指定次数的复写 当我们设置指定属性的时候 也可以自动复写repeat()
支持自动重复 不一定非要指定次数 当我们给自身长度设置为auto-fill
或auto-fit
时候 可以自动重复 例如:repeat(auto-fill, 250px)
auto-fit
效果几乎和auto-fill
一样。 不同点仅在于,当容器的大小大于各网格项之和时,auto-fill
会持续地在一端放入空行或空列,这样就会使所有网格项挤到另一边;而auto-fit
则不会在一端放入空行或空列,而是会将所有网格项拉伸至合适的大小。
- 使用
auto-fit
,当它们的水平尺寸超过150px
时,框将拉伸以填充整个剩余空间。但是,如果您将其更改为auto-fill
,则当超出minmax
函数中的基本大小时,它们将不会拉伸 minmax()
可以自动放置这些子元素。这些子元素的基本最小值为 150px ,最大值为 1fr ,这意味着在较小的屏幕上,它们将占据整个 1fr 宽度,当它们达到 150px 宽度时,它们将开始流到同一条线上。- 不要给子元素设置
weight
固定宽度 子元素的宽度会根据minmax()
自适应分配
展示效果
实现代码
<template>
<div class="allBox">
<!-- 设置子元素相应式布局 -->
<div class="sonBox">1</div>
<div class="sonBox">2</div>
<div class="sonBox">3</div>
<div class="sonBox">4</div>
<div class="sonBox">1</div>
<div class="sonBox">2</div>
<div class="sonBox">3</div>
<div class="sonBox">4</div>
<div class="sonBox">1</div>
<div class="sonBox">2</div>
<div class="sonBox">3</div>
<div class="sonBox">4</div>
</div>
</template>
<style lang="scss" scoped>
.allBox {
height: 100vh;
// 核心代码
display: grid;
gap: 30px;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
// 子元素的设置
.sonBox {
// 给子元素内部设置垂直水平居中
display: grid;
place-items: center;
background: lightpink;
}
}
</style>
# 排列布局
- 我们可以规定
flex
布局的排版方式 实现我们的效果 flex布局默认的排版方式是一行显示 通过flex-direction (opens new window)指定了内部元素是如何在 flex 容器中布局的,定义了主轴的方向 (正方向或反方向)。row
默认值flex
容器的主轴被定义为与文本方向相同。主轴起点和主轴终点与内容方向相同。(从右往左)row-reverse
表现和row
相同,但是置换了主轴起点和主轴终点 (从左往右)column
让flex
容器的主轴和块轴相同。主轴起点与主轴终点和书写模式的前后点相同 (从上到下)column-reverse
表现和column
相同,但是置换了主轴起点和主轴终点 (从下倒上)
实现效果
实现代码
<template>
<div class="allCard">
<div class="card">
<h1>Title - Card 1</h1>
<p>第一个盒子</p>
<div class="visual" />
</div>
<div class="card">
<h1>Title - Card 2</h1>
<p>第二个盒子</p>
<div class="visual" />
</div>
<div class="card">
<h1>Title - Card 3</h1>
<p>第三个盒子</p>
<div class="visual" />
</div>
</div>
</template>
<style lang="scss" scoped>
.allCard {
display: grid;
grid-gap: 1rem;
grid-template-columns: repeat(3, 1fr);
.visual {
height: 100px;
width: 100%;
background: wheat;
margin: 0.5rem 0;
}
.card {
display: flex;
// 设置flex-direction 改变flex 容器中的布局效果column让其从上到下的排布效果
flex-direction: column;
justify-content: space-between;
background: lightpink;
padding: 1rem;
}
}
</style>
# clamp函数
- clamp() (opens new window) 函数的作用是把一个值限制在一个上限和下限之间,当这个值超过最小值和最大值的范围时,在最小值和最大值之间选择一个值使用。它接收三个参数:最小值、首选值、最大值。
clamp(MIN, VAL, MAX)
其实就是表示max(MIN, min(VAL, MAX))
他是一个类似于语法糖的css属性clamp
取三个值。第一个是最小值,第二个是首选值,第三个是最大值。- 钳位函数将返回首选值,除非它小于最小值(在这种情况下它将返回最小值)或者如果它大于最大值,在这种情况下它将返回最大值.
举个例子
.css-clamp {
width: clamp(200px, 50vw, 300px)
}
从上面的 gif 里可以比较明显的感觉到,在不断调整浏览器大小的过程中:
当屏宽超过 600px 时,粉红色区域长度固定
而屏宽介于 400px 和 600px 之间时,粉色区域按照屏宽等比例变换
直到屏宽小于 400px 后,粉红区域又趋向固定。
这就是 clamp 的效果,它接受三个参数,分别是最小值、首选值和最大值;返回值默认是首选值,但是超出边界后返回最小值或最大值。还是以
clamp(200px, 50vw, 300px)
为例:当屏宽小于 400px 时,首选值(50vw)小比下限(200px),所以返回最小值(200px)
当屏宽介于 400px 和 600px 之间时,首选值(50vw)介于最小值(200px)和最大值(300px)之间时,返回首选值(50vw)
当屏宽大于 600px 时,首选值(50vw)大比上限(300px),使用最大值(300px)
简单来说,
clamp(MIN, VAL, MAX)
等价于max(MIN, min(VAL, MAX))
。上文提到,min
和max
可以简化一些媒体查询的代码;clamp 作为更复杂的方法,“语法糖”效果就更明显了,我们看看如下用媒体查询来实现clamp(200px, 50vw, 300px)
的效果的代码量,clamp
的优势就可见一斑了:
.example {
width: 50vw;
}
@media ( min-width: 600px ) {
.css-min {
width: 300px;
}
}
@media ( max-width: 400px ) {
.css-min {
width: 200px;
}
}
除了可以应用到 width
、margin
、font-size
这种比较常见的长度单位(Length)计算上,clamp
还可以在以下几个数据类型上使用:
percentage
:表示一个百分比,经常用以根据父对象来确定大小angle
:用于颜色渐变、动画等相关属性上,单位有 degrees,gradians,radians,turnstime
:用于 animations、transition 等相关属性,单位有秒(s)和毫秒(ms)number
:用于 CSS 变量(如::root{ --size: min(8px, 1rem) }
)frequency
:表示频率维度,如语音的高低,单位有赫兹(Hz)和千赫兹(KHz)
# 实现纵横比设置
- 在游戏中 经常可以设置一些 纵横/宽高比 比如
21:9
16:9
或者4:3
# 什么是纵横比
- 通过设置aspect-ratio (opens new window) 为 box 容器规定了一个期待的纵横比( 比如 16 x 9)。当容器大小改变的时候 保持指定的纵横比
- 随着响应式设计的到来,对于Web开发人员而言,保持宽高比已变得越来越重要,尤其是当图像尺寸不同且元素大小根据可用空间而变化时。
- 创建自适应iframe (opens new window),它们是父级宽度的100%,高度应保持特定的视口比例
- 为图像,视频和嵌入创建内在的占位符容器,以防止在项目加载并占用空间时重新布局
- 为交互式数据可视化或SVG动画创建统一的、响应式空间
- 为多元素组件(如卡片或日历日期)创建统一、响应的空间
- 为不同尺寸的多个图像创建统一的响应空间(可与 object-fit (opens new window) 元素自适应的方式 配合使用)
# 实现效果
- 使用
aspect-ratio
属性,当我调整卡片大小时,绿色视觉块保持 16 x 9 的宽高比。我们通过aspect-ratio: 16 / 9
保持此宽高比。
.video {
aspect-ratio: 16 / 9;
}
- 可以使用 1 / 1 的比例制作正方形,使用 2 / 1 制作 2:1 比例。可以设置任何图像缩放比例。
.square {
aspect-ratio: 1 / 1;
}
- 还可以指定宽度
width
或height
然后设置纵横比 实现理想的图片展示效果 这样只需要设置一个单位 就可以实现不错的展示效果
.image{
width: 100px; /** 设置固定的宽度 在设置纵横比 **/
aspect-ratio: 16 / 9;
}
- 另一方面,使用
aspect-ratio
创建占位符以防止此布局偏移:通常在<img>
图片标签 进行设置 在未加载成功时候占位
img {
width: 100%;
aspect-ratio: 8 / 6;
}
# 参考文献
完整视频:https://www.youtube.com/watch?v=qm0IfG1GyZU
演示:https://1linelayouts.glitch.me/
CSS clamp 函数 101 (opens new window)