各位前端的靓仔靓女们,早上好/下午好/晚上好!今天咱们来聊聊CSS里即将加入的两位新朋友:round()
和 mod()
。别听到函数就害怕,这俩家伙其实挺接地气的,能帮咱们在布局上耍出不少新花样。
第一部分:round()
– 四舍五入界的扛把子
round()
函数,顾名思义,就是用来四舍五入的。但是CSS的round()
可比你想象的要强大,它不只是简单的取整,而是可以指定精度和舍入策略。
1. 基本语法
round(value, rounding-increment)
value
: 需要进行舍入的数值。rounding-increment
: 舍入的增量,也就是精度。
2. 舍入策略(Rounding Strategies)
CSS的round()
默认的舍入策略是nearest
,也就是最接近的原则。除此之外,还有其他的策略,不过目前浏览器支持情况还不太好,咱们先了解一下,以后说不定就能用上了。
nearest
: 舍入到最接近的倍数。up
: 向上舍入到最接近的倍数。down
: 向下舍入到最接近的倍数。to-zero
: 向零方向舍入到最接近的倍数。from-zero
: 远离零方向舍入到最接近的倍数。
这些策略可以作为第三个参数传递给round()
函数,比如 round(12.6, 5, up)
。
3. 实战演练
-
等分网格:
假设我们要创建一个平均分成5列的网格,但是容器的宽度不是5的倍数,怎么办?用
round()
!.container { width: 307px; /* 容器宽度不是5的倍数 */ display: flex; } .item { width: round(100%/5, 1px); /* 将每列的宽度四舍五入到最接近的1px */ height: 50px; background-color: lightblue; border: 1px solid #ccc; }
这样,即使容器宽度不是5的倍数,也能保证每列的宽度尽量接近平均值,并且总宽度不超过容器宽度。
-
响应式间距:
根据屏幕宽度调整元素之间的间距,但间距必须是某个值的倍数。
.container { display: flex; justify-content: space-between; width: 100%; } .item { width: 20%; height: 100px; background-color: lightgreen; } .container { margin-left: calc(round(100vw * 0.05, 10px) * -1); margin-right: calc(round(100vw * 0.05, 10px) * -1); } .item { margin-left: round(100vw * 0.05, 10px); margin-right: round(100vw * 0.05, 10px); }
这段代码的意思是,间距是屏幕宽度的5%,但要四舍五入到最接近的10px。这样可以避免出现非常细小的间距,让布局更加整齐。
-
控制动画步长:
让动画的步长是某个值的倍数,避免动画出现抖动。
.element { width: 100px; height: 100px; background-color: red; position: relative; animation: move 5s linear infinite; } @keyframes move { 0% { left: 0; } 100% { left: round(300px, 10px); /* 移动300px,步长为10px */ } }
这样,元素会以10px为单位移动,避免出现小数像素导致的抖动。
4. round()
的优势
- 精确控制: 可以精确控制数值的精度,避免出现小数像素问题。
- 灵活性: 可以根据不同的需求选择不同的舍入策略。
- 可读性: 相比复杂的计算,
round()
函数更易于理解和维护。
第二部分:mod()
– 求余界的清道夫
mod()
函数,就是用来求余数的。在CSS中,它可以帮助我们实现一些循环和重复的布局效果。
1. 基本语法
mod(dividend, divisor)
dividend
: 被除数。divisor
: 除数。
2. 应用场景
-
循环背景:
让背景图片以一定的规律循环显示。
.element { width: 200px; height: 200px; background-image: url('image1.png'), url('image2.png'), url('image3.png'); background-position: calc(mod(var(--index), 3) * 100%) 0; background-size: 300% 100%; --index: 0; animation: cycle 9s infinite steps(1); } @keyframes cycle { to { --index: 1; } }
这里使用了CSS变量
--index
来控制背景图片的偏移量。mod(var(--index), 3)
的结果会循环在 0, 1, 2 之间,从而实现背景图片的循环显示。 -
交替颜色:
让列表项的背景颜色交替显示。
ul { list-style: none; padding: 0; } li { padding: 10px; background-color: hsl(0, 0%, calc(mod(var(--i), 2) * 20 + 90%)); --i: calc(var(--n) + 1); } li:nth-child(1) { --n: 0; } li:nth-child(2) { --n: 1; } li:nth-child(3) { --n: 2; } li:nth-child(4) { --n: 3; } li:nth-child(5) { --n: 4; } li:nth-child(6) { --n: 5; }
这个例子中,使用了CSS变量
--i
和--n
来记录列表项的索引。mod(var(--i), 2)
的结果会交替在 0 和 1 之间,从而控制背景颜色的交替显示。 -
创建复杂的图案:
结合其他CSS属性,可以创建出一些复杂的图案。
.container { width: 300px; height: 300px; background-color: #fff; position: relative; } .dot { width: 20px; height: 20px; border-radius: 50%; background-color: #000; position: absolute; top: calc(sin(var(--angle)) * 100px + 150px); left: calc(cos(var(--angle)) * 100px + 150px); --angle: calc(mod(var(--i), 12) * 30deg); --i: calc(var(--n) + 1); } .dot:nth-child(1) { --n: 0; } .dot:nth-child(2) { --n: 1; } .dot:nth-child(3) { --n: 2; } .dot:nth-child(4) { --n: 3; } .dot:nth-child(5) { --n: 4; } .dot:nth-child(6) { --n: 5; } .dot:nth-child(7) { --n: 6; } .dot:nth-child(8) { --n: 7; } .dot:nth-child(9) { --n: 8; } .dot:nth-child(10) { --n: 9; } .dot:nth-child(11) { --n: 10; } .dot:nth-child(12) { --n: 11; }
这个例子创建了一个圆形排列的12个点。
mod(var(--i), 12)
的结果会循环在 0 到 11 之间,从而控制每个点的角度。
3. mod()
的优势
- 循环控制: 可以方便地实现循环和重复的效果。
- 可读性: 相比复杂的计算,
mod()
函数更易于理解和维护。 - 灵活性: 可以结合其他CSS属性,创建出各种各样的布局效果。
第三部分:round()
+ mod()
= 无限可能
这两个函数单独使用已经很强大了,如果结合起来使用,那简直是如虎添翼,可以实现一些更加复杂的布局效果。
1. 实例:创建动态的仪表盘
<div class="dashboard">
<div class="needle" style="--value: 65;"></div>
</div>
.dashboard {
width: 200px;
height: 100px;
border: 1px solid #ccc;
position: relative;
overflow: hidden;
}
.needle {
width: 100px;
height: 2px;
background-color: red;
position: absolute;
left: 50%;
bottom: 0;
transform-origin: left center;
/* 将value值限制在0-100之间 */
--safe-value: clamp(0, var(--value), 100);
/* 根据value值计算旋转角度,限制在0-180度之间 */
transform: translateX(-50%) rotate(calc(round(var(--safe-value) / 100 * 180, 1deg)));
}
这个例子创建了一个简单的仪表盘。通过round()
函数,我们可以将旋转角度精确到1度,避免出现抖动。
2. 实例:创建可配置的网格系统
:root {
--grid-columns: 12; /* 总列数 */
--grid-gap: 10px; /* 列间距 */
}
.container {
display: flex;
flex-wrap: wrap;
margin-left: calc(var(--grid-gap) * -1); /* 抵消第一列的间距 */
}
.grid-item {
/* 使用grid-column-span变量控制列的跨度 */
--grid-column-span: 4;
width: calc(round((100% / var(--grid-columns) * var(--grid-column-span)), 0.01%) - var(--grid-gap)); /* 计算每列的宽度,精确到0.01% */
margin-left: var(--grid-gap);
margin-bottom: var(--grid-gap);
box-sizing: border-box;
border: 1px solid #ccc;
padding: 10px;
}
/* 使用示例 */
.grid-item:nth-child(1) { --grid-column-span: 6; } /* 第一列跨6列 */
.grid-item:nth-child(2) { --grid-column-span: 3; } /* 第二列跨3列 */
.grid-item:nth-child(3) { --grid-column-span: 3; } /* 第三列跨3列 */
这个例子创建了一个可配置的网格系统。通过CSS变量,我们可以轻松地控制网格的列数和间距。round()
函数保证了每列的宽度计算精确,避免出现布局错乱。
第四部分:注意事项
- 兼容性:
round()
和mod()
还是提案阶段,目前浏览器支持情况还不太好,使用时要注意兼容性处理。可以使用Polyfill或者PostCSS插件来提供支持。 - 性能: 过度使用复杂的计算可能会影响页面性能,要注意优化。
- 可读性: 虽然函数可以简化代码,但也要注意代码的可读性,添加必要的注释。
第五部分:总结
round()
和 mod()
是非常有用的CSS函数,可以帮助我们实现更加灵活和精确的布局效果。虽然目前兼容性还不太好,但相信未来一定会得到广泛应用。
今天就讲到这里,希望大家能够掌握这两个新朋友的用法,并在实际项目中灵活运用。 祝大家编码愉快,早日成为前端大牛! 感谢各位的聆听! 咱们下次再见!