CSS数学函数:calc、min、max、clamp

介绍了一些最受欢迎的CSS数学函数。讨论CSS数学函数的话题,以实现各种布局结果。例如,如何使用几行CSS创建响应式容器,如何添加自适应填充,以及如何使侧边栏真正像侧边栏一样运作。

calc()

calc()函数支持四种算术操作:加法(+)、减法(-)、乘法(*)和除法(/)。该函数主要用于计算容器的动态宽度和高度,以创建自适应布局体验。

1
2
3
4
5
6
7
8
9
10
.calc {
background: #c8e6f5;
padding: 10px 20px;
width: calc(100% - 200px);
}
.no-calc {
background: #c8e6f5;
padding: 10px 20px;
margin-top: 10px;
}
1
2
3
<div class="calc">100% – 200px</div>

<div class="no-calc">Default container width</div>


但是,calc()最突出的地方在于当它用于按照特定值排列元素时。通常,响应式设计是通过寻找特定的断点,然后逐个编写它们的逻辑来实现的。使用calc(),我们只需一个规范就可以实现响应式布局,这使得代码更易于维护。

让我们来看一个具体的例子,使用display: flex;。我们的目标是创建三个并排的元素,它们与容器的宽度(100%)相关联。我们还想在每个元素之间添加30px的间隙,当然,我们需要它是响应式的!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<style>
.calc-container-flex {
display: flex;
justify-content: center;
}
.calc-container-style .item {
background: #fff2ea;
padding: 20px 0;
width: calc((100% - 90px)/3);
text-align: center;

}
.calc-container-style .item + .item {
margin-left: 30px;
}
</style>

<div class="calc-container-flex calc-container-style">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>

因为我们希望每个元素之间有30px的间隙,所以我们从初始容器宽度(100%)中减去90px,然后除以3来指定我们有多少个元素。

当你调整上面的结果大小时,你会注意到所有元素都尊重它们之间的间隙,同时保持对容器宽度的响应。相当不错。

min()

min()函数用于设置最小可接受值。它接受由逗号分隔的2个不同规范,并支持算术表达式。

比如说,你指定了font-size: min(25px,1vw); – 在这个例子中,字体大小永远不会大于25px,并且根据视口大小缩小到1vw。

我们还可以使用min()来调整容器元素的宽度。

1
2
3
4
5
6
7
8
9
10
11
12
13
.min-sample-box-container {
width: 100%;
max-width: 1000px;
}
.min-sample-box {
background: #fff2ea;
padding: 15px 30px;
width: min(70%, 800px);
}

<div class="min-sample-box-container">
<div class="min-sample-box">min() example - 800px limit</div>
</div>

在这个上下文中,尽管容器的最大宽度为1000px,但我们容器内部的div元素的宽度不会超过800px。

max()

max()函数让我们做完全相反的事情。在max()内部的两个值中,较大的那个将被优先考虑。

1
2
3
4
5
6
7
8
9
10
11
12
13
.max-sample-box-container {
width: 100%;
max-width: 1000px;
}
.max-sample-box {
background: #fff2ea;
padding: 15px 30px;
width: max(70%, 200px);
}

<div class="max-sample-box-container">
<div class="max-sample-box">max() example - 200px limit</div>
</div>

如你所见——容器width: 100%;,但不会低于指定的200px标记,因为它是容器的最大值。

max()功能在应用响应式边距时特别有用。通常情况下,当你在布局中使用许多较小的元素时,一旦调整大小,它们就会堵塞屏幕。使用max(),我们可以优先考虑一个特定的边距以适应容器的宽度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.max-margin-container {
display: flex;
flex-wrap: wrap;
width: 100%;
}
.max-margin-container li {
background: #fff2ea;
color: #fff;
padding: 3px 25px;
min-width: 60px;
text-align: center;
margin: 0 max(4px,1vw) max(4px,1vw) 0;
}

<ul class="max-margin-container"><li>calc()</li><li>min()</li><li>max()</li><li>clamp()</li>
<li>sin()</li><li>cos()</li><li>tan()</li><li>acos()</li><li>asin()</li><li>atan()</li>
<li>atan2()</li><li>hypot()</li><li>sqrt()</li><li>pow()</li></ul>

尽管视口的宽度变化了,按钮始终保持着4px的边距。

clamp()

clamp()函数用于定义布局元素各种值的可接受范围:最小值、首选值和最大值。通常情况下,clamp()用于为字体设置一系列可接受的值,以创建流体字体的效果。

从本质上讲,它是min()max()功能的结合体。

一个例子:

1
font-size: clamp(1rem, 4vw + 1rem, 4rem);

这是它的样子:

在这个上下文中,我们用1rem的最小值样式化我们的h2标题,用4rem的最大值样式化,并将我们的首选大小设置为4vw(视口单位)+1rem。当我们的视口变化时,标题的字体大小也随之变化。
总的来说,我们的重点是创建响应式设计元素,否则需要通过媒体查询来编写。

使用网格创建响应式侧边栏

用2行CSS实现一个完全功能的响应式侧边栏吗?
使用display: grid;创建一个响应式侧边栏,并使用grid-template-columns来定制响应性。具体来说,我们将使用fit-contentminmax()函数来设置我们的约束。

1
2
3
4
.grid-sidebar-demo {
display: grid;
grid-template-columns: fit-content(25ch) minmax(min(55vw, 35ch), 1fr)
}

应用fit-content来声明我们侧边栏的首选大小。我们在这里指定的值会根据视口大小推动侧边栏的增长或在较小的屏幕上收缩。同时考虑到您在侧边栏中的内容量。
使用minmax(),因为我们不希望侧边栏与页面上的内容区域重叠。在我们的例子中,我们设置了55vw用于移动显示,35ch用于更大的视口。最后,当视口允许时,我们应用网格特定的分数单位来填充空间。

Flexbox布局的响应式

这是一个响应式填充的示例。但是我们使用flexboxgap属性以及clamp()函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.gap-boxes-container {
display: flex;
flex-wrap: wrap;
gap: clamp(5px, 1vw, 25px);
place-content: center;
}

.gap-box {
display: inline-flex;
width: 100px;
height: 100px;
background-color: #fff2ea;
align-items: center;
justify-content: center;
}

<div class="gap-boxes-container">
<div class="gap-box">1</div>
<div class="gap-box">2</div>
<div class="gap-box">3</div>
<div class="gap-box">4</div>
</div>


通过指定gap: clamp(5px, 1vw, 25px);,我们告诉浏览器根据视口大小调整每一列之间的间距。因此,如果窗口超过1vw——间隔将增加到25px,而较小的视口将把它减少到5px(例如,在移动设备上)。

顺便说一下,你可能已经注意到我使用了一个有趣的属性来居中容器框,那就是place-content: center;。这是一个支持各种方向的内容定位的简写属性。`

Can I Use


我们可以在没有媒体查询的情况下完成大部分响应式样式,他们想要编写代码,而不用担心各种设备之间的兼容性问题。