Sass中的多个box-shadow声明

23

我想要创建一个适用于box-shadow属性的Sass混合器,但是遇到些问题。现有的一些代码看起来像这样。

#someDiv {
  -moz-box-shadow:0 0 5px rgba(0,0,0,.25);
}

#someOtherDiv {
  -moz-box-shadow:0 0 5px rgba(0,0,0,.25) inset;
}

#theLastDiv {
  -moz-box-shadow: 0 0 5px rgba(0,0,0,.25), 0 1px 0 rgba(255,255,255,.2) inset;
}

尝试将所有内容整合成一个mixin变得困难。在mixin中使用逻辑的文档相当稀少。

我想创建一个类似以下的mixin:

@mixin boxShadow($xOffSet, $yOffSet, $blur, $red, $green, $blue, $opacity, $inset : false) {
  @if $inset == true {
    -moz-box-shadow: #{$xOffSet}px #{$yOffSet}px #{$blur}px rgba($red,$green,$blue) inset;
  } @else {
    -moz-box-shadow: #{$xOffSet}px #{$yOffSet}px #{$blur}px rgba($red,$green,$blue);
  }
}

我猜是因为Sass无法评估$inset变量而导致出现错误。

前面的例子只是展示了当box-shadow是否嵌入时我遇到的问题。另一个问题是在单个元素上声明多个box-shadow时会出现问题。请参考上面描述的#theLastDiv作为参考。

