回想过去,CSS 需要兼容各种版本的浏览器,那种在效果和可用之间痛苦选择的经历记忆犹新。现在的 CSS 能够做很多事情,而对于浏览器的兼容性只需考虑主流的,并且大部分主流的浏览器都支持最新 CSS 特性。本文来总结一下CSS中数学函数之min
、max
、calc
、clamp
。
min()
min()
的用途:以一种包含元素响应上下文的方式设置最大允许值的边界。这看起来和名称有点相反,但结果是提供的值将作为属性的最大允许值。
给定宽度:min(80ch,100vw)
,结果是在更大的视窗中,将选择 80ch
,因为它是两个选项中的较小值,但它的作用类似于基于上下文可用空间的最大值。一旦视口缩小,将使用值 100vw
,因为它被计算为小于 80ch
,但它实际上为元素的宽度提供了一个最大边界。
.container
类
刚才提供的示例是新的定义 .container
的方法,只做了一个小小的调整。min()
函数允许嵌套的基本数学运算,这意味着可以翻转来减去一些空间,作为定义左右填充的交换,如下所示:
.container { width: min(80ch, 100vw - 2rem); }
在较大的视窗中(即宽度超过80ch
),该元素可以宽度扩展到最大的 80ch
,并且一旦该宽度下面视窗缩小,小于 80ch
的时候,宽度将使用 100vw - 2rem
,相当于定义了在元素每一侧“填充” 1rem
。
在此示例中,还可以将元素改为 100%
而不是vw
使其响应父元素的宽度:
.container { width: min(40ch, 100% - 2rem); margin-right: auto; margin-left: auto; }
这样定义的好处是无需媒体查询即可响应调整大小。
除了上述用法,还可以用于背景定义,如下:
.background-image { background: #efefef url(https://crayon.devpoint.cn/assets/images/bgs/main.jpg) no-repeat center; background-size: min(800px, 100%); }
上面代码实现的效果是:当视窗宽度超过 800px
时,背景最大宽度为 800px
,当宽度小于 800px
的时候,背景的宽度就是 100%
。
max()
max()
的用途:以包含元素响应上下文的方式设置最小允许值的边界。是上面介绍的 min()
的反义词,下面来看看实例。
定义上下文边距
如果桌面尺寸为 1280px
,放大 4 倍,那么内容相当于 320px
的设备。然而,与移动电话相比,它的方向仍然是横向的。这种大小的视窗意味着读取和执行操作的区域大大减少。此外,在放大窗口中查看时,看起来适合手机的尺寸会变得很大。max()
提供了更优雅地处理边界的方法,在移动适配方面通常使用 rem
作为尺寸单位。但对于用于分隔内容部分的较大空间,使用了以下方法,允许高视图相对增长,并减少较短视图的距离,这适用于缩放视图。
.element + .element { margin-top: max(8vh, 2rem); }
上面的样式,在较高的视窗中,8vh
将被使用,在较小或放大的视窗中,2rem
将被使用。对于有缩放功能,并需要适配各种移动终端的功能上,使用这种方式可以对最终用户产生重大影响。
在iOS中使用防止浏览器放大输入框文字
是否经历过在iOS上聚焦表单输入时强迫浏览器缩放的情况?对于任何字号小于 16px
的输入,都会出现这个结果。使用 max() 可以简单的解决这个问题:
input { font-size: max(16px, 1rem); }
上面的代码 max()
的使用确保了无论提供的是什么值,字体大小都至少为 16px
,从而防止浏览器被迫缩放。
calc()
calc()
的用途:执行基本的数学运算,常用于动态计算高宽值,支持 + - * /
运算,能够在单位类型之间进行插值(例如 rem 到 vw),实际项目中主要用于自适用窗口的大小。
例如,页面的内容区为除导航高度之外的全部窗口大小,过去常用 position: absolute;
来实现自适应高度,使用 calc()
简洁多了。
.content { height: calc(100vh - 80px); }
当窗口调整大小或在更大分辨率又或者手机端时,100vh
的值将动态更新,因此高度也随之变化。
生成调色板
可以通过传入CSS自定义属性来扩展 calc()
的功能。一个非常有用的例子是使用 hsl()
创建一致的调色板。给定饱和度、亮度和起始色调的值,计算互补值以构建完整的调色板。
.colors { --base-hue: 140; --saturation: 95%; --lightness: 80%; --rotation: 60; color: #222; text-align: center; } .color { padding: 0.25rem; background-color: hsl(var(--hue), var(--saturation), var(--lightness)); } .color1 { --hue: calc(var(--base-hue)); } .color2 { --hue: calc(var(--base-hue) + var(--rotation)); } .color3 { --hue: calc(var(--base-hue) + var(--rotation) * 2); }
clamp()
clamp()
的用途:在可接受的值范围上设置边界,作用是把一个值限制在一个上限和下限之间,当这个值超过最小值和最大值的范围时,在最小值和最大值之间选择一个值使用。
clamp()
函数接收三个参数,并且需按照以下顺序。
- 范围内的最小值
- 理想值/首选值
- 范围内的最大值
可能已经遇到过使用 clamp()
的一个领域是用于流体排版。其基本概念是,字体大小值可以根据视口大小灵活地调整,这是为了防止大标题触发溢出,或占用太多的视窗。
流体 h1
样式的一个非常基本的定义:
h1 { font-size: clamp(1.75rem, 4vw + 1rem, 3rem); }
相对响应填充
使用百分比作为填充的有趣之处在于它是相对于元素的宽度的,意味着它有点像容器相关的单位,可以使用 vw。
下面的实例使用了以下填充定义,其中填充将相对于元素的宽度增长和收缩。它永远不会小于 1rem
,也永远不会大于 3rem
:
.element { padding: 1.5rem clamp(1rem, 5%, 3rem); }
与媒体查询相比,这个填充的最大好处是,由于这个填充定义是相对于元素的,当元素在页面上有更多空间时,它就会变大,而如果元素被放置在狭窄的列中,它就会变小。这需要与基于媒体查询的实用程序类进行大量的协调。