LESS CSS:重新生成。@ {name}类作为mixin

时间:2013-02-28 14:04:19

标签: css less mixins

我正在使用LESS CSS 1.3.3。对不起,如果已经提出这个问题,我在网上找不到任何相关内容。

我有几个看起来像这样的类生成器(示例非常简化,足以触发错误):

#genMarginTop (@name, @size) {
    .@{name} { margin-top: @size; }
}

然后我用它们来生成一些实际的类:

#genMarginTop(mtStandard, 40px);
#genMarginTop(mtHalf, 20px);

到目前为止,很好,LESS正确生成了这些类,我可以在HTML中使用它们。 但是当我想在其他地方重用这样生成的类作为mixin时,我收到一个错误:

.someClass {
    .mtStandard; // won't work, see error below
    // more stuff
}

我得到的错误是:

NameError: .mtStandard is undefined in /.../example.less:161:4
160 .someClass {
161     .mtStandard;
162     // more stuff

当然,在生成类之后,我尝试使用mixin 。它看起来像 LESS在生成它们之后不会在内部注册这些生成的类,但我可能错了。

有没有办法在其他类中重复使用这些生成的类作为mixins?对LESS来说还是比较新的,而且他们的文档对于生成的类来说相当稀疏,我完全失去了(特别是因为这是mixins似乎接受的唯一语法。)

感谢您阅读。


注意:我之所以使用这样的类生成器是因为它们比上面的例子复杂得多(想想所有依赖于一组公共参数的嵌套类),而我是将生成的类嵌入到各种@media查询中,以“Zen”方式支持任何设备类型。最后我得到了类似的东西:

@media (max-width: 1024px) {
    #genSomething(something, somethingParam1, ...);
    #genSomething(somethingElse, somethingElseParam1, ...);
    #genStuff(stuff, stuffParam1, ...);
}
@media (max-width: 240px) {
    #genSomething(something, somethingParam2, ...);
    #genSomething(somethingElse, somethingElseParam2, ...);
    #genStuff(stuff, stuffParam2, ...);
}
// etc

解决方案/测试用例

这是@MartinTurjak解决方案的测试用例,我可以确认这是按预期工作的,嵌套类和所有内容:

.explicit {
  margin-top: 1;
  input { margin-top: 1; }
}
.reuseExplicit {
  .explicit;
  margin-bottom: 1;
}
#generator (@arg) {
  margin-top: @arg;
  input {
    margin-top: @arg;
  }
}
.generated { #generator(1); }
.reuseGenerated {
  .generated;
  margin-bottom: 1;
}

哪个正确生成:(注意显式/生成如何产生相同的结果)

.explicit {
  margin-top: 1;
}
.explicit input {
  margin-top: 1;
}
.reuseExplicit {
  margin-top: 1;
  margin-bottom: 1;
}
.reuseExplicit input {
  margin-top: 1;
}
.generated {
  margin-top: 1;
}
.generated input {
  margin-top: 1;
}
.reuseGenerated {
  margin-top: 1;
  margin-bottom: 1;
}
.reuseGenerated input {
  margin-top: 1;
}

3 个答案:

答案 0 :(得分:6)

不幸的是。选择器插值只是字符串插值,然后将字符串打印到css中,因此在较少的运行中不会生成类对象。

所以你可以设计一个发生器/ mixin,包括你的操作:

#genMarginTop (@size) {
  margin-top: @size;
}

然后通过调用mixins / generators来构建类:

.mtStandard {#genMarginTop(40px);}
.mtHalf {#genMarginTop(20px);}

这样他们就是你可以用于mixin =)

的类对象
.someClass {
  background-color: #FFF;
  .mtStandard;
  //more of this stuff
}

在这个简单的例子中,这看起来有点傻,但也许是这样的:

 #bggenerator (@color) {
    background-color: @color;
 }
 #bggenerator (@color, dark) {
    @blend : @color + #842210;
    background-color: darken(@blend, 30%);
 }
 #bggenerator (@color, @url, @rest) {
    background: "@{color} url('@{url}') @{rest}";
 }

 .mtStandard {
    #genMarginTop(40px);
 }

.someClass {
  .mtStandard;
  #bggenerator(#FFF, "bgimage.png", left top no-repeat);
  //more of this stuff
}

或者用参数

做更令人兴奋的事情

答案 1 :(得分:6)

更新1.7+(按预期工作)

.@{name}语法现在可以像原始问题一样工作。

实际使用动态类名称的少数1.4+解决方法

我在处理另一个问题时想出了一个解决方法,所以我将它作为第二个答案发布,因为它与我之前的答案完全不同。

此解决方案需要几个步骤(因此不像LESS中的最终修复那么方便),但会提供能够使用动态生成的类名称的实际功能

首先:定义动态类

这就像你计划的那样。

#genMarginTop (@name, @size) {
    .@{name} { margin-top: @size; }
}

#genMarginTop(mtStandard, 40px);
#genMarginTop(mtHalf, 20px);

第二:将该文件编译为 CSS

所以我们假设你将dynamicClasses.less编译成dynamicClasses.css。这会导致动态类名称“解析”为实际类。

第三:将CSS作为LESS导入到使用动态类名的2 nd LESS文件中

type casting用于@import,我们这样做:

@import (less) dynamicClasses.css;

这将在dynamicClasses.css文件中获取已解析的类名,将它们作为LESS 导入,这使得所有类名现在都可用作mixins。所以你可以按照自己的意愿去做:

.someClass {
    .mtStandard; // will work
    // more stuff
}

答案 2 :(得分:3)

我同意。看起来LESS没有为mixin目的注册这些类。

不完整的解决方案

这个LESS代码:

#genMarginTop (@name, @size) {
  @genMarginTopNameCheck: @name; 
  .get(@name) when (@name = @genMarginTopNameCheck) { margin-top: @size; }
  .@{name} { .get(@name); }
}
#genMarginBot (@name, @size) {
    @genMarginBotNameCheck: @name; 
    .get(@name) when (@name = @genMarginBotNameCheck)  { margin-bottom: @size; }
    .@{name} { .get(@name); }
}


#genMarginTop(mtStandard, 40px);
#genMarginBot(mbStandard, 20px);
#genMarginTop(mtSpecial, 80px);

.myClass {
  .get(mtStandard);
  .get(mbStandard); 
}

.myClass2 {
  .get(mtSpecial);
  .get(mbStandard); 
}

生成此CSS

.mtStandard {
  margin-top: 40px;
}
.mbStandard {
  margin-bottom: 20px;
}
.mtSpecial {
  margin-top: 80px;
}
.myClass {
  /* NOTE the mtStandard definition is missing here !!! */
  margin-bottom: 20px;
}
.myClass2 {
  margin-top: 80px;
  margin-bottom: 20px;
}

对最终解决问题的解释和讨论

每个mixin都根据.get()定义一个受保护的@name mixin来获取样式,并将其交叉检查为该mixin的唯一NameCheck变量名称。您的所有实际代码都在.get()中定义,而mixin用于实际生成.@{name}类代码。

每次生成实际的类名时都可以正常工作。但是,目前的getter函数仅适用于使用mixin的类名 最后定义 。正如您在上面看到的那样,mtStandard接听电话无效,因为mtSpecial我的设置显然已覆盖了#genMarginTop } .get() mixin与mtSpecial定义。

现在我假设你打算不止一次打电话给#getMarginTop和其他类似的混音,所以很明显 这仍然是一个不完整的解决方案 。我已经弄清楚如何将顶级mixin生成的课程用作混音'对于使用.get()的其他课程,但我还没有弄清楚当再次调用顶级mixin时如何使.get()不被覆盖。