@mixin boxShadow($declarations : 2, $xOffSet1, $yOffSet1, $blur1, $red1, $green1, $blue1, $opacity1 $xOffSet2, $yOffSet2, $blur2, $red2, $green2, $blue2, $opacity2) {
  @if $declarations == 1 {
    -moz-box-shadow: #{$xOffSet}px #{$yOffSet}px #{$blur}px rgba($red,$green,$blue);
  } @else if $declarations == 2 {
    -moz-box-shadow: #{$xOffSet1}px #{$yOffSet1}px #{$blur1}px rgba($red1,$green1,$blue1), #{$xOffSet2}px #{$yOffSet2}px #{$blur2}px rgba($red2,$green2,$blue2);
  }

有时一个元素只有一个内阴影,而其他时候它需要分开的内阴影。我错了吗?Sass缺乏解读这种逻辑的能力,实现这一点需要单独的Mixin(一个用于具有一个内阴影的元素,另一个用于具有两个内阴影的mixin)。

而且,上述透明度问题如何影响这个问题?很想听听大家的反馈。如果我错了或者我对这个问题的思考方式是错误的,请让我知道。谢谢!

6个回答

25
您可以像这样使用可变参数:

You can use a variable argument like this:

// Box shadows
@mixin box-shadow($shadow...) {
  -webkit-box-shadow: $shadow;
     -moz-box-shadow: $shadow;       
          box-shadow: $shadow;
}

这允许你在参数中使用逗号,因此可以传递所有你想要的阴影。

以下是一个使用它的示例:

@include box-shadow(2px 2px 2px rgba(#ccc, .8), -2px -2px 2px rgba(#ccc, 0.8)) ;

像这样传递颜色变量:

$shadow-color: red;  // could also be a #F9F8F6 type color
@include box-shadow(0 2px 2px rgba($shadow-color, .9));

更新

$shadow-color: red;  // could also be a hex (like #F9F8F6) type color
@include box-shadow(0 2px 2px rgba($shadow-color, .9));

如果你之前没有见过使用省略号来允许在参数列表中传递可变数量的参数(即splat),请查看此链接:http://sass-lang.com/documentation/file.SASS_CHANGELOG.html#variable_keyword_arguments


你如何使用这种方法传递变量?@include(1px 1px 1px $backgroundColor)似乎不起作用? - Robert
实际上,看看你写的代码,你漏掉了混入名称。 - Will
抱歉 - @include box-shadow(0 0 3px $yellow); 返回的 CSS 定义中颜色值是字符串 "$yellow",而不是 $yellow 变量中的值。 - Robert
你是如何定义$yellow的?这会给我一个闪亮的太阳色边框: $yellow: #f2e00f; @include box-shadow( 0 0px 20px $yellow); :) - Will
不得不承认,我在第一眼看到 @mixin 定义时并没有理解其中的省略号 '...'。除了有效的 CSS box-shadow 属性值之外,您不需要其他任何内容。在澄清后会点赞。 - Volker E.
1
省略号使其成为一个扩展参数 - 扩展参数允许使用可变数量的参数。这是一个在Ruby中广泛应用并传播到CoffeeScript和Sass的概念。@VolkerE. - 请参阅http://sass-lang.com/documentation/file.SASS_CHANGELOG.html#variable_keyword_arguments - Will

19

我更喜欢在基础 CSS 参数中不使用逗号:0 0 1px rgba(0, 0, 0, .5) 而不是使用逗号:0, 0, 5, 0, 0, 0, .25

这是我的解决方案:

@mixin box-shadow($shadow1, $shadow2:false, $shadow3:false, $shadow4:false, $shadow5:false) {
 $params: $shadow1;
  @if $shadow2 
    { $params: $shadow1, $shadow2; }
    @if $shadow3 != false
      { $params: $shadow1, $shadow2, $shadow3; }
      @if $shadow4 != false
        { $params: $shadow1, $shadow2, $shadow3, $shadow4; }
        @if $shadow5 != false
          { $params: $shadow1, $shadow2, $shadow3, $shadow4, $shadow5; }

  -webkit-box-shadow: $params;
     -moz-box-shadow: $params;
          box-shadow: $params;

}

@include box-shadow(-1px -1px 2px rgba(0, 0, 0, .05), 0 1px 1px white inset), ...

比17个参数好多了。谢谢! - Ben Hull
尽管使用此解决方案,您可以拥有的阴影数量仅限于参数数量(在此情况下为5个阴影),但是Will的答案更加简洁,而且没有阴影数量上限。 - Hanna

6
您可以使用集合类型,并且只需要一个参数:
@mixin box-shadow($params) {
  -webkit-box-shadow: $params;
  -moz-box-shadow: $params;
  box-shadow: $params;
}

$shadows: 0px 0px 5px rgba(0, 0, 0, 0.25), 0px 1px 0px #000 inset;

.myclass { 
   @include box-shadow($shadows);
}

4
我已添加了一些逻辑来处理你所描述的情况。以下是 mixin 代码:
```html

我已添加了一些逻辑来处理你所描述的情况。以下是 mixin 代码:

```
@mixin boxShadow($xOffSet, $yOffSet, $blur, $red, $green, $blue, $opacity, $inset : false, $two : false, $xOffSet2 : 0, $yOffSet2 : 0, $blur2 : 0, $red2 : 0, $green2 : 0, $blue2 : 0, $opacity2 : 0, $inset2 : false) {
  @if $inset {
    @if $two {
        @if $inset2 {
            -moz-box-shadow: #{$xOffSet}px #{$yOffSet}px #{$blur}px rgba($red,$green,$blue, $opacity) inset, #{$xOffSet2}px #{$yOffSet2}px #{$blur2}px rgba($red2,$green2,$blue2, $opacity2) inset;
        } @else {
            -moz-box-shadow: #{$xOffSet}px #{$yOffSet}px #{$blur}px rgba($red,$green,$blue, $opacity) inset, #{$xOffSet2}px #{$yOffSet2}px #{$blur2}px rgba($red2,$green2,$blue2, $opacity2);
        }
    } @else {
        -moz-box-shadow: #{$xOffSet}px #{$yOffSet}px #{$blur}px rgba($red,$green,$blue, $opacity) inset;
    }
  } @else {
    @if $two {
        @if $inset2 {
            -moz-box-shadow: #{$xOffSet}px #{$yOffSet}px #{$blur}px rgba($red,$green,$blue, $opacity), #{$xOffSet2}px #{$yOffSet2}px #{$blur2}px rgba($red2,$green2,$blue2, $opacity2) inset;
        } @else {
            -moz-box-shadow: #{$xOffSet}px #{$yOffSet}px #{$blur}px rgba($red,$green,$blue, $opacity), #{$xOffSet2}px #{$yOffSet2}px #{$blur2}px rgba($red2,$green2,$blue2, $opacity2);
        }
    } @else {
        -moz-box-shadow: #{$xOffSet}px #{$yOffSet}px #{$blur}px rgba($red,$green,$blue, $opacity);
    }
  }
}

该mixin需要17个参数。很抱歉参数这么多,但是SASS不支持数组或对象。无论如何,其中10个是可选的。它们是:
- $xOffSet - 第一个阴影的x偏移量 - $yOffSet - 第二个阴影的y偏移量 - $blur - 第一个阴影的模糊程度 - $red - 第一个阴影的红色值 - $blue - 第一个阴影的蓝色值 - $green - 第一个阴影的绿色值 - $opacity - 第一个阴影的透明度 - $inset(可选)- True或False。指示第一个阴影是否应该是内嵌的(默认为false) - $two(可选)- True或False - 如果要定义两个边框,则为True(默认为false) - $xOffSet2(可选)- 第二个阴影的x偏移量 - $yOffSet2(可选)- 第二个阴影的y偏移量 - $blur2(可选)- 第二个阴影的模糊程度 - $red2(可选)- 第二个阴影的红色值 - $blue2(可选)- 第二个阴影的蓝色值 - $green2(可选)- 第二个阴影的绿色值 - $opacity2(可选)- 第二个阴影的透明度 - $inset2(可选)- True或False。指示第二个阴影是否应该是内嵌的(默认为false)
您可以像这样设置样式:
#someDiv {
    @include boxShadow(0, 0, 5, 0, 0, 0, .25);
}
#someOtherDiv {
    @include boxShadow(0, 0, 5, 0, 0, 0, .25, true);
}

#theLastDiv {
    @include boxShadow(0, 0, 5, 0, 0, 0, .25, false, true, 0, 1, 0, 255, 255, 255, .2, true);
}

