CSS函数min、max和clamp
本帖最后由 马黑黑 于 2025-4-3 19:47 编辑 <br /><br /><style>.artbox p { margin: 10px 0; font-size: 16px; }
.artbox div { box-sizing: border-box; margin-top: 10px; margin-bottom: 10px; }
.resize { margin: auto; padding: 0; width: 600px; min-width: 100px; height: fit-content; resize: horizontal; overflow: auto; border: 1px solid gray; }
.fitsize1 { width: min(50%, 200px); background: tan; padding: 8px; }
.fitsize2 { width: min(50%, 400px); background: pink; padding: 8px; }
.fitsize3 { width: max(50%, 200px); background: tan; padding: 8px; }
.fitsize4 { width: max(50%, 400px); background: pink; padding: 8px; }
.fitsize5 { width: max(350px, min(50%, 500px)); background: silver; padding: 8px; }
.fitsize6 { width: clamp(350px, 50%, 500px); background: lightblue; padding: 8px; }
.tRed { color: red; }
</style>
<div class="artbox">
<p>当我们给一个元素设置最小、最大宽度,我们自然而然会想到使用 min-width 和 max-width 这两个CSS属性。前缀 min 和 max 分别是最小、最大之意。实际上,CSS 有 min 函数和 max 函数,使用它们我们不仅仅可以设置元素的尺寸,凡可用数值参与表达的属性,都可以通过它们设置最小值和最大值。先来看看 min 函数:</p>
<div class="resize">
<div class="fitsize1">width: min(50%, 200px);</div>
<div class="fitsize2">width: min(50%, 400px);</div>
</div>
<p>min() 函数支持单值或多值,如果是多值,下一个值与上一个值之间用逗号隔开。<span class="tRed">多值的时候,浏览器会在这些值当中选取最小的那个值渲染元素对应属性</span>。例如上例,由于受到父元素 600px 的宽度限制,棕褐色 div 所提供的 min(50%, 200px) 两个值当中,50% 为 300px,显然大于 200px,浏览器选择 200px 作为棕褐色盒子的最终宽度。而粉红色的 div min() 函数参数值是 50% 和 400px,后者大于 50% 所得的 300px,故浏览器以二者中最小的 50% 即 300px渲染粉红色盒子的宽度。上例中,可以尝试拖曳父元素右下角缩小其宽度,我们会发现两个子元素最终均以父元素 50% 的宽度呈现,这是因为 min() 函数的第二个参数值大于 50% 计算出来的值,所以只能以 50% 为最终宽度;往大里拖曳父元素,粉红色尺寸也会发生改变,直到其宽度等于 400px,这是因为当父元素的宽度的一般大于 400px 时,粉红色盒子使用最小的 min() 函数参数值作为自己的最终宽度。</p>
<p>从功能上看,min() 函数用来限制元素指定属性的最小渲染值,函数在执行的时候,浏览器在函数参数值中选取值最小的值返回给元素。max() 函数也是此理,不同的是,它用于限制元素指定属性的最大值、浏览器会从中选取值最大的那个返回给元素。看演示:</p>
<div class="resize">
<div class="fitsize3">width: max(50%, 200px);</div>
<div class="fitsize4">width: max(50%, 400px);</div>
</div>
<p>上述演示,棕褐色盒子使用 max(50%, 200px) 来限制盒子的最终宽度:当 50% 小于 200px,返回 200px 给元素,反之,当 50% 换算后大于 200px,则返回 50% 给元素。粉红色使用的是 max(50%, 400px),原理与上同。可以尝试改变父元素的宽高查看 50% 与 200px、400px 的大小关系以及元素总是以最大那个值渲染宽度的原则。</p>
<p>可以嵌套使用 min()、max() 函数来规定一个元素的最小值和最大值。以下演示,银白色的盒子使用 max 函数提供两个值宽度值,红色部分是其中的一个值,浏览器将在这两个值之间选取最大的那个;红色值实际上是不确定的,它由 min 函数提供,浏览器将在其内两个值之间选取最小的那一个给前面的 max 函数作比较,最终才定夺使用哪一个值渲染盒子的宽度,可以拉大父元素观察效果:</p>
<div class="resize">
<div class="fitsize5">width: max(350px, <span class="tRed">min(50%, 500px)</span>);</div>
</div>
<p>而实现上面的效果,CSS有专门的函数,clamp(<span class="tRed">最小值, 首选值, 最大值</span>):</p>
<div class="resize">
<div class="fitsize6">clamp(350px, 50%, 500px);</div>
</div>
<p>不要被 clamp 函数第二个参数名称 <span class="tRed">首选值</span> 所误导,它实际上是最小值和最大值之间的弹性值。具体来说,浏览器这样做检测:当 50% 换算所得的值小于最小值,就返回最小值,当 50% 换算所得的值大于最大值,就返回最大值,若 50% 换算所得值在最小值和最大值之间,就返回 50% 换算值。所以,缩小父元素,浅蓝色盒子保持最低宽度为 350px,放宽父元素,在父元素宽度的一半没有达到 500px 之前,子盒子都在加大自己的长度,直至加到 500px 就不会再加。</p>
<p>上述两个演示是等效的,但在 clamp 函数出生以前,老前端程序员们能够使用的唯一方法是 min、max 的嵌套组合。</p>
<p>min、max、clamp 等函数有着广泛的应用场景。我们以 clamp 为例,通过它,希望帖子最小尺寸为 800 * 400、最大尺寸为 1400 * 760,并能在这二者间自适应。看代码:</p>
<div id="hEdiv"><pre id="hEpre">
<style>
#tz {
position: absolute;
width: clamp(800px, 90vw, 1400px);
height: clamp(460px, 90vh, 760px);
left: 50%;
transform: translate(-50%, 20px);
background: #eee;
border: 2px solid teal;
}
</style>
<div id="tz"></div>
</pre></div>
<p><button id="showRes">点击查看效果</button></p>
<p>最后强调:使用 min、max、clamp 这三个函数的元素是基于父元素的,就是说,它们的参照为父元素的相关属性设置。父元素可以是上一层的某个 HTML 标签,例如,div、body 等。</p>
</div>
<script type="module">
import hlight from 'https://638183.freep.cn/638183/web/mod/helight.js';
hlight.hl(hEdiv, hEpre);
showRes.onclick = () => {
const value = hEpre.textContent;
const previewWindow = window.open('', 'prev', 'width=1024,height=640,left=200,top=200');
previewWindow.document.open();
previewWindow.document.write(value);
setTimeout(function(){previewWindow.document.title = "预览"}, 100);
previewWindow.document.close();
};
</script> max(50%, 200px) 说明中,反之后那句应这个是返回50%吧。
这个取最大值的时候,如果父框太小,还会出现滚动条 width: max(350px, min(50%, 500px));限于350和500之间了。。这嵌套还挺有意思的。。发明这个的也是神人
下面的clamp更好玩,就确定一个范围跑不掉了。。
clamp代替嵌套,真是越来越先进 最后这个直观演示好啊,分明就是演示贴子怎么自适应屏幕大小啊。。。
预览开始界面是800*460,最大化后就变1400*760,拖拉界面可以看到 变化过程。。。
这样无论浏览器边框界面大小都能按比例完美显示。。
好智能的设计。。咋这么聪明涅 90vw,90vh这啥意思呀,为何不是上面例子中的百分比。。{:4_173:} 花飞飞 发表于 2025-4-3 19:13
max(50%, 200px) 说明中,反之后那句应这个是返回50%吧。
这个取最大值的时候,如果父框太小,还会出现滚 ...
额,是的,改了。谢谢 花飞飞 发表于 2025-4-3 19:19
width: max(350px, min(50%, 500px));限于350和500之间了。。这嵌套还挺有意思的。。发明这个的也是神人
...
它是后面一点出来的 花飞飞 发表于 2025-4-3 19:26
最后这个直观演示好啊,分明就是演示贴子怎么自适应屏幕大小啊。。。
预览开始界面是800*460,最大化后就 ...
最主要的,它是可以适配不同显示设备的 花飞飞 发表于 2025-4-3 19:27
90vw,90vh这啥意思呀,为何不是上面例子中的百分比。。
vw,vh,分别代表屏幕的横向、纵向尺寸单位,1vw = 1% 个屏幕横向距离,1vh = 1% 个屏幕纵向距离 clamp 就是那个嵌套的表达吧,那个例子中,当宽度在800和1400之间,就直接显示为90vw,高度也如此。
这个自适应挺好的,不用考虑设置的过大或过小了。{:4_204:} 貌似也有问题,当自己的图图是竖版的,会不会直接被变成横版了啊{:4_173:} 这些判断都可以交给电脑了,太省力了,这些函数厉害了{:4_187:} 马黑黑 发表于 2025-4-3 19:47
额,是的,改了。谢谢
好不容易不是JS的,没那么吓人,一不小心就看进去了。{:4_173:} 马黑黑 发表于 2025-4-3 19:47
它是后面一点出来的
函数也很神奇啊,几个字母它就知道要做什么。应该是背后有固定有某个功能的{:4_173:}程序,起了这个名字 马黑黑 发表于 2025-4-3 19:48
最主要的,它是可以适配不同显示设备的
比如,手机,平板,电脑。。现在明白适配是怎么来的了。。。{:4_173:} 马黑黑 发表于 2025-4-3 19:49
vw,vh,分别代表屏幕的横向、纵向尺寸单位,1vw = 1% 个屏幕横向距离,1vh = 1% 个屏幕纵向距离
原来它还是百分比,只不过分了横纵。。省了百分号 花飞飞 发表于 2025-4-3 20:43
原来它还是百分比,只不过分了横纵。。省了百分号
这是很好用的符号 花飞飞 发表于 2025-4-3 20:42
比如,手机,平板,电脑。。现在明白适配是怎么来的了。。。
才明白 花飞飞 发表于 2025-4-3 20:40
好不容易不是JS的,没那么吓人,一不小心就看进去了。
还是挺厉害的说 红影 发表于 2025-4-3 20:28
这些判断都可以交给电脑了,太省力了,这些函数厉害了
封装的挺优秀