当Sass和新CSS功能发生冲突时的解决方案
共 6277字,需浏览 13分钟
·
2021-04-04 03:23
错误
使用calc()嵌套在min()函数中的不同单位值时发生错误
解决方案
- let n = 12;
while n--
.item
$n: 12;
$ba: 360deg/$n;
$d: 2em;
.item {
position: absolute;
top: 50%; left: 50%;
margin: -.5*$d;
width: $d; height: $d;
/* prettifying styles */
@for $i from 0 to $n {
&:nth-child(#{$i + 1}) {
transform: rotate($i*$ba) translate(2*$d) rotate(-$i*$ba);
&::before { content: '#{$i}' }
}
}
}
但是,这意味着在更改项目数时,我必须同时更改Pug和Sass,从而使生成的代码非常重复。
从那以后,我开始让Pug生成索引作为自定义属性,然后在transform声明中使用它们。
- let n = 12;
body(style=`--n: ${n}`)
- for(let i = 0; i < n; i++)
.item(style=`--i: ${i}`)
$d: 2em;
.item {
position: absolute;
top: 50%;
left: 50%;
margin: -.5*$d;
width: $d;
height: $d;
/* prettifying styles */
--az: calc(var(--i)*1turn/var(--n));
transform: rotate(var(--az)) translate(2*$d) rotate(calc(-1*var(--az)));
counter-reset: i var(--i);
&::before { content: counter(i) }
}
这大大减少了生成的代码。
但是,如果我想生成彩虹之类的东西,仍然需要循环使用Sass。
@function get-rainbow($n: 12, $sat: 90%, $lum: 65%) {
$unit: 360/$n;
$s-list: ();
@for $i from 0 through $n {
$s-list: $s-list, hsl($i*$unit, $sat, $lum)
}
@return $s-list
}
html { background: linear-gradient(90deg, get-rainbow()) }
当然,我可以从Pug生成它作为列表变量,但是这样做没有利用CSS变量的动态特性,也没有减少提供给浏览器的代码量,因此没有任何好处出来。
我在Sass(和Compass)中使用的另一大部分是与内置的数学函数(例如三角函数)相关联的,这些函数现在是CSS规范的一部分。
但尚未在任何浏览器中实现。Sass也不具备这些功能,但是Compass具备,这就是为什么我经常需要使用Compass。
而且,当然,我可以在Sass中编写自己的此类函数。在Compass支持逆三角函数之前,我一开始就采用了此方法。
我真的很需要它们,所以我根据泰勒级数写了自己的。但是Compass如今提供了这类功能,它们比我的更好,性能更高。
数学功能对我来说非常重要,因为我是技术人员,而不是艺术家。CSS中的值通常来自数学计算。它们不是魔术数字,也不是纯粹用于美学的东西。
一个示例是生成剪切路径点的列表,这些剪切路径点将创建规则或准规则多边形。考虑一下我们要创建非矩形化身或贴纸之类的情况。
让我们看看,一个在圆上具有顶点的规则多边形,其半径50%为从其开始的正方形元素的半径。在下面的演示中拖动滑块可以使我们看到不同数量的顶点的放置位置:
将其放入Sass代码中,代码如下:
@mixin reg-poly($n: 3) {
$ba: 360deg/$n; // base angle
$p: (); // point coords list, initially empty
@for $i from 0 to $n {
$ca: $i*$ba; // current angle
$x: 50%*(1 + cos($ca)); // x coord of current point
$y: 50%*(1 + sin($ca)); // y coord of current point
$p: $p, $x $y // add current point coords to point coords list
}
clip-path: polygon($p) // set clip-path to list of points
}
请注意,这里我们还使用了循环以及诸如条件和模之类的东西,这在使用不带Sass的CSS时确实很痛苦。
稍微多一些演变的版本可能涉及通过向$oa每个顶点的角度添加相同的偏移角度来旋转多边形。
在下面的演示中可以看到。此示例以类似的方式抛出一个星形混合,但我们总是有偶数个顶点,并且每个奇数索引的顶点都位于半径较小的圆($f*50%,其中$f为次sub)上:
演示示例地址:https://codepen.io/thebabydino/pen/PRMxwj
我们也可以有这样的效果:
这个演示恰好也是依赖CSS变量。
然后,使用mixins来避免在对诸如range input之类的东西进行样式化时一遍又一遍地编写完全相同的声明。
不同的浏览器使用不同的伪元素来设置此类控件的组件样式,因此对于每个组件,我们都必须设置用于控制其在多个伪组件上的外观的样式。
如果将其放入我们的CSS中:
input::-webkit-slider-runnable-track,
input::-moz-range-track,
input::-ms-track { /* common styles */ }
但是,我们不能这样做,因为它不起作用!如果没有选择器,整个规则集将被删除。而且由于没有浏览器可以识别上述元素,因此,样式不会在任何浏览器中起到作用。
如果要应用样式,我们需要具有以下内容:
input::-webkit-slider-runnable-track { /* common styles */ }
input::-moz-range-track { /* common styles */ }
input::-ms-track { /* common styles */ }
但这可能意味着许多相同的样式重复了三遍。
而且,例如,如果要更改background,则需要在::-webkit-slider-runnable-track样式,::-moz-range-track样式和样式中进行更改::-ms-track。
我们唯一的理智的解决方案是使用mixin。样式在编译后的代码中会重复,因为它们必须在那儿重复,但是我们不必再写三遍相同的东西。
@mixin track() { /* common styles */ }
input {
&::-webkit-slider-runnable-track { @include track }
&::-moz-range-track { @include track }
&::-ms-track { @include track }
}
最后,Sass仍然非常有必要。
学习更多技能
请点击下方web前端开发