嵌套混合在LESS行为中

Sun*_*tva 1 css inheritance mixins concept less

在LESS中是否可以将mixin嵌套在另一个中,以便只有当元素是后者mixin的元素的子元素时才调用前者?

我知道,令人困惑,这是一个简单的例子(不是工作代码,只是概念):

.foo(@x) {
    width: @x;

    .foo(@y) {
        width: @y/@x;
    }
}

.a {
    .foo(20px);

    .b { 
        .foo(2);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出CSS

.a {
    width: 20px;
}

.a .b {
    width: 10px;
}
Run Code Online (Sandbox Code Playgroud)

当我这样做,要求.foo(2).b给编译成width: 2.

这应该是这样的设计,还是我在语法上出错了?另外,我是从一个完全错误的角度来解决这个问题,也许有一个更简单的解决方案,我没有考虑?

编辑

好吧,显然这是用最新版本的LESS修复的,但我想要实现的,比我上面给出的最小例子稍微复杂一些.

基本上我想要发生的是,每个.foo使用.foomixin 的另一个元素的子元素都会将其父变量用于计算,因此,理想情况下

.foo(@x) {
    width: @x;

    .foo(@y) {
        width: (@x/@y);
    }
}

.a {
    .foo(100px);

    .b { 
        .foo(2px);

        .c {
            .foo(5px);
            /* ...and so on */
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出CSS

.a {
    width: 100px;
}

.a .b {
    width: 50px;
}

.a .b .c {
    width: 10px;
}
Run Code Online (Sandbox Code Playgroud)

我得到的是,相反:

.a .b .c {
    width: 50px;
}
Run Code Online (Sandbox Code Playgroud)

我试着按如下方式修改LESS:

.foo(@x) {
    width: @x;

    .foo(@y) {
        @x:    (@x/@y)
        width: (@x);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是我得到了递归变量定义的语法错误.显然LESS不允许定义如下:

@a: 1;
@a: (@a+1);
Run Code Online (Sandbox Code Playgroud)

Mar*_*jak 5

我认为这里的主要问题是@y/@x.尝试@x/@y,它应该给予更多的期待;-)

由于嵌套的mixins在不同的较少实现中被解释为不同,我现在将答案分为两部分:

1.在less2css.org上工作的溶剂,LESS> 1.3.1(使用嵌套的mixins)

否则我认为上面的代码实际上在less2css.org上做了你想要的.正如LESS 1.4中的概念一样,您需要小心数学,因为默认情况下它需要在括号中.

如果你现在只是在非规则的规则上调用这样的mixin,比如

.b {.foo(@y); }

你需要在输入变量中使用单位,或者unit()在你的mixin中使用ad ,否则你只会得到你输入的数字,例如2:

.foo(@x) {
    width: unit(@x,px);
    .foo(@y) {
        width: (@x/@y);
    }
}

.a {
    .foo(20px);
    .b{
        .foo(2);
     }
}
.c {
    .foo(2);
}
Run Code Online (Sandbox Code Playgroud)

将输出CSS:

.a {
  width: 20px;
}
.a .b {
  width: 10px;
}
.c {
  width: 2px;
}
Run Code Online (Sandbox Code Playgroud)

您甚至可以变得更加漂亮,并且如果子类中的属性将pixles作为一个单元,请与守卫核对,这样您也可以在不传递因子的情况下嵌套类:

.foo(@x) {
    width: @x;
    .foo(@y) when (ispixel(@y)) {
        width: @y;
    }
    .foo(@y) when not (ispixel(@y)) {
        width: (@x/@y);
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,测试这个嵌套的mixin解决方案似乎只适用于less2css.org,但不适用于jsbin.com,lesstester.com和其他一些服务[需要调用嵌套(第二)级别的mixin).foo .too,以应用第二级来自mixin的样式].

所以我提出了一种替代方法,我测试了它,它似乎适用于所有提到的页面,使用less-css编译器,小于1.2.

2.使用防护装置的解决方案ispixel应该适用于大多数LESS> 1.2安装

您可以构建两个mixin,而不是嵌套的mixin,它们基于警卫检查像素作为单位.

  • 如果属性@x是像素=>返回width:@x;并分配@x给变量@width
  • 如果属性@x是不是在像素=>返回width:@width/@x;(注意: @width需要预先分配通过调用与所述混入@xpx第一)

示例少:

.foo(@x) when (ispixel(@x)) {
        width:@x;
        @width:@x;
}
.foo(@x) when not (ispixel(@x)) {
        width: (@width/@x);
}


.a, .b {
  background-color: #ddd;
  height: 100px;
}
.a {
  .foo(100px);
  .b {
    background-color: red;
    .foo(2);
  }
}
Run Code Online (Sandbox Code Playgroud)

输出CSS:

.a, .b {
  background-color: #ddd;
  height: 100px;
}
.a {
  width: 100px;
}
.a .b {
  background-color: red;
  width: 50px;
}
Run Code Online (Sandbox Code Playgroud)

与您的方法不同,但也许更直接,似乎运作良好.

编辑:

因此,您不希望区分单元输入和单元输入,我只能考虑调用两个参数mixin,其中一个参数用于基数(width在您的情况下),第二个作为默认值的因子到此1.您可以根据需要递归调用.

减:

.foo(@x,@y:1){
    width:unit(@parent,px);
    @parent:(@x/@y);
}


.a {
    .foo(100px);
    .b{
        .foo(@parent,2px);
        .c{
            .foo(@parent,5px);
            .d{
                .foo(@parent,0.05);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出CSS:

.a {
  width: 100px;
}
.a .b {
  width: 50px;
}
.a .b .c {
  width: 10px;
}
.a .b .c .d {
  width: 200px;
}
Run Code Online (Sandbox Code Playgroud)

所以现在输入的单位并不重要,因为你可以在mixin中为输出分配所需的单位.当你调用mixin时,它会覆盖@parent当前作用域的变量,然后继承到嵌套规则,在@x再次调用mixin时可以将其用作width参数.这应该会给你想要的结果.