Меньше CSS: миксины с переменным количеством аргументов

LESS позволяет использовать параметрические примеси, такие как:

.transition(@property, @duration){
    transition:         @property @duration;
    -moz-transition:    @property @duration; /* Firefox 4 */
    -webkit-transition: @property @duration; /* Safari and Chrome */
    -o-transition:      @property @duration; /* Opera */
}

Однако это не всегда работает с такими свойствами, как переходы. Если вы пытаетесь иметь несколько переходов и пытаетесь вызвать миксин несколько раз, последний миксин переопределяет все ранее определенные переходы. Это потому, что правильный синтаксис CSS3 для определения нескольких переходов:

... {
    transition: @property1 @duration1, @property2 @duration2, ...;
}

Единственный способ, который я могу придумать, чтобы определить несколько переходов как миксины, — это перегрузить миксин:

.transition(@property, @duration){...}
.transition(@property, @duration, @prop2, @dur2){...}
.transition(@property, @duration, @prop2, @dur2, @prop3, @dur3){...}

Есть ли более надежный и лаконичный способ определения примеси перехода, чтобы принимать переменное количество аргументов и создавать соответствующий переходный CSS?

Контекст. Иногда мне нужно перейти к нескольким ресурсам; например, :hover может вызывать переходы по цвету фона, тени окна, цвету текста и т. д...


person Tuanderful    schedule 10.07.2012    source источник


Ответы (6)


См. мой ответ здесь: Несколько свойств обрабатываются как отдельные аргументы в миксинах

Резюме: используйте этот миксин для переменного количества аргументов:

.transition (@value1,@value2:X,...)
{
    @value: ~`"@{arguments}".replace(/[\[\]]|\,\sX/g, '')`;

    -webkit-transition: @value;
    -moz-transition: @value;
    -ms-transition: @value;
    -o-transition: @value;
    transition: @value;
}
person David Rettenbacher    schedule 21.11.2012
comment
Это действительно здорово. Однако следует отметить, что этот миксин не будет работать при переходе преобразования (конкретно). Это связано с обязательными префиксами поставщиков. - person EoghanTadhg; 12.05.2016
comment
Эта схема хороша, но если используется LessPHP - можетt evalute regexp js. So, there is simple solution if we donне нужно разделять параметры каждого перехода (просто ise prop+:): .transition(...){ -webkit-transition+: @arguments; -moz-transition+: @arguments; -o-переход+: @аргументы; переход+: @arguments; } - person user989840; 23.04.2021

ОБНОВЛЕНИЕ для МЕНЬШЕ 1.3.3+

Вывод такой же, но обратите внимание на разницу в том, как свойства могут быть переданы в более новых версиях LESS с использованием точки с запятой вместо экранированной строки:

@prop1: color;
@prop2: opacity;
@dur1: 3s;
@dur2: 4s;

.transition(@transString: 0) when not (@transString = 0) {
    transition:         @transString;
    -moz-transition:    @transString; /* Firefox 4 */
    -webkit-transition: @transString; /* Safari and Chrome */
    -o-transition:      @transString; /* Opera */
}

.class1 {.transition();}
.class2 {.transition(width 2s, height 2s;);}
                                        ^
                                   semicolon here
.class3 {.transition(@prop1 @dur1, @prop2 @dur2;);}
                                               ^
                                         semicolon here

Точка с запятой заставляет запятые оцениваться как разделители списков, а не как разделители параметров.

Одно решение для LESS до версии 1.3.3

Мы создаем правильные аргументы свойства в виде строки для transition, затем используем оператор экранированного значения (~) для преобразования этого в необходимый собственный синтаксис. Используя интерполяцию строк (@{variableName}), мы можем даже встраивать переменные в процесс, но фактический ввод должен быть в виде экранированной строки.

МЕНЬШЕ кода

@prop1: color;
@prop2: opacity;
@dur1: 3s;
@dur2: 4s;

