Ответ 1
Обновление: МЕНЬШЕ >= 1.6
Начиная с версии 1.6 (см. changelog) интерполяция имени свойства реализована в LESS. Так что вам больше не нужна магия. (Для более старых версий см. Мой первоначальный ответ.)
Ваш mixin будет работать в основном так:
LESS:
.vendor(@property; @value){
[email protected]{property}: @value;
[email protected]{property}: @value;
[email protected]{property}: @value;
[email protected]{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}; [email protected]{property}: @{value}; [email protected]{property}: @{value}; [email protected]{property}: @{value}; [email protected]{property}: @{value}; @{property}: @{value}";
}
Мы можем попробовать это на примере - может быть, что-то, что может стоить... давайте попробуем трансформировать короткое:
LESS:
.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, но он чувствует, что kinnda ошибочно =)
Обходной путь №2: вставить динамически генерируемые свойства в имя следующего класса (до версии 1.3.3)
Итак, я сыграл с этой идеей немного больше... и подумал о том, как это не создает ненужных свойств. Он вводит динамически созданные свойства в имя следующего класса. Позвольте мне показать вам, как я заработал:
1). Определим общий метод mixin (аргумент @rest
будет использоваться для выравнивания нескольких блоков поставщика позже)
.vendors(@property, @value, @rest:"") {
@inject:~"@{rest} [email protected]{property}: @{value}; [email protected]{property}: @{value}; [email protected]{property}: @{value}; [email protected]{property}: @{value}; @{property}: @{value};";
}
2). Создайте виртуальный класс/набор правил, который мы хотим, чтобы поставщики были включены, но мы делаем его как mixin, который в конце создает следующий класс aswel - поэтому мы действительно делаем mixin, который будет рекурсивно строить два или более классов. Например (используя тот же пример, что и выше), мы можем написать что-то вроде этого (обратите внимание на использование @inject
во втором вызове .vendor()
, чтобы связать два блока поставщика вместе):
.test(@nextclass){
.vendors(transform, "matrix(2,0,0,2,20,20)");
.vendors(transform-origin,"10px 10px", @inject);
(~"{@{inject}} [email protected]{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*/
}
Выход будет всего лишь в одной строке.
Изменить: Для более удобного форматирования вы можете включить javascript-интерполяцию "\n"
и "\t"
, см. предложение Скотта в комментариях ниже.
Таким образом, вы можете теперь объединить несколько классов, используя метод mixer поставщика, без каких-либо ненужных свойств.
Обходной путь №3: вставить динамически генерируемые свойства в имя следующего класса (v1.4.0) с помощью рекурсии
Я добавляю эту причину. Скотт указал в одном из комментариев, что изменения, которые идут с версией 1.4, не позволят обходному пути №2. Но если мы немного находчивы, мы сможем справиться с этой проблемой. Давайте посмотрим, какие проблемы выше обходного пути и исправить их.
1) Первой проблемой будет то, что интерполяция селектора (~"[email protected]{index}") { ...
устарела ", поэтому нам нужно выполнить интерполяцию строк на отдельном шаге. Реализации этого было бы достаточно, чтобы добавить один микс .vendors
сверху.
МЕНЬШЕ: (используя предложение Scott newline):
@nl: `"\n\t"`;
.vendors(@property, @value) {
@inject:~"@{nl}[email protected]{property}: @{value};@{nl}[email protected]{property}: @{value};@{nl}[email protected]{property}: @{value};@{nl}[email protected]{property}: @{value};@{nl}@{property}: @{value};";
}
.test(@nextclass){
.vendors(transform, "matrix(2,0,0,2,20,20)");
@inj: ~"{@{inject}`'\n'`} `'\n'`[email protected]{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) Вторая проблемабыло бы, что "переменные в mixins больше не" течет "в свою область вызова", но я заметил в версии 1.4.0, что если переменная вводится только в mixin, она все равно может быть вызвана из включенного набора правил, поэтому с небольшая рекурсия, вы можете построить блоки .vendors
, а на последнем шаге назначьте их новой переменной, которую вы затем используете для инъекции. Я также получил возбуждение и использовал новую функцию extract()
, введенную в этой версии меньше. С переменной @i
мы назначаем уровень рекурсии (количество блоков поставщиков, которые нужно вставить).
LESS:
@nl: `"\n\t"`;
.multi(@props,@vals,1,@inj) {
@property: extract(@props, 1);
@value: extract(@vals, 1);
@inject:~"@{inj}@{nl}[email protected]{property}: @{value};@{nl}[email protected]{property}: @{value};@{nl}[email protected]{property}: @{value};@{nl}[email protected]{property}: @{value};@{nl}@{property}: @{value};";
}
.multi(@props,@vals,@i,@inj:"") when (@i > 0) {
@property: extract(@props, @i);
@value: extract(@vals, @i);
@injnext:~"@{inj}@{nl}[email protected]{property}: @{value};@{nl}[email protected]{property}: @{value};@{nl}[email protected]{property}: @{value};@{nl}[email protected]{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, но давайте посмотрим, что принесет будущее.