如何解决Sass和新CSS功能发生冲突的问题
最近,CSS 添加了许多新的很酷的功能,例如自定义属性和新功能。尽管这些新属性可以使我们的生活更加轻松,但它们最终也可能以有趣的方式与 Sass 等预处理器进行交互。因此,这将是关于我遇到的问题,如何解决这些问题?特此整理一篇文章来说说。
错误
如果您在使用新功能min()
和新max()
功能时,使用不同的单元时可能会遇到如下错误消息:“不兼容的单元:vh
和em
。”
这是因为Sass 具有其自己的min()
功能,并且忽略 CSS min()
功能。另外,Sass 无法使用两个值之间没有固定关系的单位执行任何类型的计算。
例如,cm
和in
单位之间具有固定的关系,因此min(20in, 50cm)
当我们尝试在代码中使用 Sass 时,Sass 可以找出结果是什么,并且不会引发错误。
其他单位也一样。例如,角度单位在它们之间都具有固定的关系:1turn
,1rad
或1grad
始终计算为相同的deg
值。这同样适用于1s
这始终是1000ms
,1kHz
这始终是1000Hz
,1dppx
这始终是96dpi
,而且1in
这是永远96px
。这就是 Sass 可以在它们之间进行转换并将它们混合在计算和内部函数(例如其自身min()
函数)中的原因。
但是,当这些单位之间没有固定的关系时,事情就破裂了(就像前面提到的em
和vh
单位一样)。
这不仅仅是不同的单位。尝试在calc()
内部使用min()
也会导致错误。如果我尝试类似calc(20em + 7px)
,我得到的错误是“ calc(20em + 7px)
不是的数字” min
。
当我们要使用一个 CSS 变量或数学 CSS 函数的结果(如出现了另一个问题calc()
,min()
或max()
像一个 CSS 过滤器)invert()
。
在这种情况下,我们被告知“ $color: 'var(--p, 0.85)
不是的颜色” invert
。
发生相同的事情是grayscale()
:“ $color
:’ calc(.2 + var(--d, .3))
‘不是…的颜色grayscale
。”
opacity()
导致相同的问题:“ $color
:’ var(--p, 0.8)
‘不是’的颜色opacity
。”
然而,其他filter
功能-包括sepia()
,blur()
,drop-shadow()
,brightness()
,contrast()
和hue-rotate()
-所有的与 CSS 变量相关处理都很好!
事实证明,正在发生的事情与min()
and max()
问题类似。sass 没有内置式sepia()
,blur()
,drop-shadow()
,brightness()
,contrast()
,hue-rotate()
的功能,但它确实有它自己的grayscale()
,invert()
和opacity()
功能,以及它们的第一个参数是一个$color
值。由于找不到该参数,因此会引发错误。
出于同样的原因,当尝试使用列出至少两个hsl()
或两个hsla()
值的 CSS 变量时,我们也会遇到麻烦。
另一方面,它color: hsl(9, var(--sl, 95%, 65%))
是完全有效的 CSS,在没有 Sass 的情况下也可以正常工作。
rgb()
和rgba()
函数会发生完全相同的事情。
此外,如果我们导入 Compass 并尝试在 a linear-gradient()
或 a 内使用 CSS 变量radial-gradient()
,即使在内部使用变量conic-gradient()
也很好(也就是说,如果浏览器支持),也会遇到另一个错误。
推荐阅读相关文章《css3 颜色值 线性渐变和径向渐变》
这是因为 Compass 带有linear-gradient()
和radial-gradient()
功能,但从未添加conic-gradient()
一个。
在所有这些情况下,问题都来自于 Sass 或 Compass 具有相同名称的功能,并假设这些是我们打算在代码中使用的功能。
解决方案
这里的窍门是记住Sass 区分大小写,但是 CSS 不区分大小写。
这意味着我们可以编写,Min(20em, 50vh)
而 Sass 不会将其识别为自己的min()
功能。不会抛出任何错误,并且它仍然是可以正常使用的有效 CSS。同样,写作HSL()
/ HSLA()
/ RGB()
/ RGBA()
或Invert()
使我们避免了我们在前面的问题。
至于渐变,我通常更喜欢linear-Gradient()
并且radial-Gradient()
仅仅因为它更接近 SVG 版本,但是在其中至少使用一个大写字母也可以。
虽然我发现 CSS 变量非常有用,并且在过去三年中几乎将它们用于所有变量,但要记住,它们会带来性能成本,而且要跟踪在迷宫式 calc()计算中出现问题的地方可能会很麻烦。我们当前的 DevTools 让您感到痛苦。我尽量不要过度使用它们,以免进入使用它们的弊端超过收益的领域。
通常,如果它像常量一样工作,则不会更改元素到元素或状态到状态(在这种情况下,绝对要使用自定义属性)或减少已编译 CSS 的数量(解决重复问题)由前缀创建),那么我将使用 Sass 变量。
其次,变量一直是我使用 Sass 的很小一部分。当我在 2012 年末开始使用 Sass 时,它主要是用于循环播放,这是 CSS 中尚没有的功能。尽管我已将其中一些循环移至 HTML 预处理器(因为这样可以减少生成的代码,并且避免以后再修改 HTML 和 CSS),但在很多情况下,我仍会使用 Sass 循环,例如生成值列表,渐变函数内的停止列表,多边形函数内的点列表,变换列表等。
这是一个例子。我曾经使用n
预处理器生成 HTML 项目。预处理器的选择无关紧要,但是我将在这里使用 Pug。
- let n = 12; while n-- .item
然后,将$n
变量设置为 Sass(它必须与 HTML 中的变量相等)并循环到它以生成将每个项目定位的转换:
$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%为从其开始的正方形元素的半径。在下面的演示中拖动滑块可以使我们看到不同数量的顶点的放置位置:
HTML(Pug)代码:
- d = 2000 - rf = .35 svg(viewbox=`${-.5*d} ${-.5*d} ${d} ${d}`) defs circle(id='vertex' r='8') path(id='axis' d=`M${-.5*d},0 L${.5*d},0`) g(class='axes') use(xlink:href='#axis') use(xlink:href='#axis' transform='rotate(90)') circle(id='ccirc' r=`${rf*d}`) polygon(id='poly') line(class='axis--cover' x2=`${.9*rf*d}`) line(id='radius' x2=`${rf*d}`) g(id='vertices') g(class='arc') path(class='arc__fill') path(class='arc__line') text circle(id='origin' r='8') form input(id='n' type='range' min='3' max='10' value='3') label(for='n') number of vertices: span(id='val--n') 3 hr p base angle: span(id='val--a') 120°
SCSS 代码:
$theme-c: #e18728; $hl-c: #be4c39; $csyst-c: #ccc; $circle-c: #555; $poly-c: $theme-c; $arc-bg: #d49b00; $arc-c: $hl-c; $arc-txt: #9351a6; $radius-c: $theme-c; $guide-c: #838383; $vertex-bg: #d49b00; $vertex-c: $hl-c; $vertex-txt: #9351a6; html { overflow: hidden; } body { margin: 0; } svg { display: block; margin: calc(50vh - 50vmin) auto; min-width: 10em; min-height: 10em; width: 100vmin; height: 100vmin; max-width: 100em; max-height: 100em; font-size: 1em; } text { font: 700 100px monospace; opacity: .001; } .q1, .q2 { dominant-baseline: hanging; } .q2, .q3 { text-anchor: end; } .hidden { opacity: .001; pointer-events: none; } [id='axis'], [id='ccirc'], [id='poly'], [id='radius'], .arc__line, [id='vertices'] line, [id='vertices'] circle { vector-effect: non-scaling-stroke; } [id='axis'], .axis--cover { fill: $csyst-c; stroke: $csyst-c; stroke-width: 2; } [id='ccirc'] { fill: transparent; stroke: $circle-c; stroke-width: 2; } [id='poly'] { fill: transparent; stroke: $poly-c; stroke-width: 4; } .arc { &__fill { fill: lighten($arc-bg, 30%); } &__line { fill: none; stroke: $arc-c; stroke-width: 4; vector-effect: non-scaling-stroke; } text { fill: $arc-txt; dominant-baseline: middle; text-anchor: middle; } } [id='radius'] { stroke: $radius-c; stroke-width: 4; } [id='vertices'] { line { stroke: $guide-c; stroke-dasharray: 8; stroke-width: 2 } circle { fill: lighten($vertex-bg, 30%); stroke: $vertex-c; stroke-width: 4; } text { fill: $vertex-txt; } } @media ( min-width: 240px) and (min-height: 240px) { text { opacity: .999; } } @media ( min-width: 320px) and (min-height: 320px) { text { font-size: 80px; } } @media ( min-width: 480px) and (min-height: 480px) { text { font-size: 56px; } } @media ( min-width: 800px) and (min-height: 800px) { text { font-size: 40px; } } /* controls */ $theme-hl: #e18728; $ctrl-bg: #262626; $ctrl-ll: #aaa; $ctrl-hl: $theme-hl; $track-w: 13em; $track-h: .25em; $thumb-d: 1.25em; @mixin track() { width: $track-w; height: $track-h; background: $ctrl-ll; } @mixin fill() { background: $ctrl-hl; } @mixin thumb() { border: none; width: $thumb-d; height: $thumb-d; border-radius: 50%; background: $ctrl-hl; } form { position: absolute; top: .25em; right: .25em; margin: .25em; padding: .5em; background: $ctrl-bg; color: $ctrl-ll; font: 1em/1.375em trebuchet ms, sans serif; text-align: center; } input[type='range'] { &, &::-webkit-slider-runnable-track, &::-webkit-slider-thumb { -webkit-appearance: none; } display: block; margin: 1em auto 0; padding: 0; width: $track-w; height: 2em; background: none; font-size: 1em; cursor: pointer; &::-webkit-slider-runnable-track { @include track(); } &::-moz-range-track { @include track(); } &::-ms-track { border: none; @include track(); color: transparent; } &::-moz-range-progress { height: $track-h; @include fill(); } &::-ms-fill-lower { @include fill(); } &::-webkit-slider-thumb { margin-top: ($track-h - $thumb-d)/2; @include thumb(); } &::-moz-range-thumb { @include thumb(); } &::-ms-thumb { @include thumb(); } &::-ms-tooltip { display: none; } + label { display: block; } &:focus { outline: none; } }
JS 代码:
/* because me lazy */ Object.getOwnPropertyNames(Math).map(function(p) { window[p] = Math[p]; }); Node.prototype.setAttrs = function(attr_obj) { for(var prop in attr_obj) { this.setAttribute(prop, attr_obj[prop]); } }; var NS_URI = 'http://www.w3.org/2000/svg', XLink_NS = 'http://www.w3.org/1999/xlink', DEG_MOTION_SPEED = 3, T_HL = 60, LEN_MOTION_SPEED = 16, V_RADIUS = 8, PULSE_F = .32, RAD_F = PI/180, svg = document.querySelector('svg'), vb = svg.getAttribute('viewBox').split(' ') .map(function(d) { return ~~d; }), c_el = document.getElementById('ccirc'), p_el = document.getElementById('poly'), r_el = document.getElementById('radius'), w_el = document.getElementById('vertices'), r = ~~c_el.getAttribute('r'), p, curr_off, r_a = .2*r, n_el = document.getElementById('n'), vn_el = document.getElementById('val--n'), va_el = document.getElementById('val--a'), arc_el = document.querySelector('.arc'), arc_f_el = document.querySelector('.arc__fill'), arc_l_el = document.querySelector('.arc__line'), arc_t_el = document.querySelector('.arc text'), n = ~~n_el.value, vertices = [], a_base = 360/n, k = 360%n, a_target = 0, a = 0, idx = 0, r_id = null, t = 0; var init = function() { createPoly(); }; var f = function() { var m = ~~n_el.value; if(m !== n) { if(r_id) { cancelAnimationFrame(r_id); r_id = null; } idx = 0; a = 0; t = 0; n = m; a_base = 360/n; k = 360%n; stepDisplay(); vn_el.textContent = n; va_el.textContent = ('' + a_base).slice(0, 5) + '°'; createPoly(); } }; var createPoly = function() { var frg = document.createDocumentFragment(), curr_vx, curr_pt, curr_txt, curr_r, x, y, l, q, j1, j2, p_txt ='', rad_a_base = 2*PI/n, rad_a; vertices = []; w_el.textContent = ''; l = 2*r*sin(rad_a_base/2); curr_off = p = n*l; p_el.setAttrs({ 'stroke-dasharray': p, 'stroke-dashoffset': curr_off }); for(var i = 0; i < n; i++) { rad_a = i*rad_a_base; q = floor(2*rad_a/PI); j1 = floor(q/2); j2 = q%2; x = r*cos(rad_a); y = r*sin(rad_a); p_txt += x + ',' + y + ' '; curr_r = document.createElementNS( NS_URI, 'line' ); curr_r.setAttrs({ 'x2': x, 'y2': y, 'class': 'hidden' }); curr_pt = document.createElementNS( NS_URI, 'circle' ); curr_pt.setAttrs({ 'cx': x, 'cy': y }); curr_txt = document.createElementNS( NS_URI, 'text' ); curr_txt.textContent = (i + '*' + a_base).slice(0, 7) + '°'; curr_txt.setAttrs({ 'x': x + 2*V_RADIUS*pow(-1, j2 ^ j1), 'y': y + 2*V_RADIUS*pow(-1, j1), 'class': 'q' + (q + 1) }); curr_vx = document.createElementNS( NS_URI, 'g' ); curr_vx.setAttrs({ 'class': 'hidden' }); vertices.push({ 'v': curr_vx, 'p': curr_pt, 'r': curr_r }); curr_vx.appendChild(curr_r); curr_vx.appendChild(curr_pt); curr_vx.appendChild(curr_txt); frg.appendChild(curr_vx); } p_el.setAttribute('points', p_txt.trim()); w_el.appendChild(frg); constructPoly(); }; var constructPoly = function() { r_el.setAttribute('class', ''); arc_el.setAttribute('class', 'arc'); pulse(); }; var updateAngle = function() { if(a >= a_target) { a = a_target; stepDisplay(); cancelAnimationFrame(r_id); r_id = null; pulse(); return; } a += DEG_MOTION_SPEED; stepDisplay(); r_id = requestAnimationFrame(updateAngle); }; var stepDisplay = function() { var sn = (a > 100)?6:5, rad_a = RAD_F*a, x = r_a*cos(rad_a), y = r_a*sin(rad_a), d_txt = 'M' + ~~x + ' ' + ~~y + 'A' + r_a + ' ' + r_a + ' 0 ' + floor(a/180) + ' 0 ' + r_a + ' 0'; r_el.setAttribute( 'transform', 'rotate(' + a + ')' ); arc_l_el.setAttribute('d', d_txt); d_txt += 'L0,0z'; arc_f_el.setAttribute('d', d_txt); arc_t_el.setAttribute( 'transform', 'rotate(' + .5*a + ')' + 'translate(' + 1.5*r_a + ')' + 'rotate(' + -.5*a + ')' ); arc_t_el.textContent = ('' + a).slice(0, sn) + '°'; }; var pulse = function() { if(t > T_HL) { cancelAnimationFrame(r_id); r_id = null; t = 0; if(idx < n) { a = ~~a; vertices[idx].r.setAttribute('class', ''); if(idx < n - 1) { a_target = (++idx)*a_base; updateAngle(); } else { r_el.setAttribute('class', 'hidden'); arc_el.setAttribute('class', 'hidden'); drawPolyLine(); } } return; } if(idx < n) { if(t === 0) { vertices[idx].v.setAttribute('class', ''); } vertices[idx].p.setAttribute( 'r', V_RADIUS*(1.25 + sin(PULSE_F*t)) ); } t++; r_id = requestAnimationFrame(pulse); }; var drawPolyLine = function() { if(abs(curr_off) < LEN_MOTION_SPEED) { curr_off = 0; cancelAnimationFrame(r_id); r_id = null; return; } curr_off -= LEN_MOTION_SPEED; p_el.setAttribute( 'stroke-dashoffset', curr_off ); r_id = requestAnimationFrame(drawPolyLine); }; init(); n_el.addEventListener('change', f, false); n_el.addEventListener('input', f, false);
将其放入 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
为次 unit):
HTML 代码:
<div></div> <div></div>
SCSS 代码:
@import 'compass/css3'; $d: 80vh; // $n: number of vertices/ edges (integer) // $oa: offset angle (angle) @mixin reg-poly($n: 3, $oa: -90deg) { $ba: 360deg/$n; $p: (); @for $i from 0 to $n { $ca: $i*$ba + $oa; $x: 50%*(1 + cos($ca)); $y: 50%*(1 + sin($ca)); $p: $p, $x $y } // avoid prefixing repetition --points: #{$p}; -webkit-clip-path: polygon(var(--points)); clip-path: polygon(var(--points)) } // $n: number of star points (integer) // $f: star factor (number - between 0 and 1 for a star) // $oa: offset angle (angle) @mixin star-shape-poly($n: 3, $f: .5, $oa: -90deg) { $m: 2*$n; $ba: 360deg/$m; $rr: $f*cos($ba); $p: (); @for $i from 0 to $m { $ca: $i*$ba + $oa; $cr: if($i%2 == 0, 1, $rr); $x: 50%*(1 + $cr*cos($ca)); $y: 50%*(1 + $cr*sin($ca)); $p: $p, $x $y } // avoid prefixing repetition --points: #{$p}; -webkit-clip-path: polygon(var(--points)); clip-path: polygon(var(--points)) } div { display: inline-block; width: $d; height: $d; background: orange; @include reg-poly(8, 15deg); &:nth-child(2) { @include star-shape-poly(14, .85, 5deg) } }
效果如下:
我们也可以有这样的胖星星:
<div class='star'></div> ...
SCSS 代码:
@import 'compass/css3'; $d: 5em; // $n-point star // $k = disc radius relative to star circumradius // $p = rounding precision @mixin star($n: 5, $k: .65, $p: 3) { $m: 2*$n; $ba: 360deg/$m; $la: $ba/$p; $ro: 50%; $ri: $k*$ro; $plist: (); @for $i from 0 to $m { $sa: ($i - .5)*$ba - 90deg; @if $i%2 == 0 { // pointy part $ma: $sa + .5*$ba; $plist: $plist, $ro + $ri*cos($sa) $ro + $ri*sin($sa), $ro + $ro*cos($ma) $ro + $ro*sin($ma) } @else { // round part @for $j from 0 to $p { $ca: $sa + $j*$la; $plist: $plist, $ro + $ri*cos($ca) $ro + $ri*sin($ca) } } } --poly: #{polygon($plist)}; -webkit-clip-path: var(--poly); clip-path: var(--poly); } body:before { display: block; margin-bottom: 1em; font: 1em consolas, monaco, monospace; content: '1 element stars with clip-path' } .star { display: inline-block; width: $d; height: $d; background: gold; &:nth-child(1) { @include star(3, .25) } &:nth-child(2) { @include star(4, .35) } &:nth-child(3) { @include star(5, .32) } &:nth-child(4) { @include star(5, .51) } &:nth-child(5) { @include star(6, .29) } &:nth-child(6) { @include star(6, .5) } &:nth-child(7) { @include star(7, .27) } &:nth-child(8) { @include star(7, .57) } &:nth-child(9) { @include star(7) } &:nth-child(10) { @include star(8, .39) } &:nth-child(11) { @include star(8, .53) } &:nth-child(12) { @include star(8) } &:nth-child(13) { @include star(8, .75) } &:nth-child(14) { @include star(9, .39) } &:nth-child(15) { @include star(9, .53) } &:nth-child(16) { @include star(9) } &:nth-child(17) { @include star(9, .75) } &:nth-child(18) { @include star(10, .39) } &:nth-child(19) { @include star(10, .53) } &:nth-child(20) { @include star(10) } &:nth-child(21) { @include star(10, .75) } &:nth-child(22) { @include star(11, .39) } &:nth-child(23) { @include star(11, .53) } &:nth-child(24) { @include star(11) } &:nth-child(25) { @include star(11, .75) } &:nth-child(26) { @include star(12, .39) } &:nth-child(27) { @include star(12, .53) } &:nth-child(28) { @include star(12) } &:nth-child(29) { @include star(12, .75) } &:nth-child(30) { @include star(13, .39) } &:nth-child(31) { @include star(13, .53) } &:nth-child(32) { @include star(13) } &:nth-child(33) { @include star(13, .75) } &:nth-child(34) { @include star(14, .39) } &:nth-child(35) { @include star(14, .53) } &:nth-child(36) { @include star(14) } &:nth-child(37) { @include star(14, .75) } &:nth-child(38) { @include star(15, .39) } &:nth-child(39) { @include star(15, .53) } &:nth-child(40) { @include star(15) } &:nth-child(41) { @include star(15, .75) } &:nth-child(42) { @include star(16, .39) } &:nth-child(43) { @include star(16, .53) } &:nth-child(44) { @include star(16) } &:nth-child(45) { @include star(16, .75) } }
效果如下:
或带有有趣 border 图案的贴纸。在这个特定的演示中,每个标签都是使用单个 HTML 元素 border 创建的 clip-path,而模式是使用 Sass 中的,循环和数学创建的。实际上,这相当多。
HTML(pug)代码:
- let data = ['#f6b096', '#d19db4', '#f5b4d2', '#d0aad1', '#cf82b6', '#7f96cc', '#57a7b2', '#dbe285', '#fff7b6', '#fbd5a6', '#f5ad72', '#f8aa48'], n = data.length; //h3 Can you figure out how these were made without checking the code? while n-- .circ(style=`background: ${data[n]}`) Hello, Gorgeous!
SCSS 代码:
@import 'compass/css3'; $n: 7; $gg: 1em; $d: 5em; $g: .125em; $b: .375em; $r: $b/2; $o: -1*($b + $g); $m: $g - $o; $fs: 2.5; $ro: 50%; $rm: calc(50% - #{$r}); $ri: calc(50% - #{$b}); @function arrow($ua, $i, $m: 1, $in: 0, $dbl: 0, $sgn: 1) { $a0: $i*$ua; $a1: $a0 + $sgn*$m*$ua; $a2: $a0 + $sgn*$ua; $list: (); $xo: 50% + $ro*cos($a0); $yo: 50% + $ro*sin($a0); $list: $list, $xo $yo; @if $dbl > 0 { $list: $list, 50% + $ro*cos($a1) 50% + $ro*sin($a1) } $list: $list, calc(50% + #{$rm}*#{cos($a2)}) calc(50% + #{$rm}*#{sin($a2)}); @if $dbl > 0 { $list: $list, calc(50% + #{$ri}*#{cos($a1)}) calc(50% + #{$ri}*#{sin($a1)}) } $list: $list, calc(50% + #{$ri}*#{cos($a0)}) calc(50% + #{$ri}*#{sin($a0)}); @if $in > 0 { $list: $list, calc(50% + #{$rm}*#{cos($a1)}) calc(50% + #{$rm}*#{sin($a1)}) } @return $list, $xo $yo } @function spike($ua, $i, $vo: 0, $in: 0) { $a0: ($i - .5)*$ua; $av: $a0 + ($vo + .5)*$ua; $a1: $a0 + $ua; $list: (); $ao0: if($in < 1, $av, $a0); $ai0: if($in < 1, $a0, $av); $xo: 50% + $ro*cos($ao0); $yo: 50% + $ro*sin($ao0); $list: $list, $xo $yo; @if $in > 0 { $list: $list, 50% + $ro*cos($a1) 50% + $ro*sin($a1) } @else { $list: $list, calc(50% + #{$ri}*#{cos($a1)}) calc(50% + #{$ri}*#{sin($a1)}) } $list: $list, calc(50% + #{$ri}*#{cos($ai0)}) calc(50% + #{$ri}*#{sin($ai0)}); @return $list, $xo $yo } @function double($ua, $i) { $a0: $i*$ua; $a1: $a0 + .25*$ua; $a2: $a0 + .5*$ua; $a3: $a1 + .5*$ua; $a4: $a0 + $ua; $list: (); $xo: 50% + $ro*cos($a1); $yo: 50% + $ro*sin($a1); @return $list, $xo $yo, calc(50% + #{$ri}*#{cos($a2)}) calc(50% + #{$ri}*#{sin($a2)}), calc(50% + #{$ri}*#{cos($a0)}) calc(50% + #{$ri}*#{sin($a0)}), $xo $yo, 50% + $ro*cos($a2) 50% + $ro*sin($a2), 50% + $ro*cos($a4) 50% + $ro*sin($a4), calc(50% + #{$ri}*#{cos($a3)}) calc(50% + #{$ri}*#{sin($a3)}), 50% + $ro*cos($a2) 50% + $ro*sin($a2), $xo $yo } @function rhombus($ua, $i) { $a0: $i*$ua; $a1: $a0 + .5*$ua; $a2: $a0 + $ua; $list: (); $xo: 50% + $ro*cos($a1); $yo: 50% + $ro*sin($a1); @return $list, $xo $yo, calc(50% + #{$rm}*#{cos($a2)}) calc(50% + #{$rm}*#{sin($a2)}), calc(50% + #{$ri}*#{cos($a1)}) calc(50% + #{$ri}*#{sin($a1)}), calc(50% + #{$rm}*#{cos($a0)}) calc(50% + #{$rm}*#{sin($a0)}), $xo $yo } @function hexagon($ua, $i) { $a0: $i*$ua; $a1: $a0 + .25*$ua; $a2: $a1 + .5*$ua; $a3: $a0 + $ua; $list: (); $xo: 50% + $ro*cos($a1); $yo: 50% + $ro*sin($a1); @return $list, $xo $yo, 50% + $ro*cos($a2) 50% + $ro*sin($a2), calc(50% + #{$rm}*#{cos($a3)}) calc(50% + #{$rm}*#{sin($a3)}), calc(50% + #{$ri}*#{cos($a2)}) calc(50% + #{$ri}*#{sin($a2)}), calc(50% + #{$ri}*#{cos($a1)}) calc(50% + #{$ri}*#{sin($a1)}), calc(50% + #{$rm}*#{cos($a0)}) calc(50% + #{$rm}*#{sin($a0)}), $xo $yo } @function points($n, $fn-name, $fn-args) { $ua: 2*pi()/$n; $list: (); $x0: 100%; $y0: 50%; @for $i from 0 to $n { $list: $list, call($fn-name, $ua, $i, $fn-args...), $x0 $y0 } @return $list } body { $s: $fs*($d + 2*$m); display: grid; grid-template-columns: repeat(var(--n, #{$n}), $s); grid-gap: $gg; place-content: center; margin: 0; min-height: 100vh; background: repeating-linear-gradient(45deg, #000, #000 2px, transparent 0, transparent 7px) #555; text-align: center; @for $i from 1 to $n { @media (max-width: ($n - $i + 1)*$s + ($n - $i + 2)*$gg) { --n: #{$n - $i} } } } h3 { grid-column: 1/ span var(--n); color: #fff; font: 2em segoe script, comic sans ms, purisa, cursive } .circ { box-sizing: border-box; display: grid; place-content: center; position: relative; margin: $m; padding-left: .25em; width: $d; height: $d; border-radius: 50%; font: 900 #{$fs*1em}/ 1.25 pinyon script, cursive; filter: drop-shadow(1px 1px #fff); &::after { position: absolute; top: $o; right: $o; bottom: $o; left: $o; background: inherit; content: '' } } .circ:nth-of-type(1)::after { clip-path: polygon(#{points(36, arrow, ())}) } .circ:nth-of-type(2)::after { clip-path: polygon(#{points(36, rhombus, ())}) } .circ:nth-of-type(3)::after { clip-path: polygon(#{points(36, hexagon, ())}) } .circ:nth-of-type(4)::after { clip-path: polygon(points(36, spike, ())) } .circ:nth-of-type(5)::after { clip-path: polygon(points(36, spike, (0, 1))) } .circ:nth-of-type(6)::after { clip-path: polygon(points(36, spike, (1))) } .circ:nth-of-type(7)::after { clip-path: polygon(points(36, spike, (-1))) } .circ:nth-of-type(8)::after { clip-path: polygon(#{points(36, arrow, (.5, 1))}) } .circ:nth-of-type(9)::after { clip-path: polygon(#{points(36, arrow, (.5, 1, 0, -1))}) } .circ:nth-of-type(10)::after { clip-path: polygon(#{points(36, arrow, (.5, 1, 1))}) } .circ:nth-of-type(11)::after { clip-path: polygon(#{points(36, arrow, (.5, 1, 1, -1))}) } .circ:nth-of-type(12)::after { clip-path: polygon(#{points(24, double, ())}) }
效果图如下:
然后使用 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 和新 CSS 功能发生冲突的问题,希望对大家有帮助,文章有点长,但是干货满满,建议先马后看。如有更好方法欢迎留言讨论。
码云笔记 » 如何解决Sass和新CSS功能发生冲突的问题