【问题标题】:Is it possible with LESS CSS to store multiple arguments in a variable?LESS CSS 是否可以在一个变量中存储多个参数?
【发布时间】:2014-03-19 03:28:00
【问题描述】:

我希望下面的 mixin 能够理解我想传递多个参数而不是使用 3px, 0, 0, 3px 作为单个参数。

注意:我确实意识到我可以制作 @myRadius: 3px.border-radius( @myRadius, 0, 0 @myRadius );。我只是不想。

示例代码(粘贴到LESSTESTER 以查看输出):

.border-radius(@topright: 0, @bottomright: 0, @bottomleft: 0, @topleft: 0) {
     -webkit-border-top-right-radius: @topright;
  -webkit-border-bottom-right-radius: @bottomright;
   -webkit-border-bottom-left-radius: @bottomleft;
      -webkit-border-top-left-radius: @topleft;

     -moz-border-radius-topright: @topright;
  -moz-border-radius-bottomright: @bottomright;
   -moz-border-radius-bottomleft: @bottomleft;
      -moz-border-radius-topleft: @topleft;

     border-top-right-radius: @topright;
  border-bottom-right-radius: @bottomright;
   border-bottom-left-radius: @bottomleft;
      border-top-left-radius: @topleft;
}

@myRadius: 3px, 0, 0, 3px;

div {
    .border-radius( @myRadius );
}

