简体   繁体   English

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

[英]LESS CSS: Reuse generated .@{name} class as a mixin

I'm using LESS CSS 1.3.3. 我正在使用LESS CSS 1.3.3。 Sorry if this question has already been asked, I didn't find anything relevant on the web. 对不起,如果已经提出这个问题,我在网上找不到任何相关内容。

I have several class generators that look like this (example extremely simplified, just enough to trigger the error): 我有几个看起来像这样的类生成器(示例非常简化,足以触发错误):

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

Then I use them to generate some actual classes: 然后我用它们来生成一些实际的类:

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

So far, so good, LESS correctly generates those classes and I can use them in the HTML. 到目前为止,很好,LESS正确生成了这些类,我可以在HTML中使用它们。 However when I want to reuse such a generated class as a mixin somewhere else, I get an error: 但是当我想在其他地方重用这样生成的类作为mixin时,我收到一个错误:

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

The error I get is: 我得到的错误是:

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

Of course I try to use the mixin after the class has been generated. 当然,我尝试在生成类之后使用mixin。 It looks like LESS somehow won't register such generated classes internally after it generates them, but I could well be wrong. 看起来像 LESS以某种方式在生成它们之后不会在内部注册这些生成的类,但我可能错了。

Is there a way to reuse such generated classes as mixins in other classes? 有没有办法在其他类中重用这些生成的类作为mixins? Being quite new with LESS, and their documentation being rather sparse about generated classes, I'm at a total loss (especially since this is the only syntax that seems to be accepted for mixins). 作为LESS的新手,他们的文档对生成的类相当稀疏,我完全失去了(特别是因为这是mixins似乎接受的唯一语法)。

Thanks for reading me. 谢谢你读我


Note: The reason why I use such class generators is because they are much more complex than the example above (think nested classes that all depend on a common set of parameters), and I'm embedding the generated classes in various @media queries to support any device type in a "Zen" fashion. 注意:我使用这样的类生成器的原因是因为它们比上面的例子复杂得多(想想所有依赖于一组公共参数的嵌套类),并且我将生成的类嵌入到各种@media查询中以“Zen”方式支持任何设备类型。 In the end I get something like: 最后我得到了类似的东西:

@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

Solution / test case 解决方案/测试用例

Here's a test case for @MartinTurjak 's solution, I can confirm that this works as expected, nested classes and everything: 这是@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;
}

Which correctly generates: (notice how explicit/generated yield the very same result) 哪个正确生成:(注意显式/生成如何产生相同的结果)

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

Unfortunately. 不幸。 The selector interpolation is just string interpolation, and the string gets then printed into css, so no class object is generated in the less run. 选择器插值只是字符串插值,然后将字符串打印到css中,因此在较少的运行中不会生成类对象。

So you can design a generator/mixin, that includes your operation: 所以你可以设计一个发电机/混合,包括你的操作:

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

But then build classes by calling the mixins / generators: 但是通过调用mixins / generators来构建类:

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

And this way they are class objects that you can use for mixin =) 这样它们就是你可以用于mixin =)的类对象

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

This looks a bit silly in this simple example, but maybe something like this: 在这个简单的例子中,这看起来有点傻,但也许是这样的:

 #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
}

Or something that does even more exciting stuff with the arguments 或者用参数做更令人兴奋的事情

UPDATE LESS 1.7+ (Works as Desired) 更新1.7+(按预期工作)

The .@{name} syntax will now work just as the original question had desired. .@{name}语法现在可以像原始问题所希望的那样工作。

LESS 1.4+ Workaround to Actually Use Dynamic Class Names 实际使用动态类名称的工作量少于1.4+

I came up with a work around for this while working on another question, so I'm posting it as a second answer, since it goes in a totally different direction than my earlier answer. 我在处理另一个问题时想出了一个解决方法,所以我将它作为第二个答案发布,因为它与我之前的答案完全不同。

This solution requires a couple of steps (so is not as convenient as a final fix in LESS would be), but would give actual functionality of being able to use dynamically generated class names . 这个解决方案需要几个步骤(因此不像LESS中的最终修复那么方便),但是会给出能够使用动态生成的类名的实际功能

First: Define your dynamic classes 第一:定义动态类

This is just as you planned. 这和你的计划一样。

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

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

Second: Compile that file into CSS 第二步:将该文件编译为CSS

So lets say you compile your dynamicClasses.less into dynamicClasses.css . 因此,假设您将dynamicClasses.less编译为dynamicClasses.css This causes the dynamic class names to "resolve" to actual classes. 这会导致动态类名称“解析”为实际的类。

Third: Import that CSS as LESS into a 2 nd LESS file that uses the dynamic class names 第三步:将CSS作为LESS导入到使用动态类名的第二个 LESS文件中

Using type casting for @import , we do this: 使用@import 类型转换 ,我们这样做:

@import (less) dynamicClasses.css;

This takes those resolved class names in the dynamicClasses.css file and imports them as LESS , which makes all the class names now available as mixins. 这将在dynamicClasses.css文件中获取这些已解析的类名,并将它们作为LESS导入 ,这使得所有类名现在都可用作mixins。 So you can do as you desired: 所以你可以按照自己的意愿去做:

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

I agree. 我同意。 It looks like LESS does not register those classes for mixin purposes. 看起来LESS没有为mixin目的注册这些类。

Incomplete Solution 不完整的解决方案

This LESS code: 这个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); 
}

Generates this CSS 生成这个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;
}

Explanation and Disscussion of Final Issue to Resolve 对最终解决问题的解释和讨论

Each mixin is defining a guarded .get() mixin based off the @name to get the styles, and that is cross checked to a unique NameCheck variable name for that mixin. 每个mixin都根据@name定义一个受保护的.get() mixin来获取样式,然后交叉检查该mixin的唯一NameCheck变量名。 All your actual code is defined in the .get() , and that mixin is used to actually generate the .@{name} class code. 所有实际代码都在.get()定义,而mixin用于实际生成.@{name}类代码。

This works fine every time for generating the actual class name. 每次生成实际的类名时都可以正常工作。 However, the getter function at present is only working for the class name last defined by a use of the mixin. 但是,目前的getter函数仅适用于最后使用mixin 定义的类名。 So as you can see above, my get call for mtStandard is not working because my setting of mtSpecial has apparently overwritten the #genMarginTop .get() mixin with the mtSpecial definition. 正如你在上面看到的那样,我对mtStandard 调用不起作用,因为mtSpecial 设置 mtSpecial已经用mtSpecial定义覆盖了#genMarginTop .get() mixin。

Now I assume you are going to want to call #getMarginTop and your other such mixins more than once, so obviously this is still an incomplete solution . 现在我假设您要#getMarginTop调用#getMarginTop和其他类似的mixin,所以显然这仍然是一个不完整的解决方案 I've figured out how you can get the class generated by the top level mixin to be used as a 'mixin' for another class using the .get() , but I haven't figure out how to make the .get() not get overridden when the top level mixin is called again. 我已经弄清楚如何使用.get()将顶层mixin生成的类用作另一个类的'mixin',但我还没弄明白如何制作.get()当再次调用顶级mixin时,不会被覆盖。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM