css - 在LESS中使用属性名称中的变量(动态属性/属性名称插值)

标签 css less vendor-prefix

我注意到用SASS编写的inuit.css具有.vendor混合:

@mixin vendor($property, $value...){
    -webkit-#{$property}:$value;
       -moz-#{$property}:$value;
        -ms-#{$property}:$value;
         -o-#{$property}:$value;
            #{$property}:$value;
}

有没有办法在LESS中使用一些奇怪的功能(例如e()和@ {})来复制它?

最佳答案

更新:LESS> = 1.6
从1.6版开始(请参见 changelog ),在LESS中实现了属性名称插值。因此,您不再需要任何魔术。 (对于较旧的版本,请参阅我的原始答案。)
您的mixin基本上可以按以下方式工作:
减:

.vendor(@property; @value){
    -webkit-@{property}: @value;
       -moz-@{property}: @value;
        -ms-@{property}: @value;
         -o-@{property}: @value;
            @{property}: @value;
}

/*example*/
.test {
    .vendor(transform, translateX(20px));
}
CSS:
.test {
  -webkit-transform: translateX(20px);
  -moz-transform: translateX(20px);
  -ms-transform: translateX(20px);
  -o-transform: translateX(20px);
  transform: translateX(20px);
}

原始答案:LESS <1.6
据我所知,很少有人没有添加对动态插入属性的支持,这在前面已经讨论了很多次,请参见:
  • LESS CSS Escape entire CSS rule with different prefixes?
  • Generic `vendors` mixin
  • Rounded corner tables with LESS

  • 因此,通常的方式是使用参数混合和模式匹配...这样会增加一些硬编码...但是属性和不同的供应商有时仍然需要稍微不同的参数格式,因此需要更多的控制以这种方式添加。
    解决方法#1:将动态生成的属性注入(inject)属性值
    解决方法的第一个选项有点丑陋,但我尝试过,它可以在http://less2css.org上使用。
    因此,我尝试将动态创建的属性注入(inject)到另一个由您硬编码的属性的值中(我刚刚在此处给了一个随机的“供应商”名称-inj并将其分配为ect值,但是您可能想使用一些有用的方法代替(如果您已经从所有供应商mixin中添加了元素)
    .vendors(@property, @value, @pre: ect) {
        -inj:~"@{pre}; -webkit-@{property}: @{value}; -moz-@{property}: @{value}; -ms-@{property}: @{value}; -o-@{property}: @{value}; @{property}: @{value}";
    }
    
    我们可以在一个示例上进行尝试-也许值得尝试的东西...让我们简短地尝试一下:
    (少):
    .test-class{
        .vendors(transform, matrix(1,0,0,1,20,20));
        .vendors(transform-origin,"10px 10px");
    }
    
    CSS输出:
    .test-class {
        -inj: ect; -webkit-transform: matrix(1, 0, 0, 1, 20, 20); -moz-transform: matrix(1, 0, 0, 1, 20, 20); -ms-transform: matrix(1, 0, 0, 1, 20, 20); -o-transform: matrix(1, 0, 0, 1, 20, 20); transform: matrix(1, 0, 0, 1, 20, 20);
        -inj: ect; -webkit-transform-origin: 10px 10px; -moz-transform-origin: 10px 10px; -ms-transform-origin: 10px 10px; -o-transform-origin: 10px 10px; transform-origin: 10px 10px;
    }
    
    这似乎产生工作的CSS,但感觉kinnda错误=)

    解决方法#2:将动态生成的属性注入(inject)以下类的名称(最高v1.3.3)
    因此,我对这个想法进行了更多尝试,并想到了一种不会产生不必要属性的方法。它将动态创建的属性注入(inject)到下一个类的名称中。让我告诉你我是如何工作的:
    1)让我们定义一个通用的供应商混合(@rest参数稍后将用于排列多个供应商块)
    .vendors(@property, @value, @rest:"") {
        @inject:~"@{rest} -webkit-@{property}: @{value}; -moz-@{property}: @{value}; -ms-@{property}: @{value}; -o-@{property}: @{value}; @{property}: @{value};";
    }
    
    2)构造一个虚拟类/规则集,我们希望将供应商包含在其中,但是我们将其作为一个mixin,最后构造了下一个类welwel-因此,我们实际上制作了一个mixin,它将递归地构建两个或多个类。例如(使用与上述相同的示例),我们可以编写如下内容(注意在第二个@inject调用中使用.vendor()将两个供应商块绑定(bind)在一起):
    .test(@nextclass){
        .vendors(transform, "matrix(2,0,0,2,20,20)");
        .vendors(transform-origin,"10px 10px", @inject);
        (~"{@{inject}} .@{nextclass}"){/*next class properties*/};
    }
    
    3)现在,我们将这个mixin包装到另一个类中以显示在CSS中:
    .this-class{
        .test(next-class);
    }
    
    生成的 CSS 将包括以下内容:
    .this-class {
      -webkit-transform: matrix(2, 0, 0, 2, 20, 20);
      -moz-transform: matrix(2, 0, 0, 2, 20, 20);
      -ms-transform: matrix(2, 0, 0, 2, 20, 20);
      -o-transform: matrix(2, 0, 0, 2, 20, 20);
      transform: matrix(2, 0, 0, 2, 20, 20);
      -webkit-transform-origin: 10px 10px;
      -moz-transform-origin: 10px 10px;
      -ms-transform-origin: 10px 10px;
      -o-transform-origin: 10px 10px;
      transform-origin: 10px 10px;
    }
    .next-class {
      /*next class properties*/
    }
    
    输出将仅在一行中。
    编辑:要获得更好的格式设置,可以包括"\n""\t"的javascript插值,请参阅下面评论中的Scott建议。
    这样,您现在可以使用供应商mixin链接多个类,而无需任何不必要的属性。

    解决方法#3:使用递归将动态生成的属性注入(inject)到以下类(v1.4.0)的名称中
    我正在添加此原因,因为Scott在其中一项评论中指出,版本1.4所进行的更改将不允许解决方法#2。但是,如果我们有足够的资源,我们可以克服这个问题。让我们看看上述解决方法有哪些问题并加以解决。
    1)第一个问题是“不赞成使用(~".@{index}") { ...选择器插值”,因此我们需要在单独的步骤中进行字符串插值。实现这一点足以从上方注入(inject)单个.vendors mixin。
    最少:(使用Scott的换行符建议):
    @nl: `"\n\t"`;        
    .vendors(@property, @value) {
        @inject:~"@{nl}-webkit-@{property}: @{value};@{nl}-moz-@{property}: @{value};@{nl}-ms-@{property}: @{value};@{nl}-o-@{property}: @{value};@{nl}@{property}: @{value};";
    }
    .test(@nextclass){
        .vendors(transform, "matrix(2,0,0,2,20,20)");
        @inj: ~"{@{inject}`'\n'`} `'\n'`.@{nextclass}";
        @{inj} {/*next class properties*/}
    }
    .this-class{
        .test(next-class);
    }
    
    CSS输出:
    .this-class {
        -webkit-transform: matrix(2,0,0,2,20,20);
        -moz-transform: matrix(2,0,0,2,20,20);
        -ms-transform: matrix(2,0,0,2,20,20);
        -o-transform: matrix(2,0,0,2,20,20);
        transform: matrix(2,0,0,2,20,20);
    } 
    .next-class {
        /*next class properties*/
    }
    
    2)第二个问题是“mixin中的变量不再'泄漏'到其调用范围内”,但我在1.4.0 beta中注意到,如果仅在mixin中引入变量,则仍可以调用它从包含的规则集中开始,只需稍作递归,就可以构造.vendors块,并在最后一步中将它们分配给新变量,然后将其用于注入(inject)。我也很兴奋,并使用了此less版本中引入的新extract()函数。使用@i变量,我们指定递归级别(要注入(inject)的供应商块数)。
    (少):
    @nl: `"\n\t"`; 
    .multi(@props,@vals,1,@inj) {
        @property: extract(@props, 1);
        @value: extract(@vals, 1);
        @inject:~"@{inj}@{nl}-webkit-@{property}: @{value};@{nl}-moz-@{property}: @{value};@{nl}-ms-@{property}: @{value};@{nl}-o-@{property}: @{value};@{nl}@{property}: @{value};";
    }
    
    .multi(@props,@vals,@i,@inj:"") when (@i > 0) {
        @property: extract(@props, @i);
        @value: extract(@vals, @i);
        @injnext:~"@{inj}@{nl}-webkit-@{property}: @{value};@{nl}-moz-@{property}: @{value};@{nl}-ms-@{property}: @{value};@{nl}-o-@{property}: @{value};@{nl}@{property}: @{value};";
        .multi(@props,@vals,(@i - 1),@injnext);
    }
    
    @properties: "transform-origin" "transform";
    @values: "10px 10px" "matrix(2,0,0,2,20,20)";
    
    // string of other properties you want to include in the same class
    @p: ~"@{nl}width:20px; @{nl}height:12px; @{nl}background-color:#000;";
    
    .this-class {
        .multi(@properties,@values,2,@p);
        @inj: ~"{@{inject}`'\n'`} `'\n'`.next-class ";
        @{inj} {/**/}
    }
    
    CSS输出:
    .this-class {
      width:20px;
      height:12px;
      background-color:#000;
      -webkit-transform: matrix(2, 0, 0, 2, 20, 20);
      -moz-transform: matrix(2, 0, 0, 2, 20, 20);
      -ms-transform: matrix(2, 0, 0, 2, 20, 20);
      -o-transform: matrix(2, 0, 0, 2, 20, 20);
      transform: matrix(2, 0, 0, 2, 20, 20);
      -webkit-transform-origin: 10px 10px;
      -moz-transform-origin: 10px 10px;
      -ms-transform-origin: 10px 10px;
      -o-transform-origin: 10px 10px;
      transform-origin: 10px 10px;
    }
    .next-class {
      /*next class properties*/
    }
    
    现在,在1.4.0 beta中,这对我来说效果很好,但是让我们看看 future 会怎样。

    关于css - 在LESS中使用属性名称中的变量(动态属性/属性名称插值),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14868042/

    相关文章:

    css - IE10/11 使用转换 :-webkit-transform?

    css - 将 "-webkit-"以外的供应商特定前缀用于 "transition"是否有任何意义?

    javascript - vanilla javascript 前缀以 css 选择器开头

    javascript - 切换时如何隐藏div a

    css - 使用变换属性创建背景

    loops - 在 Less 中循环变量名数组

    css - WordPress 是 SASS 还是 LESS?

    javascript - 在表行中展开和折叠

    javascript - 如何使 div 可拖动且可编辑 ="true"?

    javascript - Jasny Bootstrap Off Canvas 'Reveal' 方法 - 故障排除