简体   繁体   English

较少CSS传递mixin作为另一个mixin的参数

[英]LESS CSS Pass mixin as a parameter to another mixin

Is there any way to pass one mixin or style's declaration to another mixin as an input parameter? 有没有办法将一个mixin或style的声明传递给另一个mixin作为输入参数?

Let's take a look at an example with animation keyframes. 我们来看一个动画关键帧的例子。 Following is how we define keyframes in pure CSS: 以下是我们如何在纯CSS中定义关键帧:

@-moz-keyframes some-name
{
    from { color: red; }
    to { color: blue; }
}

@-webkit-keyframes some-name
{
    from { color: red; }
    to { color: blue; }
}

@keyframes some-name
{
    from { color: red; }
    to { color: blue; }
}

Idea is to simplify these declarations using mixins, so we can have something like following: 想法是使用mixins简化这些声明,所以我们可以使用以下内容:

.keyframes(name, from, to)
{
    // here we need somehow to reproduce structure
    // that we have in an example above
}

// define one animation
.my-from() { color: red; }
.my-to() { color: blue; }
// the following won't work because you cannot pass mixin as a parameter
// in way I have here, so I am looking for a way to solve this problem
.keyframes('some-name', .my-from, .my-to);

// define another animation
.another-from() { font-size: 1em; }
.another-to() { font-size: 2em; }
.keyframes('another-name', .another-from, .another-to);

The system will have different modules that could be dynamically attached to application as well as removed. 系统将具有可以动态附加到应用程序以及移除的不同模块。 So, don't suggest me to use @import because it's not the case. 所以,不要建议我使用@import因为事实并非如此。 Output CSS is dynamically compiled on-fly using information about modules and their own LESS styles as well as base LESS dependencies like mixins library and etc. 使用有关模块及其自己的LESS样式的信息以及诸如mixins库等的基本LESS依赖性,动态地动态编译输出CSS。

Note: it will work for me if you know a way to pass class definition instead of mixin. 注意:如果你知道一种传递类定义而不是mixin的方法,它对我有用。 In an example above it would be .my-from instead of .my-from() and etc. 在上面的例子中,它将是.my-from而不是.my-from()等。

UPDATED for LESS 1.7.0+ ( WAY Simpler) 更新的LESS 1.7.0+(WAY简单)

We can do this far more directly now with the 1.7.0 update and the ability to create rulesets , and to use variables in setting @keyframes . 我们现在可以更直接地使用1.7.0更新和创建规则集的能力,以及在设置@keyframes使用变量

Now we really can pass a mixin through a parameter by a ruleset, or we can pass in the property stings themselves. 现在我们真的可以通过规则集传递一个参数mixin,或者我们可以自己传递属性stings。 So consider this: 所以考虑一下:

LESS (using 1.7) 少(使用1.7)

.keyframes(@name, @from, @to) {
    @frames: {
        from { @from(); }
        to { @to(); }
    };
    @pre: -moz-keyframes;
    @-moz-keyframes @name
    {
       @frames();
    }

    @-webkit-keyframes @name
    {
       @frames();
    }

    @keyframes @name
    {
       @frames();
    }
}

.keyframes(testName, {color: red; .myMix(0);}, {color: blue; .myMix(1);});

.myMix(@value) {opacity: @value;}

Note that I am passing both a property setting and a mixin call, and my output is: 请注意,我传递了属性设置和mixin调用,我的输出是:

CSS Output CSS输出

@-moz-keyframes testName {
  from {
    color: red;
    opacity: 0;
  }
  to {
    color: blue;
    opacity: 1;
  }
}
@-webkit-keyframes testName {
  from {
    color: red;
    opacity: 0;
  }
  to {
    color: blue;
    opacity: 1;
  }
}
@keyframes testName {
  from {
    color: red;
    opacity: 0;
  }
  to {
    color: blue;
    opacity: 1;
  }
}

Note how the rulesets are passed, in brackets {...} , and then called, via @from() and @to() (looking a lot like a mixin call). 注意规则集如何通过括号{...}传递,然后通过@from()@to()调用(看起来很像mixin调用)。 I'm using these passed rule sets to set another ruleset of @frames which is then itself called to fill the keyframes definitions. 我正在使用这些传递的规则集来设置@frames另一个规则集,然后调用它来填充关键帧定义。

