31

I noticed that inuit.css, which was written in SASS, has a .vendor mix-in:

@mixin vendor($property, $value...){
    -webkit-#{$property}:$value;
       -moz-#{$property}:$value;
        -ms-#{$property}:$value;
         -o-#{$property}:$value;
            #{$property}:$value;
}

Is there a way to replicate this in LESS with some of the odd features like e() and @{ } ?

4

2 に答える 2

58

更新: LESS >= 1.6

バージョン 1.6 ( changelogを参照) では、プロパティ名の補間が LESS に実装されています。だからもう魔法はいらない。(古いバージョンについては、元の回答を参照してください。)

あなたのミックスインは基本的にそのまま動作します:

以下:

.vendor(@property; @value){
    -webkit-@{property}: @value;
       -moz-@{property}: @value;
        -ms-@{property}: @value;
         -o-@{property}: @value;
            @{property}: @value;
}

/*example*/
.test {
    .vendor(transform, translateX(20px));
}

CSS:

.test {
  -webkit-transform: translateX(20px);
  -moz-transform: translateX(20px);
  -ms-transform: translateX(20px);
  -o-transform: translateX(20px);
  transform: translateX(20px);
}

元の答え: LESS < 1.6

私に関する限り、動的に挿入されたプロパティのサポートはあまり追加されていません。これについては、SO で何度も議論されています。

したがって、通常はパラメトリック ミックスインとパターン マッチングを使用して行われます...そのため、もう少しハード コーディングが必要になります...しかし、プロパティやさまざまなベンダーでは、パラメータの形式が少し異なる場合があるため、もう少し制御する必要がありますこのように追加されます。

回避策 #1: 動的に生成されたプロパティをプロパティ値に挿入する

回避策の最初のオプションは少し見にくいですが、試してみたところhttp://less2css.orgで動作しました。それで、私が試みたのは、動的に作成されたプロパティを、ハードコーディングした別のプロパティの値に挿入することでした(これは、-injここでランダムな「ベンダー」名を付けて値を割り当てたectだけですが、代わりに何か便利なものを使用したい場合があります既にすべてのベンダー mixin インクルードの要素を追加しています)

.vendors(@property, @value, @pre: ect) {
    -inj:~"@{pre}; -webkit-@{property}: @{value}; -moz-@{property}: @{value}; -ms-@{property}: @{value}; -o-@{property}: @{value}; @{property}: @{value}";
}

例でそれを試すことができます - 多分それを価値のあるものにするために... 短い変換を試してみましょう:

以下:

.test-class{
    .vendors(transform, matrix(1,0,0,1,20,20));
    .vendors(transform-origin,"10px 10px");
}

CSS 出力:

.test-class {
    -inj: ect; -webkit-transform: matrix(1, 0, 0, 1, 20, 20); -moz-transform: matrix(1, 0, 0, 1, 20, 20); -ms-transform: matrix(1, 0, 0, 1, 20, 20); -o-transform: matrix(1, 0, 0, 1, 20, 20); transform: matrix(1, 0, 0, 1, 20, 20);
    -inj: ect; -webkit-transform-origin: 10px 10px; -moz-transform-origin: 10px 10px; -ms-transform-origin: 10px 10px; -o-transform-origin: 10px 10px; transform-origin: 10px 10px;
}

これは動作するcssを生成するようですが、ちょっと間違っているように感じます=)


回避策 #2: 動的に生成されたプロパティを次のクラスの名前に挿入します (v1.3.3 まで)。

そこで、私はこのアイデアをもう少しいじって、不必要なプロパティを生成しない方法を考えました。動的に作成されたプロパティを次のクラスの名前に挿入します。私がどのようにそれを機能させたかをお見せしましょう:

1)一般的なベンダー mixin を定義しましょう (@rest引数は後で複数のベンダー ブロックを並べるために使用されます)

.vendors(@property, @value, @rest:"") {
    @inject:~"@{rest} -webkit-@{property}: @{value}; -moz-@{property}: @{value}; -ms-@{property}: @{value}; -o-@{property}: @{value}; @{property}: @{value};";
}

2)ベンダーを含めたい仮想クラス/ルールセットを構築しますが、最後に次のクラスを構築する mixin として作成します。つまり、実際には 2 つ以上のクラスを再帰的に構築する mixin を作成します。たとえば、(上記と同じ例を使用して) 次のように記述できます (2 番目の呼び出しで を使用@injectして.vendor()2 つのベンダー ブロックをバインドしていることに注意してください)。

.test(@nextclass){
    .vendors(transform, "matrix(2,0,0,2,20,20)");
    .vendors(transform-origin,"10px 10px", @inject);
    (~"{@{inject}} .@{nextclass}"){/*next class properties*/};
}

3)次に、この mixin を別のクラスにラップして、css に表示します。

.this-class{
    .test(next-class);
}

結果のCSSには以下が含まれます。

.this-class {
  -webkit-transform: matrix(2, 0, 0, 2, 20, 20);
  -moz-transform: matrix(2, 0, 0, 2, 20, 20);
  -ms-transform: matrix(2, 0, 0, 2, 20, 20);
  -o-transform: matrix(2, 0, 0, 2, 20, 20);
  transform: matrix(2, 0, 0, 2, 20, 20);
  -webkit-transform-origin: 10px 10px;
  -moz-transform-origin: 10px 10px;
  -ms-transform-origin: 10px 10px;
  -o-transform-origin: 10px 10px;
  transform-origin: 10px 10px;
}
.next-class {
  /*next class properties*/
}

出力はすべて1行になります。

