Динамические имена классов с параметрами в миксине Less

Я пытаюсь создать миксин Less для генерации медиа-запросов. Цель состоит в том, чтобы хранить мои контрольные точки в variables.less файл, и цикл по ним, чтобы создать @media блоки.

Затем миксин будет использоваться как:

.mq-medium({
  // rules
});

и генерировать CSS как:

@media only screen and (min-width: 640px) {
  // rules
}

Вот мой текущий миксин:

variables.less

/* media queries */
@breakpoints: small 0, medium 640px, large 1024px, xlarge 1281px, xxlarge 1440px;

mediaqueries.less

.createMQClasses(@iterator:1) when(@iterator <= length(@breakpoints)-1) {
  @breakpoint: extract(extract(@breakpoints, @iterator),1);
  @breakpoint-next: extract(@breakpoints, (@iterator + 1));
  @breakpoint-next-px: extract(@breakpoint-next, 2);
    .mq-@{breakpoint} {
      @media only screen and (min-width: extract(extract(@breakpoints, @iterator),2)) {
      }
    }

    .createMQClasses((@iterator + 1));
}

.createMQClasses();

Пока мой код перебирает и генерирует пустой @media блоки. Тем не менее, мне нужно передать любой @rules до выхода. Я делал это ранее со статическими именами классов, например так:

.mq-medium(@rules) {
  @media only screen and (min-width: extract(extract(@breakpoints, 2),2)) {
    @rules();
  }
}

И это прекрасно работает.

Но с динамическим именем это вызывает ошибки. Я попытался добавить дополнительный параметр в .mq-@{breakpoint} заявления, как:

.mq-@{breakpoint}(@rules) {
  @media only screen and (min-width: extract(extract(@breakpoints, @iterator),2)) {
    @rules();
  }
}

Это приводит к различным ошибкам. Как можно передать включенные правила, чтобы они были включены в вывод миксина?

1 ответ

Нет, вы не можете использовать переменные в именах параметрического миксина. Таким образом, вы не можете "генерировать" миксины по списку идентификаторов. Так что вам нужно придумать какой-то другой подход...

Ну, есть несколько возможностей - например, обратите внимание, что @{breakpoint} часть имени миксина - это просто еще один параметр миксина. Тогда это может быть закодировано как-то вроде (упрощенно):

// usage:

@devices: small 0, medium 640px, large 1024px;

.mq(medium, {
    foo {
        bar: baz;
    }
});  

// impl.:

.mq(@id, @style) {
    .-(length(@devices));
    .-(@i) when (@i > 0) {
        .-(@i - 1);
        .--(extract(@devices, @i));
    }
    .--(@device) when (@id = extract(@device, 1)) {
        @media (min-width: extract(@device, 2)) {@style();}
    }
}

---

В качестве альтернативы (просто чтобы проиллюстрировать эти "несколько возможностей"), на самом деле можно сделать идентификатор устройства префиксной частью имени, используя определенные приемы и приемы. Например:

// impl.:
// (here mixin definitions should always go before their usage)

.make-media-mixins();
.make-media-mixins(@i: length(@devices)) when (@i > 0) {
    .make-media-mixins(@i - 1);
    @device: extract(@devices, @i);
    @id: extract(@device, 1);
    .@{id} {.mq(@rules) {
        @media (min-width: extract(@device, 2)) {@rules();}
    }}
}

// usage:

@devices: small 0, medium 640px, large 1024px;

.medium.mq({
    foo {
        bar: baz;
    }
});  

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

Другие вопросы по тегам