More Generically 更一般地说

Here I pass a private mixin to another mixin and then call it from that other mixin: 在这里,我将私有mixin传递给另一个mixin,然后从其他mixin调用它:

LESS

.someMixin(@class; @expectedMixin) {
    .@{class} {
      @expectedMixin();
      .myPrivateMix(0.6);
      test: 1;
    }
}

.someMixin(newClass; {.myClass;});

.myClass {
  .myPrivateMix(@value) {opacity: @value;}
}

CSS Output CSS输出

.newClass {
  opacity: 0.6;
  test: 1;
}

Kept the below for legacy info. 保留下面的遗留信息。

Updated (added LESS 1.4.0+ support) 更新(添加了LESS 1.4.0+支持)

Wow, this took some doing, but I think I have something you can work with. 哇,这需要做一些,但我想我有一些你可以使用的东西。 However, it does take some special defining of your mixins in your modules, specifically, using pattern matching . 但是,它确实需要在模块中对mixin进行一些特殊定义,特别是使用模式匹配 So... 所以...

First, Define Your Module Mixins 首先,定义模块混合

Note how the module mixins intended to be used in a specific future mixin are defined with the same mixin name , but with a different pattern name. 请注意,在特定的未来mixin中使用的模块mixin是如何使用相同的mixin名称定义的,但具有不同的模式名称。 This was key to making this work. 这是实现这项工作的关键。

// define one animation in a module
.from(my-from){ color: red; }
.to(my-to) { color: blue; }

// define one animation in another module
.from(another-from){ font-size: 1em; }
.to(another-to) { font-size: 2em; }

If you also want individual mixin names in the modules, you should be able to do this: 如果您还需要模块中的各个mixin名称 ,您应该能够这样做:

// define one animation in a module
.my-from(){ color: red; }
.my-to() { color: blue; }

.from(my-from){ .my-from() }
.to(my-to) { .my-to() }   

// define one animation in another module
.another-from(){ font-size: 1em; }
.another-to() { font-size: 2em; }

.from(another-from){ .another-from() }
.to(another-to) { .another-to() }

This should allow one to call either the straight mixin .my-from() or, to make it variably accessible within later mixins that access the singular .from() mixin group through the pattern matching. 这应该允许一个人调用直接mixin .my-from()或者在后来的mixins中通过模式匹配访问单个.from() mixin组,使其可以变化地访问。

Next, Define Your Mixin 接下来,定义您的Mixin

For your @keyframes example, that was extremely difficult. 对于你的@keyframes示例,这非常困难。 In fact, a stack overflow answer was vital to helping me solve an issue with applying the @name , which was not applying under normal LESS rules because of it following the @keyframes definition. 事实上, 堆栈溢出答案对于帮助我解决应用@name的问题至关重要,因为它遵循@keyframes定义,因此不能在正常的LESS规则下应用。 The solution to apply the @name looks nasty, but it works. 应用@name的解决方案看起来很讨厌,但它确实有效。 It does have the, perhaps, unfortunate necessity of also defining a selector string to play the animation by (because it uses that string to help build the last } of the keyframes). 它确实有一个非常不幸的必要,即定义一个选择器字符串来播放动画(因为它使用该字符串来帮助构建关键帧的最后一个} )。 This naming limitation would only be true of css strings that begin with @ like @keyframes and probably @media . 这种命名限制只适用于以@ like @keyframes开头的css字符串,可能是@media

Further, because we have a standard mixin name used in our module files, we can access that consistently within our new mixin, while at the same time passing a variable in to select the proper variation of that mixin through a pattern match. 此外,因为我们的模块文件中使用了标准的mixin名称,所以我们可以在新的mixin中一致地访问它,同时传递变量以通过模式匹配选择该mixin的正确变体 So we get: 所以我们得到:

LESS 1.3.3 or under 少于1.3.3或以下

// define mixin in mixin file