【问题讨论】:

    标签: less


    【解决方案1】:

    简而言之:不,目前这是不可能的(变量总是作为一个 mixin 参数)。 (“参数列表扩展”功能实际上已经实现,可能会出现在 Less 2.0 中,但它需要一些支持,请参阅 #1857 - 不要犹豫到 +1 那里)。

    解决方法

    1

    您可以通过 mixin 特化创建“智能参数处理”(请参阅​​ Pattern Matching)。 例如。 (小于 1.6+):

    .border-radius(@tr: 0, @br: 0, @bl: 0, @tl: 0) when (default()) {
        border-top-right-radius:    @tr;
        border-bottom-right-radius: @br;
        border-bottom-left-radius:  @bl;
        border-top-left-radius:     @tl;
    }
    
    .border-radius(@values) when (length(@values) = 4) {
        .border-radius(
            extract(@values, 1),
            extract(@values, 2),
            extract(@values, 3),
            extract(@values, 4));
    }
    
    // you also have to provide specializations for
    // (length(@values) = 2) and (length(@values) = 3)
    // cases if you need to handle them
    
    // ...............................................
    // usage:
    
    @myRadius: 3px, 0, 0, 3px;
    
    a {
        .border-radius(1px, 2px);
    }
    
    b {
        .border-radius(@myRadius);
    }
    

    2

    和上面一样,只是稍微不那么冗长的变体(Less 1.5+):

    .border-radius(@values...) {
        .-() {@tr: 0; @br: 0; @bl: 0; @tl: 0} .-();
        .-() when (length(@values) > 0) {@tr: extract(@values, 1)}
        .-() when (length(@values) > 1) {@br: extract(@values, 2)}
        .-() when (length(@values) > 2) {@bl: extract(@values, 3)}
        .-() when (length(@values) > 3) {@tl: extract(@values, 4)}
    
        border-top-right-radius:    @tr;
        border-bottom-right-radius: @br;
        border-bottom-left-radius:  @bl;
        border-top-left-radius:     @tl;
    }
    
    // ...............................................
    // usage:
    
    @myRadius: 3px, 0, 0, 3px;
    
    a {.border-radius(1)}
    b {.border-radius(1, 2)}
    c {.border-radius(1, 2, 3)}
    d {.border-radius(1, 2, 3, 4)}
    e {.border-radius(1 2 3 4)}
    f {.border-radius(@myRadius)}
    // etc.
    

    3

    不是一种解决方法,而是“以防万一”备注,如果用例仅限于基本 CSS 属性,如果您真的需要默认值是 0 而不是实际的 CSS,这实际上是有问题的”默认值”(即为什么我们需要将.border-radius(1, 2) 扩展为border-radius: 1 2 0 0; 而不是border-radius: 1 2;?)。相反,我希望混合遵循 CSS 语法,这样就可以很简单:

    .border-radius(@values...) {
        // ...
        border-radius: @values;
    }
    
    // ...............................................
    // usage:
    
    @myRadius: 3px 0 0 3px; // no commas here
    
    a {.border-radius(1)}
    b {.border-radius(1, 2)}
    c {.border-radius(1, 2, 3)}
    d {.border-radius(1, 2, 3, 4)}
    e {.border-radius(1 2 3 4)}
    f {.border-radius(@myRadius)} 
    

    附:和我一样:如果你对这类东西的用例仅限于供应商前缀,请考虑在你的构建链中添加一个自动前缀工具,以停止浪费你的时间来编写这些供应商化预处理器 mixin (see also)。

    【讨论】:

    • 非常好的例子@seven-phases-max。我不确定,但我认为你不能有一个名为 .-() 的 mixin(你可能想将其重命名为 ._().tmp()
    • 更少的变量和选择器(如果它们以.# 开头,则混入)可能包含A...Za...z0...9_- 字符并从其中任何一个开始。例如:.-.0.444-87-80 是有效的 mixin 名称(而 @-@42 是有效的变量 :)
    • 好的。我提到过,因为我曾经遇到过一个名为.-() 的mixin 问题,我不得不将其更改为._() 才能使其正常工作。但那是不久前的事了。也许它现在支持它。
    • 非常令人耳目一新的答案,干得好!选项 3 显然是边界半径情况的最佳选择(我不记得为什么我编写了 mixin 来明确分配每个角)。无论如何,我的示例代码只是为了说明这一点。选项 1 很酷,感谢您指出 GitHub 问题。另外,感谢您提醒我,我什至不需要供应商前缀 border-radius 了。另外,感谢您向我指出 Autoprefixer(我真的需要安装它......无处不在......永远)。简而言之,你是个坏蛋。干杯!
    【解决方案2】:

    有一种方法可以“将多个参数存储在一个变量中”,但是必须设置 mixin 来处理它,并且还必须正确设置变量定义。

    使用 LESS 1.7.0+

    考虑一下:

    @callPropterySet: {@props();};
    
    .border-radius(@topright: 0; @bottomright: 0; @bottomleft: 0; @topleft: 0; @varSet: @callPropterySet) {
        @varSet();
        @props: {
         -webkit-border-top-right-radius: @topright;
      -webkit-border-bottom-right-radius: @bottomright;
       -webkit-border-bottom-left-radius: @bottomleft;
          -webkit-border-top-left-radius: @topleft;
    
         -moz-border-radius-topright: @topright;
      -moz-border-radius-bottomright: @bottomright;
       -moz-border-radius-bottomleft: @bottomleft;
          -moz-border-radius-topleft: @topleft;
    
         border-top-right-radius: @topright;
      border-bottom-right-radius: @bottomright;
       border-bottom-left-radius: @bottomleft;
          border-top-left-radius: @topleft;
      };
    }
    
    @myRadii: {
        @topright: 3px; 
        @bottomright: 0; 
        @bottomleft: 0; 
        @topleft: 3px;
        @callPropterySet(); //have to include this call again
    };
    

    我已经为规则集设置了一个全局变量,以调用 mixin 中的属性设置,@callPropterySet: {@props();};。这允许我将它设置为我重新定义的 mixin 的默认值,它使用自己的新变量 @varSet 调用它。 @props() 本身通过 @varSet 访问的实际规则集是在 mixin 本身内部定义的。这样就可以灵活地以各种不同的方式调用 mixin,如下所示:

    div {
        .border-radius(@varSet: @myRadii); //call with the single variable
    }
    
    .test {
        .border-radius(10px, 5px, 4px, 2px); //call with properties
    }
    
    .test2 {
        .border-radius(); //call with defaults
    }
    

    所有都会产生预期的输出。但是请注意,进行这项工作的关键是让该单个变量也将@callPropterySet(); 作为其规则集的一部分。显然,目前(LESS 1.7)在规则集中定义的变量仅在该规则集的范围内被考虑(它们不会像 mixin 那样扩展到范围内)。

    所以你目前不能做这样的事情并让它工作:

    .border-radius(@topright: 0; @bottomright: 0; @bottomleft: 0; @topleft: 0; @varSet...) {
        @varSet();
         -webkit-border-top-right-radius: @topright;
      -webkit-border-bottom-right-radius: @bottomright;
       -webkit-border-bottom-left-radius: @bottomleft;
          -webkit-border-top-left-radius: @topleft;
    
         -moz-border-radius-topright: @topright;
      -moz-border-radius-bottomright: @bottomright;
       -moz-border-radius-bottomleft: @bottomleft;
          -moz-border-radius-topleft: @topleft;
    
         border-top-right-radius: @topright;
      border-bottom-right-radius: @bottomright;
       border-bottom-left-radius: @bottomleft;
          border-top-left-radius: @topleft;
    }
    
    @myRadii: {
        @topright: 3px; 
        @bottomright: 0; 
        @bottomleft: 0; 
        @topleft: 3px;
    };
    

    因为它是这样的:

    .border-radius(@topright: 0; @bottomright: 0; @bottomleft: 0; @topleft: 0; @varSet: @callPropterySet) {
        {
          @topright: 3px; 
          @bottomright: 0; 
          @bottomleft: 0; 
          @topleft: 3px;
        }
         -webkit-border-top-right-radius: @topright;
      -webkit-border-bottom-right-radius: @bottomright;
       -webkit-border-bottom-left-radius: @bottomleft;
          -webkit-border-top-left-radius: @topleft;
    
         -moz-border-radius-topright: @topright;
      -moz-border-radius-bottomright: @bottomright;
       -moz-border-radius-bottomleft: @bottomleft;
          -moz-border-radius-topleft: @topleft;
    
         border-top-right-radius: @topright;
      border-bottom-right-radius: @bottomright;
       border-bottom-left-radius: @bottomleft;
          border-top-left-radius: @topleft;
    }
    

    这会将规则集置于与您要设置的属性不同的范围内,因此它们永远不会被设置。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-13
      • 1970-01-01
      • 1970-01-01
      • 2012-10-17
      • 1970-01-01
      • 2019-08-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多