.transition(@transString: 0) when not (@transString = 0) {
    transition:         @transString;
    -moz-transition:    @transString; /* Firefox 4 */
    -webkit-transition: @transString; /* Safari and Chrome */
    -o-transition:      @transString; /* Opera */
}

.class1 {.transition();}
.class2 {.transition(~" width 2s, height 2s");}
.class3 {.transition(~" @{prop1} @{dur1}, @{prop2} @{dur2}");}

Вывод CSS

Примечание: .class1 не выводится, потому что защитное выражение гарантирует, что что-то введено (хотя и не защищает от неправильного ввода).

.class2 {
  transition: width 2s, height 2s;
  -moz-transition: width 2s, height 2s;
  -webkit-transition: width 2s, height 2s;
  -o-transition: width 2s, height 2s;
}
.class3 {
  transition: color 3s, opacity 4s;
  -moz-transition: color 3s, opacity 4s;
  -webkit-transition: color 3s, opacity 4s;
  -o-transition: color 3s, opacity 4s;
}
person ScottS    schedule 19.07.2012

В LESS вы можете разделять аргументы запятыми ИЛИ точками с запятой. Для одиночных значений, содержащих запятые, вы можете завершить это единственное значение точкой с запятой, чтобы отправить список как одно значение, например:

.class {
  .background-size(100%, auto;);
}

Для нескольких значений просто используйте этот синтаксис:

/* Example mixin */
.set-font-properties(@font-family, @size) {  
  font-family: @font-family;
  font-size: @size;
}
/* Usage with comma-separated values */
.class {
  .set-font-properties(Arial, sans-serif; 16px);
}

/* Output */
.class {
  font-family: Arial, sans-serif;
  font-size: 16px;
}

Очень просто!

person Matthew Dean    schedule 13.05.2013

Примечание. Этот ответ добавлен не с целью сказать, что существующие ответы неверны или устарели. Все ответы действительны и все равно будут работать. Этот просто предоставляет другой метод, который, на мой взгляд, немного сложнее, но также и более гибкий с точки зрения того, как каждый аргумент может быть упомянут как пары ключ-значение.

Преимущества использования этого метода: этот метод станет более полезным, когда необходимо выполнить какую-либо дополнительную операцию над значениями (например, добавить unit как deg, px или выполнить какие-либо дополнительные математические операции и т. д.) или также динамическое добавление префиксов поставщиков для @property. Например, бывают случаи, когда вы можете захотеть передать только transform в качестве входного свойства примеси, но хотите добавить -webkit-transform для -webkit-transition и -moz-transform для -moz-transition и т. д.

В этом методе мы используем функцию ..., которая позволяет нам передавать переменное количество аргументов миксину, циклически перебирать каждый переданный аргумент, extract имя свойства вместе с дополнительными параметрами (такими как продолжительность, степень вращения д.), а затем используйте функция объединения, предоставляемая Меньше, чтобы объединить значения, указанные для свойства.

  • +: объединяет значения свойств с запятой и было введено в Less v1.5.0.
  • +_: объединяет значения свойств с пробелом и был представлен в Less v1.7.0. .
.transition(@args...){
    .loop-args(@argCount) when (@argCount > 0) {
        .loop-args(@argCount - 1);
        @arg: extract(@args, @argCount);
        @property: extract(@arg,1);
        @duration: extract(@arg,2);
        -webkit-transition+: @property @duration;
        -moz-transition+: @property @duration;
        -o-transition+: @property @duration;
        transition+: @property @duration;
    }
    .loop-args(length(@args));    
}

div{
    .transition(background, 1s; border-color, 2s; color, 2s);
}

.transform(@args...){
    .loop-args(@argCount) when (@argCount > 0) {
        .loop-args(@argCount - 1);
        @arg: extract(@args, @argCount);
        @property: extract(@arg,1);
        @param: extract(@arg,2);
        -webkit-transform+_: ~"@{property}(@{param})";
        -moz-transform+_: ~"@{property}(@{param})";
        -o-transform+_: ~"@{property}(@{param})";
        transform+_: ~"@{property}(@{param})";
    }
    .loop-args(length(@args));    
}

