7

我正在使用 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查询中以支持任何设备类型以“禅”的方式。最后我得到类似的东西:

@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;
}
4

3 回答 3

6

很遗憾。选择器插值只是字符串插值,然后字符串被打印到 css 中,因此在 less 运行中不会生成类对象。

因此,您可以设计一个生成器/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
}

或者用争论做更令人兴奋的事情

于 2013-02-28T18:07:30.407 回答
6

UPDATE LESS 1.7+(按要求工作)

.@{name}语法现在将按照原始问题的要求工作。

实际使用动态类名的 LESS 1.4+ 解决方法

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

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

第一:定义你的动态类

这和你计划的一样。

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

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

第二:将该文件编译成CSS

所以可以说你编译dynamicClasses.lessdynamicClasses.css. 这会导致动态类名“解析”为实际类。

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

使用类型转换for @import,我们这样做:

@import (less) dynamicClasses.css;

dynamicClasses.css这会将文件中那些已解析的类名导入为 LESS,这使得所有类名现在都可以作为 mixins 使用。所以你可以做你想做的事:

.someClass {
    .mtStandard; // will work
    // more stuff
}
于 2013-11-06T20:23:38.580 回答
3

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

不完整的解决方案

这个更少的代码:

#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()mixin@name以获取样式,并交叉检查NameCheck该 mixin 的唯一变量名。您所有的实际代码都在 中定义.get(),并且该 mixin 用于实际生成.@{name}类代码。

每次生成实际的类名都可以正常工作。但是,目前的 getter 函数仅适用于使用 mixin定义的最后一个类名。因此,正如您在上面看到的,我的get 调用mtStandard不起作用,因为我的设置显然已经用定义mtSpecial覆盖了#genMarginTop .get()mixin 。mtSpecial

现在我假设您将要#getMarginTop多次调用和您的其他此类混入,因此显然这仍然是一个不完整的解决方案。我已经弄清楚了如何让顶级 mixin 生成的类用作另一个类的“mixin” .get(),但我还没有弄清楚如何.get()在顶级 mixin被再次调用。

于 2013-02-28T17:00:46.053 回答