生成以下CSS:
/* line 9, ../src/screen.scss */
#someDiv {
  -moz-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.25);
}

/* line 12, ../src/screen.scss */
#someOtherDiv {
  -moz-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.25) inset;
}

/* line 16, ../src/screen.scss */
#theLastDiv {
  -moz-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.25), 0px 1px 0px rgba(255, 255, 255, 0.2) inset;
}

是的。在我发布问题后不久,我构建了几乎相同的东西。很遗憾,在SASS中没有更好的构建这种东西的方法。如果SASS添加了一些连接类型的功能,那将会很有趣。也许这要求太多了。 - Steve Klein

1

当我在为Sass主题化时遇到相同的问题(参考:如何正确生成Sass主题),我解决了这个问题。

我通过使用变量来处理box-shadow,然后在代码中使用该变量来解决问题:

$btn-shadow-light: rgba(15, 15, 15, 0.1) 0px 0px 0px 1px, rgba(15, 15, 15, 0.1) 0px 2px 4px;
$btn-shadow-dark: rgba(15, 15, 15, 0.2) 0px 0px 0px 1px, rgba(15, 15, 15, 0.2) 0px 2px 4px;
$themes: (
  light: (
    color: rgba(55, 53, 47, 0.6),
    fill: rgba(55, 53, 47, 0.6),
    background: rgba(55, 53, 47, 0.08),
    floating-btn-shadow: $btn-shadow-light,
  ),
  dark: (
    color: rgba(255, 255, 255, 0.6),
    fill: rgba(255, 255, 255, 0.6),
    background: rgb(71, 76, 80),
    floating-btn-shadow: $btn-shadow-dark,
  ),
);

0

学习指南代码可能是值得的研究

然而,他们似乎也使用了一些服务器端的帮助程序。

@mixin box-shadow(
  $shadow-1 : default,
  $shadow-2 : false,
  $shadow-3 : false,
  $shadow-4 : false,
  $shadow-5 : false,
  $shadow-6 : false,
  $shadow-7 : false,
  $shadow-8 : false,
  $shadow-9 : false,
  $shadow-10: false
) {
  @if $shadow-1 == default {
    $shadow-1 : -compass-space-list(compact(if($default-box-shadow-inset, inset, false), $default-box-shadow-h-offset, $default-box-shadow-v-offset, $default-box-shadow-blur, $default-box-shadow-spread, $default-box-shadow-color));
  }
  $shadow : compact($shadow-1, $shadow-2, $shadow-3, $shadow-4, $shadow-5, $shadow-6, $shadow-7, $shadow-8, $shadow-9, $shadow-10);
  @include experimental(box-shadow, $shadow,
    -moz, -webkit, not -o, not -ms, not -khtml, official
  );
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接