編集:より適切な書式設定を行うには、"\n"およびの JavaScript 補間を含めることができ"\t"ます。以下のコメントで Scott の提案を参照してください。

このようにして、不要なプロパティなしで、ベンダー mixin をすべて使用して複数のクラスをチェーン化できるようになりました。


回避策 #3: 再帰を使用して、動的に生成されたプロパティを次のクラス (v1.4.0) の名前に挿入します。

Scott がコメントの 1 つで、バージョン 1.4 で予定されている変更では回避策 #2 を使用できないと指摘した原因を追加します。しかし、私たちが少し機知に富んでいれば、この問題を克服できます。上記の回避策の問題が何であるかを見て、それらを修正しましょう。

1)最初の問題は、「(~".@{index}") { ...セレクター補間が非推奨」であるため、別のステップで文字列補間を行う必要があることです。これを実装するだけで、上から単一の.vendorsmixin を注入するのに十分です。

LESS: (Scott の改行提案を使用):

@nl: `"\n\t"`;        
.vendors(@property, @value) {
    @inject:~"@{nl}-webkit-@{property}: @{value};@{nl}-moz-@{property}: @{value};@{nl}-ms-@{property}: @{value};@{nl}-o-@{property}: @{value};@{nl}@{property}: @{value};";
}
.test(@nextclass){
    .vendors(transform, "matrix(2,0,0,2,20,20)");
    @inj: ~"{@{inject}`'\n'`} `'\n'`.@{nextclass}";
    @{inj} {/*next class properties*/}
}
.this-class{
    .test(next-class);
}

CSS 出力:

.this-class {
    -webkit-transform: matrix(2,0,0,2,20,20);
    -moz-transform: matrix(2,0,0,2,20,20);
    -ms-transform: matrix(2,0,0,2,20,20);
    -o-transform: matrix(2,0,0,2,20,20);
    transform: matrix(2,0,0,2,20,20);
} 
.next-class {
    /*next class properties*/
}

2)2番目の問題は、「ミックスインの変数が呼び出しスコープに「リーク」しなくなった」ことですが、1.4.0ベータで、変数がミックスインでのみ導入された場合でも、変数から呼び出すことができることに気付きましたルールセットが含まれているため、少し再帰して.vendorsブロックを構築し、最後のステップでブロックを新しい変数に割り当てて、それを注入に使用できます。私も興奮してextract()、このバージョンの less で導入された新しい機能を使用しました。変数@iを使用して、再帰のレベル (注入されるベンダー ブロックの数) を割り当てます。

以下:

@nl: `"\n\t"`; 
.multi(@props,@vals,1,@inj) {
    @property: extract(@props, 1);
    @value: extract(@vals, 1);
    @inject:~"@{inj}@{nl}-webkit-@{property}: @{value};@{nl}-moz-@{property}: @{value};@{nl}-ms-@{property}: @{value};@{nl}-o-@{property}: @{value};@{nl}@{property}: @{value};";
}

.multi(@props,@vals,@i,@inj:"") when (@i > 0) {
    @property: extract(@props, @i);
    @value: extract(@vals, @i);
    @injnext:~"@{inj}@{nl}-webkit-@{property}: @{value};@{nl}-moz-@{property}: @{value};@{nl}-ms-@{property}: @{value};@{nl}-o-@{property}: @{value};@{nl}@{property}: @{value};";
    .multi(@props,@vals,(@i - 1),@injnext);
}

@properties: "transform-origin" "transform";
@values: "10px 10px" "matrix(2,0,0,2,20,20)";

// string of other properties you want to include in the same class
@p: ~"@{nl}width:20px; @{nl}height:12px; @{nl}background-color:#000;";

.this-class {
    .multi(@properties,@values,2,@p);
    @inj: ~"{@{inject}`'\n'`} `'\n'`.next-class ";
    @{inj} {/**/}
}

CSS 出力:

.this-class {
  width:20px;
  height:12px;
  background-color:#000;
  -webkit-transform: matrix(2, 0, 0, 2, 20, 20);
  -moz-transform: matrix(2, 0, 0, 2, 20, 20);
  -ms-transform: matrix(2, 0, 0, 2, 20, 20);
  -o-transform: matrix(2, 0, 0, 2, 20, 20);
  transform: matrix(2, 0, 0, 2, 20, 20);
  -webkit-transform-origin: 10px 10px;
  -moz-transform-origin: 10px 10px;
  -ms-transform-origin: 10px 10px;
  -o-transform-origin: 10px 10px;
  transform-origin: 10px 10px;
}
.next-class {
  /*next class properties*/
}

これは 1.4.0 ベータ版でかなりうまく機能しましたが、今後どうなるか見てみましょう。

于 2013-03-15T22:20:06.143 に答える
3

「マイナス」をプロパティ名として使用できることを追加したかっただけで、パーサーはそれを無視しますが、残りの文字列を追加します。そうすれば、空inject:;または inj プロパティを取得できなくなります。それはまだハッキーですが、ねえ... :)

.prefix(@property, @value) {
    -:~";-webkit-@{property}: @{value}; -moz-@{property}: @{value}; -ms-@{property}: @{value}; -o-@{property}: @{value}; @{property}: @{value}";
}

例:

.prefix(transition, "all .2s, color 0s");

出力します:

-webkit-transition: all .2s, color 0;
-moz-transition: all .2s, color 0;
-ms-transition: all .2s, color 0;
-o-transition: all .2s, color 0;
transition: all .2s, color 0;
于 2013-06-10T03:40:08.487 に答える