div#div2{
    .transform(rotate, 20deg; scale, 1.5; translateX, 10px);
}

Приведенный выше код при компиляции выдаст следующий вывод:

div {
    -webkit-transition: background 1s, border-color 2s, color 2s;
    -moz-transition: background 1s, border-color 2s, color 2s;
    -o-transition: background 1s, border-color 2s, color 2s;
    transition: background 1s, border-color 2s, color 2s;
}
div#div2 {
    -webkit-transform: rotate(20deg) scale(1.5) translateX(10px);
    -moz-transform: rotate(20deg) scale(1.5) translateX(10px);
    -o-transform: rotate(20deg) scale(1.5) translateX(10px);
    transform: rotate(20deg) scale(1.5) translateX(10px);
}

Похожий ответ:

  • Вот ответ от seven-phases-max, который объясняет, как этот метод можно использовать для автоматического добавления префиксов поставщиков, как я упоминал в параграфе о преимуществах.
person Harry    schedule 04.10.2014

Это должно сработать, я думаю:

.transition(...) {
    transition:         @arguments;
    -moz-transition:    @arguments; /* Firefox 4 */
    -webkit-transition: @arguments; /* Safari and Chrome */
    -o-transition:      @arguments; /* Opera */
}

... - допустимый синтаксис меньшего размера, а не то, что нужно заменить.

person esp    schedule 07.01.2013
comment
У меня не работает, по крайней мере, в моем случае * box-shadow. В сгенерированном CSS запятые отсутствуют. Ответ @Warappa работает для меня. - person Ortwin Gentz; 22.05.2013
comment
Конечно. Это выглядит очень аккуратно, но конечный результат недействителен. Заполнитель @arguments расширяется до списка параметров, соединенных пробелами, а не разделенных запятыми. - person Timo Tijhof; 03.09.2015

Актуальна для LESS 1.4, документация (http://lesscss.org/features/#mixins-parametric-feature-mixins-with-multiple-parameters) предлагает правильный способ справиться с этим:

Использование запятой в качестве разделителя примесей делает невозможным создание списков, разделенных запятыми, в качестве аргумента. С другой стороны, если компилятор видит хотя бы одну точку с запятой внутри вызова или объявления миксина, он предполагает, что аргументы разделены точкой с запятой и все запятые принадлежат спискам css:

В частности, примесь:

.transition(@prop-or-props) {
    -webkit-transition: @prop-or-props;
       -moz-transition: @prop-or-props;
         -o-transition: @prop-or-props;
            transition: @prop-or-props;
}

использование:

.transition(opacity .2s, transform .3s, -webkit-transform .3s;);

Обратите внимание, что несколько свойств разделяются запятыми, а завершающая точка с запятой приводит к тому, что список, разделенный запятыми, обрабатывается как один параметр в миксине.

Было бы лучше определить миксин с параметром rest... и иметь возможность извлекать каждый элемент аргументов произвольной длины для отдельной обработки, но вариант использования, о котором я думаю, — это добавление префиксов поставщиков для преобразования переходов (чтобы я мог вызовите его просто с помощью .transition(opacity .2s, transform .3s) и автоматически добавьте бит -webkit-transform), и, возможно, в любом случае это лучше обрабатывается другой утилитой (например, gulp-autoprefixer).

person Jon z    schedule 10.06.2014
comment
› Было бы лучше определить миксин с параметром rest... и иметь возможность извлекать каждый элемент. См. stackoverflow.com/q /21061361/2712740 (но, как я уже сказал, в эти дни это больше похоже на пустую трату времени, инструменты автоматического префикса теперь наши лучшие друзья). - person seven-phases-max; 10.06.2014
comment
@seven-phases-max: извините, приятель, я видел этот ответ и последний абзац, но не заметил вашего комментария и связанного с ним ответа. Надеюсь, вы не возражаете против моего ответа. - person Harry; 05.10.2014