嵌套混合在LESS行为中

时间:2013-04-14 00:45:31

标签: css inheritance less mixins concept

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

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

LESS

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

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

.a {
    .foo(20px);

    .b { 
        .foo(2);
    }
}

输出CSS

.a {
    width: 20px;
}

.a .b {
    width: 10px;
}

当我执行此操作时,在.foo(2)上调用.b可以编译width: 2

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

修改

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

基本上我想要发生的是,每个.foo.foo mixin的另一个元素的子节点,它将使用其父变量进行计算,因此,理想情况下

LESS

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

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

.a {
    .foo(100px);

    .b { 
        .foo(2px);

        .c {
            .foo(5px);
            /* ...and so on */
        }
    }
}

输出CSS

.a {
    width: 100px;
}

.a .b {
    width: 50px;
}

.a .b .c {
    width: 10px;
}

我得到的是:

.a .b .c {
    width: 50px;
}

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

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

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

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

@a: 1;
@a: (@a+1);

1 个答案:

答案 0 :(得分:5)

我认为这里的主要问题是@y/@x。 试试@x/@y,它应该提供更多预期的东西; - )

  

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

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

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

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

.b {     包含.foo(@y); }

您需要将输入变量中的单位或广告unit()用于您的mixin,否则您只会获得您输入的数字,例如2:

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

.a {
    .foo(20px);
    .b{
        .foo(2);
     }
}
.c {
    .foo(2);
}

将输出 CSS:

.a {
  width: 20px;
}
.a .b {
  width: 10px;
}
.c {
  width: 2px;
}

你可以变得更加漂亮,并且如果子类中的属性将pixles作为一个单元,请与守卫核对,这样你也可以在没有传递因子的地方嵌套类:

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

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

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

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

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

  • 如果属性ispixel以像素为单位=>返回@x并将width:@x;分配给变量@x
  • 如果属性@width不在像素中=>返回@x注意: width:@width/@x;需要事先通过首先使用@width中的@x调用mixin来分配

示例 LESS:

px

输出 CSS

.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);
  }
}

与您的方法不同,但可能更直接一点,似乎运作良好。

编辑:

因为你不想区分输入单位和没有单位的输入,我只能想到调用两个参数mixin ,其中一个参数用于基数({{ 1}}在你的情况下)和第二个作为一个默认为1的因子。这你可以现在递归调用你想要的次数。

<强> LESS:

.a, .b {
  background-color: #ddd;
  height: 100px;
}
.a {
  width: 100px;
}
.a .b {
  background-color: red;
  width: 50px;
}

输出 CSS:

width

所以现在输入的单位并不重要,因为你可以在mixin中为输出分配所需的单位。当你调用mixin时,它会覆盖当前作用域的.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); } } } } 变量,然后继承到嵌套规则,在再次调用mixin时可以将其用作宽度参数.a { width: 100px; } .a .b { width: 50px; } .a .b .c { width: 10px; } .a .b .c .d { width: 200px; } 。这应该会给你想要的结果。