.keyframes(@selector, @name, @from, @to) {
    @newline: `"\n"`; // Newline
    .setVendor(@pre, @post, @vendor) {
        (~"@{pre}@@{vendor}keyframes @{name} {@{newline}from") {
            .from(@from); 
        }    
        to  { 
            .to(@to);
        }
       .Local(){}
       .Local() when (@post=1) {
           (~"}@{newline}@{selector}") {
              -moz-animation: @name;
              -webkit-animation: @name;
              -o-animation: @name;
              -ms-animation: @name;
              animation: @name;
           } 
       }    
       .Local;
    } 
    .setVendor(""            , 0,    "-moz-");
    .setVendor(~"}@{newline}", 0, "-webkit-");
    .setVendor(~"}@{newline}", 0,      "-o-");
    .setVendor(~"}@{newline}", 0,     "-ms-");
    .setVendor(~"}@{newline}", 1,         "");
}

LESS 1.4.0+ 少1.4.0+

.keyframes(@selector, @name, @from, @to) {
    @newline: `"\n"`; // Newline
    .setVendor(@pre, @post, @vendor) {
        @frames: ~"@{pre}@@{vendor}keyframes @{name} {@{newline}from";
        @{frames} {
            .from(@from); 
        }    
        to  { 
            .to(@to);
        }
       .Local(){}
       .Local() when (@post=1) {
           @animationSector: ~"}@{newline}@{selector}";
           @{animationSector} {
              -moz-animation: @name;
              -webkit-animation: @name;
              -o-animation: @name;
              -ms-animation: @name;
              animation: @name;
           } 
       }    
       .Local;
    } 
    .setVendor(""            , 0,    "-moz-");
    .setVendor(~"}@{newline}", 0, "-webkit-");
    .setVendor(~"}@{newline}", 0,      "-o-");
    .setVendor(~"}@{newline}", 0,     "-ms-");
    .setVendor(~"}@{newline}", 1,         "");
}

Now Call Your Mixin 现在打电话给你的Mixin

You can give it your own name, and just pass the straight pattern (all are no dot [.] and no quotes) for the pattern matches on the module mixins, but don't forget that you also need a selector string (which is quoted) to get the mixin to work right: 您可以给它自己的名字,并且只为模块mixins上的模式匹配传递直线模式(所有都没有点[。]和没有引号),但不要忘记您还需要一个选择器字符串(这是引用)让mixin正常工作:

.keyframes('.changeColor', some-name, my-from, my-to);
.keyframes('.changeFontSize', another-name, another-from, another-to);

Which Gives You the Desired Output 这给了你想要的输出

@-moz-keyframes some-name {
from {
  color: red;
}
to {
  color: blue;
}
}
@-webkit-keyframes some-name {
from {
  color: red;
}
to {
  color: blue;
}
}
@-o-keyframes some-name {
from {
  color: red;
}
to {
  color: blue;
}
}
@-ms-keyframes some-name {
from {
  color: red;
}
to {
  color: blue;
}
}
@keyframes some-name {
from {
  color: red;
}
to {
  color: blue;
}
}
.changeColor {
  -moz-animation: some-name;
  -webkit-animation: some-name;
  -o-animation: some-name;
  -ms-animation: some-name;
  animation: some-name;
}
@-moz-keyframes another-name {
from {
  font-size: 1em;
}
to {
  font-size: 2em;
}
}
@-webkit-keyframes another-name {
from {
  font-size: 1em;
}
to {
  font-size: 2em;
}
}
@-o-keyframes another-name {
from {
  font-size: 1em;
}
to {
  font-size: 2em;
}
}
@-ms-keyframes another-name {
from {
  font-size: 1em;
}
to {
  font-size: 2em;
}
}
@keyframes another-name {
from {
  font-size: 1em;
}
to {
  font-size: 2em;
}
}
.changeFontSize {
  -moz-animation: another-name
  -webkit-animation: another-name;
  -o-animation: another-name;
  -ms-animation: another-name;
  animation: another-name;
}

Simplification 简单化

I just simplified a little ScottS' way, separateing @keframes from -animation : 我只是简化了一点ScottS的方式,将@keframes-animation分开:

.keyframes(@name, @from, @to) {
    @newline: `"\n"`;
    .Local(@x){};
    .Local(@x) when (@x="") {(~"}@{newline}/*"){a:a}/**/};

    .setVendor(@pre, @vendor) {
        (~"@{pre}@@{vendor}keyframes @{name} {@{newline}from") {
            .from(@from);
        }
        to {
            .to(@to);
        }
        .Local(@vendor);
    }
    .setVendor(""            , "-webkit-");
    .setVendor(~"}@{newline}",    "-moz-");
    .setVendor(~"}@{newline}",      "-o-");
    .setVendor(~"}@{newline}",         "");
}

.animation(...) {
  -webkit-animation: @arguments;
     -moz-animation: @arguments;
       -o-animation: @arguments;
          animation: @arguments;
}

use: 使用:

.from(a1-from){ width: 10px; }
.to(a1-to) { width: 20px; }
.keyframes(a1-animation, a1-from, a1-to);


.selector {
    // some other css
    .animation(a1-animation 1s infinite linear);
}

output: 输出:

@-webkit-keyframes a1-animation {
from {
  width: 10px;
}
to {
  width: 20px;
}
}
@-moz-keyframes a1-animation {
from {
  width: 10px;
}
to {
  width: 20px;
}
}
@-o-keyframes a1-animation {
from {
  width: 10px;
}
to {
  width: 20px;
}
}
@keyframes a1-animation {
from {
  width: 10px;
}
to {
  width: 20px;
}
}
/* {
  a: a;
}
/**/


.selector {
  // some other css
  -webkit-animation: a1-animation 1s infinite linear;
  -moz-animation: a1-animation 1s infinite linear;
  -o-animation: a1-animation 1s infinite linear;
  animation: a1-animation 1s infinite linear;
}

little problem: 小问题:

So animation is now separated from @keyframes, but we got to pay the price . 因此动画现在与@keyframes分开,但我们必须付出代价 There is a nasty: 有一个令人讨厌的:

/* {
  a: a;
}
/**/

but it shouldn't be a problem -> propably all of us push CSS files through any kinds of minifiers which cut comments out. 但它不应该是一个问题 - >可能我们所有人都推动CSS文件通过任何类型的缩小器,削减评论。

You can also use my solution to generate CSS keyframes: https://github.com/thybzi/keyframes 您还可以使用我的解决方案生成CSS关键帧: https//github.com/thybzi/keyframes

Features: 特征:

  • Cross-browser keyframes generation (Firefox 5+, Chrome 3+, Safari 4+, Opera 12+, IE 10+) 跨浏览器关键帧生成(Firefox 5 +,Chrome 3 +,Safari 4 +,Opera 12 +,IE 10+)
  • Up to 16 timepoints in each keyframes rule (and the number can be easily augmented, if needed) 每个keyframes规则中最多16个时间点(如果需要,可以轻松扩充该数量)
  • Mixins, variables and functions can be used for styling timepoints 混合,变量和函数可用于样式时间点
  • Keyframes are created separately from animation rules, so: 关键帧与animation规则分开创建,因此:
    • multiple animation rules can use the same keyframe with different values for timing, repeating, etc, 多个animation规则可以使用具有不同值的相同关键帧进行计时,重复等,
    • multiple animations can be used within same animation rule 可以在同一animation规则中使用多个动画
    • animations can be applied (not created!) inside any parent selector 动画可以在任何父选择器中应用(不创建!)
  • Lightweight and (almost) neat LESS code 轻量级(几乎)整洁的LESS代码

Basic usage: 基本用法:

// Preparing styles for animation points
.keyframes-item(fadeIn, 0%) {
    opacity: 0;
}
.keyframes-item(fadeIn, 100%) {
    opacity: 1;
}
// Generating keyframes
.keyframes(fadeIn);

// Applying animation to fade-in block in 1.5 seconds
.myBlock {
    .animation(fadeIn 1.5s);
}

Its not really how you would use mixins. 它不是你如何使用mixins。

You should do something along the lines of: 你应该做的事情是这样的:

.mixin-one { ... }
.mixin-two { ... }
.target-style {
    .mixin-one;
    .mixin-two;
    font-family: 'Comic Sans MS';
    color: magenta;
}

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

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