如何解决Sass和新CSS功能发生冲突的问题

最近,CSS添加了许多新的很酷的功能,例如自定义属性和新功能。尽管这些新属性可以使我们的生活更加轻松,但它们最终也可能以有趣的方式与Sass等预处理器进行交互。因此,这将是关于我遇到的问题,如何解决这些问题?特此整理一篇文章来说说。

错误

如果您在使用新功能min()和新max()功能时,使用不同的单元时可能会遇到如下错误消息:“不兼容的单元:vhem。”

在min()/ max()函数中使用不同类型的单元时发生错误

这是因为Sass具有其自己的min()功能,并且忽略CSS min()功能。另外,Sass无法使用两个值之间没有固定关系的单位执行任何类型的计算。

例如,cmin单位之间具有固定的关系,因此min(20in, 50cm)当我们尝试在代码中使用Sass时,Sass可以找出结果是什么,并且不会引发错误。

其他单位也一样。例如,角度单位在它们之间都具有固定的关系:1turn1rad1grad始终计算为相同的deg值。这同样适用于1s这始终是1000ms1kHz这始终是1000Hz1dppx这始终是96dpi,而且1in这是永远96px。这就是Sass可以在它们之间进行转换并将它们混合在计算和内部函数(例如其自身min()函数)中的原因。

但是,当这些单位之间没有固定的关系时,事情就破裂了(就像前面提到的emvh单位一样)。

这不仅仅是不同的单位。尝试在calc()内部使用min()也会导致错误。如果我尝试类似calc(20em + 7px),我得到的错误是“ calc(20em + 7px)不是的数字” min

calc()在min()函数中嵌套使用不同的单位值时出错

当我们要使用一个CSS变量或数学CSS函数的结果(如出现了另一个问题calc()min()max()像一个CSS过滤器)invert()

在这种情况下,我们被告知“ $color: 'var(--p, 0.85)不是的颜色” invert

var()在filter: invert()错误

发生相同的事情是grayscale():“ $color:’ calc(.2 + var(--d, .3))‘不是…的颜色grayscale。”

calc()在filter: grayscale()错误

opacity()导致相同的问题:“ $color:’ var(--p, 0.8)‘不是’的颜色opacity。”

var()在filter: 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变量时,我们也会遇到麻烦。

var()在color: hsl()错误。

另一方面,它color: hsl(9, var(--sl, 95%, 65%))是完全有效的CSS,在没有Sass的情况下也可以正常工作。

rgb()rgba()函数会发生完全相同的事情。

var()在color: rgba()错误

此外,如果我们导入Compass并尝试在a linear-gradient()或a 内使用CSS变量radial-gradient(),即使在内部使用变量conic-gradient()也很好(也就是说,如果浏览器支持),也会遇到另一个错误。

推荐阅读相关文章《css3颜色值 线性渐变和径向渐变

var()在background: linear-gradient()错误

这是因为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让您感到痛苦。我尽量不要过度使用它们,以免进入使用它们的弊端超过收益的领域。

弄清楚这些calc()表达式的结果并不容易

通常,如果它像常量一样工作,则不会更改元素到元素或状态到状态(在这种情况下,绝对要使用自定义属性)或减少已编译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,从而使生成的代码非常重复。

上面的代码生成的CSS

从那以后,我开始使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) }
}

使Pug生成索引作为自定义属性

这大大减少了生成的代码。

上面的代码生成的CSS

但是,如果我想生成彩虹渐变之类的东西,仍然需要循环使用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()) }

生成彩虹之类的东西,仍然需要循环使用Sass

当然,我可以从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, ())})
}

效果图如下:

带有有趣border图案的贴纸

然后使用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功能发生冲突的问题,希望对大家有帮助,文章有点长,但是干货满满,建议先马后看。如有更好方法欢迎留言讨论。

1. 本站所有免费资源来源于用户上传和网络,因此不包含技术服务请大家谅解!如有侵权请邮件联系客服!
2. 本站不保证所提供下载的免费资源的准确性、安全性和完整性,免费资源仅供下载学习之用!如有链接无法下载、失效,请联系客服处理!
3. 您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容资源!如用于商业或者非法用途,与本站无关,一切后果请用户自负!
4. 如果您也有好的资源或技术教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
5. 加入前端开发QQ群:565733884,我们大家一起来交流技术!
码云笔记 » 如何解决Sass和新CSS功能发生冲突的问题

发表评论