马黑黑 发表于 2025-4-3 18:43

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">
&lt;style&gt;
#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;
}
&lt;/style&gt;

&lt;div id="tz"&gt;&lt;/div&gt;
    </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>

花飞飞 发表于 2025-4-3 19:13

max(50%, 200px) 说明中,反之后那句应这个是返回50%吧。
这个取最大值的时候,如果父框太小,还会出现滚动条

花飞飞 发表于 2025-4-3 19:19

width: max(350px, min(50%, 500px));限于350和500之间了。。这嵌套还挺有意思的。。发明这个的也是神人
下面的clamp更好玩,就确定一个范围跑不掉了。。
clamp代替嵌套,真是越来越先进

花飞飞 发表于 2025-4-3 19:26

最后这个直观演示好啊,分明就是演示贴子怎么自适应屏幕大小啊。。。
预览开始界面是800*460,最大化后就变1400*760,拖拉界面可以看到 变化过程。。。
这样无论浏览器边框界面大小都能按比例完美显示。。
好智能的设计。。咋这么聪明涅

花飞飞 发表于 2025-4-3 19:27

90vw,90vh这啥意思呀,为何不是上面例子中的百分比。。{:4_173:}

马黑黑 发表于 2025-4-3 19:47

花飞飞 发表于 2025-4-3 19:13
max(50%, 200px) 说明中,反之后那句应这个是返回50%吧。
这个取最大值的时候,如果父框太小,还会出现滚 ...

额,是的,改了。谢谢

马黑黑 发表于 2025-4-3 19:47

花飞飞 发表于 2025-4-3 19:19
width: max(350px, min(50%, 500px));限于350和500之间了。。这嵌套还挺有意思的。。发明这个的也是神人
...

它是后面一点出来的

马黑黑 发表于 2025-4-3 19:48

花飞飞 发表于 2025-4-3 19:26
最后这个直观演示好啊,分明就是演示贴子怎么自适应屏幕大小啊。。。
预览开始界面是800*460,最大化后就 ...

最主要的,它是可以适配不同显示设备的

马黑黑 发表于 2025-4-3 19:49

花飞飞 发表于 2025-4-3 19:27
90vw,90vh这啥意思呀,为何不是上面例子中的百分比。。

vw,vh,分别代表屏幕的横向、纵向尺寸单位,1vw = 1% 个屏幕横向距离,1vh = 1% 个屏幕纵向距离

红影 发表于 2025-4-3 20:25

clamp 就是那个嵌套的表达吧,那个例子中,当宽度在800和1400之间,就直接显示为90vw,高度也如此。
这个自适应挺好的,不用考虑设置的过大或过小了。{:4_204:}

红影 发表于 2025-4-3 20:27

貌似也有问题,当自己的图图是竖版的,会不会直接被变成横版了啊{:4_173:}

红影 发表于 2025-4-3 20:28

这些判断都可以交给电脑了,太省力了,这些函数厉害了{:4_187:}

花飞飞 发表于 2025-4-3 20:40

马黑黑 发表于 2025-4-3 19:47
额,是的,改了。谢谢

好不容易不是JS的,没那么吓人,一不小心就看进去了。{:4_173:}

花飞飞 发表于 2025-4-3 20:41

马黑黑 发表于 2025-4-3 19:47
它是后面一点出来的

函数也很神奇啊,几个字母它就知道要做什么。应该是背后有固定有某个功能的{:4_173:}程序,起了这个名字

花飞飞 发表于 2025-4-3 20:42

马黑黑 发表于 2025-4-3 19:48
最主要的,它是可以适配不同显示设备的

比如,手机,平板,电脑。。现在明白适配是怎么来的了。。。{:4_173:}

花飞飞 发表于 2025-4-3 20:43

马黑黑 发表于 2025-4-3 19:49
vw,vh,分别代表屏幕的横向、纵向尺寸单位,1vw = 1% 个屏幕横向距离,1vh = 1% 个屏幕纵向距离

原来它还是百分比,只不过分了横纵。。省了百分号

马黑黑 发表于 2025-4-3 20:50

花飞飞 发表于 2025-4-3 20:43
原来它还是百分比,只不过分了横纵。。省了百分号

这是很好用的符号

马黑黑 发表于 2025-4-3 20:50

花飞飞 发表于 2025-4-3 20:42
比如,手机,平板,电脑。。现在明白适配是怎么来的了。。。

才明白

马黑黑 发表于 2025-4-3 20:51

花飞飞 发表于 2025-4-3 20:40
好不容易不是JS的,没那么吓人,一不小心就看进去了。

还是挺厉害的说

马黑黑 发表于 2025-4-3 20:54

红影 发表于 2025-4-3 20:28
这些判断都可以交给电脑了,太省力了,这些函数厉害了

封装的挺优秀
页: [1] 2 3 4 5
查看完整版本: CSS函数min、max和clamp