Less
Обзор
В качестве расширения CSS, Less не только совместим со старыми версиями CSS, но и добавленные им функции используют существующую синтаксическую конструкцию CSS. Это упрощает изучение Less, и в случае сомнений, вы можете вернуться к обычному CSS.
Переменные
Эти переменные довольно понятны:
@nice-blue: #5B83AD;
@light-blue: @nice-blue + #111;
#header {
color: @light-blue;
}
Выходные данные:
#header {
color: #6c94be;
}
Обратите внимание, что переменные фактически являются «константами», поскольку их можно определить только один раз.
Миксины
Миксины — это способ включения («смешивания») набора свойств из одного набора правил в другой набор правил. Предположим, у нас есть следующий класс:
.bordered {
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
И мы хотим использовать эти свойства внутри других наборов правил. Для этого нам нужно просто добавить имя класса, где мы хотим свойства, как показано ниже:
#menu a {
color: #111;
.bordered;
}
.post a {
color: red;
.bordered;
}
Свойства класса .bordered теперь будут отображаться как в #menu a, так и в .post a. (Обратите внимание, что вы также можете использовать #ids в качестве миксинов.)
Дополнительная информация
Вложенные правила
Less предоставляет возможность использовать вложенность вместо или в сочетании с каскадированием. Предположим, у нас есть следующий CSS:
#header {
color: black;
}
#header .navigation {
font-size: 12px;
}
#header .logo {
width: 300px;
}
В Less мы можем написать это так:
#header {
color: black;
.navigation {
font-size: 12px;
}
.logo {
width: 300px;
}
}
Полученный код более лаконичен и имитирует структуру вашего HTML.
Вы также можете объединять псевдо-селекторы со своими миксинами с помощью этого метода. Вот классический хак clearfix, переписанный как миксин (& представляет текущий родительский селектор):
.clearfix {
display: block;
zoom: 1;
&:after {
content: " ";
display: block;
font-size: 0;
height: 0;
clear: both;
visibility: hidden;
}
}
См. также
Вложенные директивы и «пузырение»
Директивы, такие как media или keyframe, могут быть вложены так же, как и селекторы. Директива помещается сверху, а относительный порядок по отношению к другим элементам внутри того же набора правил остается неизменным. Это называется «пузырение».
Условные директивы, например, @Media, @supports и @document, также содержат скопированные селекторы в своих телах:
.screen-color {
@media screen {
color: green;
@media (min-width: 768px) {
color: red;
}
}
@media tv {
color: black;
}
}
выходные данные:
@media screen {
.screen-color {
color: green;
}
}
@media screen and (min-width: 768px) {
.screen-color {
color: red;
}
}
@media tv {
.screen-color {
color: black;
}
}
Остальные не условные директивы, например, font-face или keyframes, также «пузырятся» вверх. Их тела не изменяются:
#a {
color: blue;
@font-face {
src: made-up-url;
}
padding: 2 2 2 2;
}
выходные данные:
#a {
color: blue;
}
@font-face {
src: made-up-url;
}
#a {
padding: 2 2 2 2;
}
Операции
Арифметические операции +, -, *, / могут применяться к любому числу, цвету или переменной. Если это возможно, математические операции учитывают единицы измерения и преобразуют числа перед сложением, вычитанием или сравнением. Результат имеет тип единицы измерения, указанный слева. Если преобразование невозможно или не имеет смысла, единицы измерения игнорируются. Пример невозможного преобразования: px в см или рад в %.
// numbers are converted into the same units @conversion-1: 5cm + 10mm; // result is 6cm @conversion-2: 2 - 3cm - 5mm; // result is -1.5cm // conversion is impossible @incompatible-units: 2 + 5px - 3cm; // result is 4px // example with variables @base: 5%; @filler: @base * 2; // result is 10% @other: @base + @filler; // result is 15%
Умножение и деление не преобразуют числа. В большинстве случаев это не имело бы смысла — длина, умноженная на длину, даёт площадь, а CSS не поддерживает указание площадей. Less будет выполнять операции над числами как есть и присваивать явно указанный тип единицы измерения результату.
@base: 2cm * 3mm; // result is 6cm
Цвета разбиваются на красную, зелёную, синюю и альфа-компоненты. Операция применяется к каждой компоненте цвета по отдельности. Например, если пользователь складывает два цвета, то зелёная компонента результата равна сумме зелёных компонент входных цветов. Если пользователь умножает цвет на число, каждая компонента цвета будет умножена.
Примечание: арифметическая операция над альфа-каналом не определена, поскольку математические операции над цветами не имеют общепринятого смысла. Не полагайтесь на текущее выполнение, так как оно может измениться в более поздних версиях.
Операция над цветами всегда производит допустимый цвет. Если какая-либо компонента цвета результата окажется больше ff или меньше 00, компонент будет округлён до ff или 00. Если альфа-канал окажется больше 1.0 или меньше 0.0, альфа-канал будет округлён до 1.0 или 0.0.
@color: #224488 / 2; //results in #112244 background-color: #112244 + #111; // result is #223355
Экранирование
Экранирование позволяет использовать любую произвольную строку в качестве свойства или значения переменной. Всё внутри ~"anything" или ~'anything' используется как есть без изменений, кроме интерполяции.
.weird-element {
content: ~"^//* some horrible but needed css hack";
}
результат:
.weird-element {
content: ^//* some horrible but needed css hack;
}
Функции
Less предоставляет множество функций, которые преобразуют цвета, манипулируют строками и выполняют математические операции. Полная документация по ним приведена в справочнике по функциям.
Использование их достаточно просто. Следующий пример использует проценты для преобразования 0.5 в 50%, увеличивает насыщенность базового цвета на 5%, а затем устанавливает цвет фона, осветлённый на 25% и повернутый на 8 градусов:
@base: #f04615;
@width: 0.5;
.class {
width: percentage(@width); // returns `50%`
color: saturate(@base, 5%);
background-color: spin(lighten(@base, 25%), 8);
}
Пространства имён и аксессоры
(Не путать с CSS @namespace или селекторами пространства имён).
Иногда вам может потребоваться сгруппировать миксины для организации или просто для некоторой инкапсуляции. Это довольно интуитивно реализовано в Less, например, вы хотите объединить миксины и переменные под #bundle, для дальнейшего повторного использования или распространения:
#bundle {
.button {
display: block;
border: 1px solid black;
background-color: grey;
&:hover {
background-color: white
}
}
.tab { ... }
.citation { ... }
}
Теперь, если мы хотим применить миксин .button к нашему #header a, мы можем сделать следующее:
#header a {
color: orange;
#bundle > .button;
}
Обратите внимание, что переменные, объявленные внутри пространства имён, будут доступны только в этом пространстве имён и не будут доступны снаружи с помощью того же синтаксиса, что и для ссылки на миксин (#Namespace > .mixin-name). Так, например, вы не можете сделать следующее: (#Namespace > @this-will-not-work).
Область видимости
Область видимости в Less очень похожа на области видимости в языках программирования. Переменные и миксины сначала ищутся локально, и если они не найдены, компилятор будет искать в родительской области видимости и так далее.
@var: red;
#page {
@var: white;
#header {
color: @var; // white
}
}
Переменные и миксины не должны быть объявлены до использования, поэтому следующий код Less идентичен предыдущему примеру:
@var: red;
#page {
#header {
color: @var; // white
}
@var: white;
}
См. также
Комментарии
Можно использовать как комментарии в блоках, так и однострочные комментарии:
/* One hell of a block style comment! */ @var: red; // Get in line! @var: white;
Импорт
Импорт работает примерно так же, как ожидается. Вы можете импортировать файл .less, и все переменные в нём будут доступны. Расширение необязательно указывается для файлов .less.
@import "library"; // library.less @import "typo.css";
Переменные
Управление часто используемыми значениями в одном месте.
Обзор
Не редкость видеть одно и то же значение, повторяющееся десятками, а то и сотнями раз в ваших стилевых файлах:
a,
.link {
color: #428bca;
}
.widget {
color: #fff;
background: #428bca;
}
Переменные упрощают поддержку кода, предоставляя способ управления этими значениями из одного места:
// Variables
@link-color: #428bca; // sea blue
@link-color-hover: darken(@link-color, 10%);
// Usage
a,
.link {
color: @link-color;
}
a:hover {
color: @link-color-hover;
}
.widget {
color: #fff;
background: @link-color;
}
Интерполяция переменных
Приведённые выше примеры сосредоточились на использовании переменных для управления значениями в правилах CSS, но их также можно использовать и в других местах, таких как имена селекторов, имена свойств, URL-адреса и @import операторы.
Селекторы
Версия: 1.4.0
// Variables
@my-selector: banner;
// Usage
.@{my-selector} {
font-weight: bold;
line-height: 40px;
margin: 0 auto;
}
Компилируется в:
.banner {
font-weight: bold;
line-height: 40px;
margin: 0 auto;
}
URL-адреса
// Variables
@images: "../img";
// Usage
body {
color: #444;
background: url("@{images}/white-sand.png");
}
Операторы импорта
Версия: 1.4.0
Синтаксис: @import "@{themes}/tidal-wave.less";
Обратите внимание, что до версии 2.0.0 учитывались только переменные, объявленные в корне или текущей области видимости, а также только текущий файл и вызывающие файлы при поиске переменной.
Пример:
// Variables
@themes: "../../src/themes";
// Usage
@import "@{themes}/tidal-wave.less";
Свойства
Версия: 1.6.0
@property: color;
.widget {
@{property}: #0ee;
background-@{property}: #999;
}
Компилируется в:
.widget {
color: #0ee;
background-color: #999;
}
Имена переменных
Также можно определить переменные с именем переменной:
@fnord: "I am fnord."; @var: "fnord"; content: @@var;
Что компилируется в:
content: "I am fnord.";
Ленивая оценка
Переменные оцениваются лениво и не должны объявляться перед использованием.
Правильный фрагмент Less:
.lazy-eval {
width: @var;
}
@var: @a;
@a: 9%;
Это также допустимый фрагмент Less:
.lazy-eval-scope {
width: @var;
@a: 9%;
}
@var: @a;
@a: 100%;
оба компилируются в:
.lazy-eval-scope {
width: 9%;
}
При определении переменной дважды используется последнее определение переменной, поиск осуществляется сверху вниз по текущей области видимости. Это аналогично самому CSS, где последнее свойство в определении используется для определения значения.
Например:
@var: 0;
.class {
@var: 1;
.brass {
@var: 2;
three: @var;
@var: 3;
}
one: @var;
}
Компилируется в:
.class {
one: 1;
}
.class .brass {
three: 3;
}
Значения переменных по умолчанию
Иногда поступают запросы о переменных по умолчанию — возможность установить переменную только в том случае, если она ещё не установлена. Эта функция не требуется, потому что вы можете легко переопределить переменную, поместив определение позже.
Например:
// library @base-color: green; @dark-color: darken(@base-color, 10%); // use of library @import "library.less"; @base-color: red;
Это работает нормально из-за ленивой загрузки — base-color переопределяется, а dark-color — тёмно-красным.
Расширение
Расширение — это псевдокласс Less, который объединяет селектор, к которому он прикреплён, с селекторами, которые соответствуют тому, на что он ссылается.
Выпущено v1.4.0
nav ul {
&:extend(.inline);
background: blue;
}
В наборе правил выше селектор :extend применит «расширяющий селектор» (nav ul) к классу .inline везде, где появляется класс .inline. Блок объявления будет сохранён без изменений, но без ссылки на расширение (поскольку расширение — это не CSS).
Таким образом, следующее:
nav ul {
&:extend(.inline);
background: blue;
}
.inline {
color: red;
}
Выходные данные
nav ul {
background: blue;
}
.inline,
nav ul {
color: red;
}
Обратите внимание, как селектор nav ul:extend(.inline) выводится как nav ul — расширение удаляется перед выводом, а блок селектора остаётся без изменений. Если в этом блоке нет свойств, он удаляется из вывода (но расширение по-прежнему может влиять на другие селекторы).
Синтаксис расширения
Расширение прикрепляется к селектору или помещается в набор правил. Оно выглядит как псевдокласс с параметром селектора, за которым необязательно следует ключевое слово all.
Пример:
.a:extend(.b) {}
// the above block does the same thing as the below block
.a {
&:extend(.b);
}
.c:extend(.d all) {
// extends all instances of ".d" e.g. ".x.d" or ".d.x"
}
.c:extend(.d) {
// extends only instances where the selector will be output as just ".d"
}
Он может содержать один или несколько классов для расширения, разделенных запятыми.
Пример:
.e:extend(.f) {}
.e:extend(.g) {}
// the above an the below do the same thing
.e:extend(.f, .g) {}
Расширение, привязанное к селектору
Расширение, привязанное к селектору, выглядит как обычный псевдокласс с селектором в качестве параметра. Селектор может содержать несколько элементов расширения, но все расширения должны стоять в конце селектора.
- Расширение после селектора:
pre:hover:extend(div pre). - Разрешается пробел между селектором и расширением:
pre:hover :extend(div pre). - Разрешается несколько расширений:
pre:hover:extend(div pre):extend(.bucket tr)- Обратите внимание, что это то же самое, что иpre:hover:extend(div pre, .bucket tr) - Это НЕ разрешается:
pre:hover:extend(div pre).nth-child(odd). Расширение должно быть последним.
Если набор правил содержит несколько селекторов, любой из них может иметь ключевое слово extend. Несколько селекторов с extend в одном наборе правил:
.big-division,
.big-bag:extend(.bag),
.big-bucket:extend(.bucket) {
// body
}
Расширение внутри набора правил
Расширение можно поместить в тело набора правил, используя синтаксис &:extend(selector). Помещение расширения в тело — это сокращение для его размещения в каждом селекторе этого набора правил.
Расширение внутри тела:
pre:hover,
.some-class {
&:extend(div pre);
}
абсолютно идентично добавлению расширения после каждого селектора:
pre:hover:extend(div pre),
.some-class:extend(div pre) {}
Расширение вложенных селекторов
Расширение может соответствовать вложенным селекторам. Следуя less:
Пример:
.bucket {
tr { // nested ruleset with target selector
color: blue;
}
}
.some-class:extend(.bucket tr) {} // nested ruleset is recognized
Вывод:
.bucket tr,
.some-class {
color: blue;
}
В сущности, расширение смотрит на скомпилированный CSS, а не на исходный Less.
Пример:
.bucket {
tr & { // nested ruleset with target selector
color: blue;
}
}
.some-class:extend(tr .bucket) {} // nested ruleset is recognized
Вывод:
tr .bucket,
.some-class {
color: blue;
}
Точное соответствие с расширением
Расширение по умолчанию ищет точное соответствие между селекторами. Важно, использует ли селектор ведущую звездочку или нет. Неважно, что две nth-выражения имеют одинаковый смысл, они должны иметь одинаковую форму, чтобы соответствовать. Единственным исключением являются кавычки в селекторе атрибутов, Less понимает, что они имеют одинаковый смысл и сопоставляет их.
Пример:
.a.class,
.class.a,
.class > .a {
color: blue;
}
.test:extend(.class) {} // this will NOT match the any selectors above
Ведущая звездочка имеет значение. Селекторы *.class и .class эквивалентны, но расширение не будет их сопоставлять:
*.class {
color: blue;
}
.noStar:extend(.class) {} // this will NOT match the *.class selector
Вывод:
*.class {
color: blue;
}
Порядок псевдоклассов имеет значение. Селекторы link:hover:visited и link:visited:hover соответствуют одному и тому же набору элементов, но расширение рассматривает их как разные:
link:hover:visited {
color: blue;
}
.selector:extend(link:visited:hover) {}
Вывод:
link:hover:visited {
color: blue;
}
Выражение nth
Форма выражения nth имеет значение. Nth-выражения 1n+3 и n+3 эквивалентны, но расширение не будет их сопоставлять:
:nth-child(1n+3) {
color: blue;
}
.child:extend(:nth-child(n+3)) {}
Вывод:
:nth-child(1n+3) {
color: blue;
}
Тип кавычек в селекторе атрибутов не имеет значения. Все следующие эквивалентны.
[title=identifier] {
color: blue;
}
[title='identifier'] {
color: blue;
}
[title="identifier"] {
color: blue;
}
.noQuote:extend([title=identifier]) {}
.singleQuote:extend([title='identifier']) {}
.doubleQuote:extend([title="identifier"]) {}
Вывод:
[title=identifier],
.noQuote,
.singleQuote,
.doubleQuote {
color: blue;
}
[title='identifier'],
.noQuote,
.singleQuote,
.doubleQuote {
color: blue;
}
[title="identifier"],
.noQuote,
.singleQuote,
.doubleQuote {
color: blue;
}
Расширение "all"
Когда вы указываете ключевое слово all в последнем аргументе расширения, это сообщает Less сопоставить этот селектор как часть другого селектора. Селектор будет скопирован, а сопоставленная часть селектора будет заменена расширением, создавая новый селектор.
Пример:
.a.b.test,
.test.c {
color: orange;
}
.test {
&:hover {
color: green;
}
}
.replacement:extend(.test all) {}
Вывод:
.a.b.test,
.test.c,
.a.b.replacement,
.replacement.c {
color: orange;
}
.test:hover,
.replacement:hover {
color: green;
}
Можно представить этот режим работы как неразрушающий поиск и замену.
Интерполяция селектора с расширением
Расширение НЕ может сопоставлять селекторы с переменными. Если селектор содержит переменную, расширение её проигнорирует.
Существует запрос на новую функцию по этому вопросу, но это не лёгкая правка. Однако расширение может быть прикреплено к интерполированному селектору.
Селектор с переменной не будет сопоставлен:
@variable: .bucket;
@{variable} { // interpolated selector
color: blue;
}
.some-class:extend(.bucket) {} // does nothing, no match is found
и расширение с переменной в целевом селекторе ничего не сопоставляет:
.bucket {
color: blue;
}
.some-class:extend(@{variable}) {} // interpolated selector matches nothing
@variable: .bucket;
Оба предыдущих примера компилируются в:
.bucket {
color: blue;
}
Однако :extend прикреплённый к интерполированному селектору работает:
.bucket {
color: blue;
}
@{variable}:extend(.bucket) {}
@variable: .selector;
предыдущий Less компилируется в:
.bucket, .selector {
color: blue;
}
Ограничение области действия / Расширение внутри @media
Расширение, написанное внутри объявления media, должно сопоставлять только селекторы внутри того же объявления media:
@media print {
.screenClass:extend(.selector) {} // extend inside media
.selector { // this will be matched - it is in the same media
color: black;
}
}
.selector { // ruleset on top of style sheet - extend ignores it
color: red;
}
@media screen {
.selector { // ruleset inside another media - extend ignores it
color: blue;
}
}
компилируется в:
@media print {
.selector,
.screenClass { /* ruleset inside the same media was extended */
color: black;
}
}
.selector { /* ruleset on top of style sheet was ignored */
color: red;
}
@media screen {
.selector { /* ruleset inside another media was ignored */
color: blue;
}
}
Расширение, написанное внутри объявления media, не сопоставляет селекторы внутри вложенного объявления:
@media screen {
.screenClass:extend(.selector) {} // extend inside media
@media (min-width: 1023px) {
.selector { // ruleset inside nested media - extend ignores it
color: blue;
}
}
}
компилируется в:
@media screen and (min-width: 1023px) {
.selector { /* ruleset inside another nested media was ignored */
color: blue;
}
}
Расширение верхнего уровня сопоставляет всё, включая селекторы внутри вложенных media:
@media screen {
.selector { /* ruleset inside nested media - top level extend works */
color: blue;
}
@media (min-width: 1023px) {
.selector { /* ruleset inside nested media - top level extend works */
color: blue;
}
}
}
.topLevel:extend(.selector) {} /* top level extend matches everything */
компилируется в:
@media screen {
.selector,
.topLevel { /* ruleset inside media was extended */
color: blue;
}
}
@media screen and (min-width: 1023px) {
.selector,
.topLevel { /* ruleset inside nested media was extended */
color: blue;
}
}
Обнаружение дублирования
В настоящее время обнаружения дублирования нет.
Пример:
.alert-info,
.widget {
/* declarations */
}
.alert:extend(.alert-info, .widget) {}
Вывод:
.alert-info,
.widget,
.alert,
.alert {
/* declarations */
}
Сценарии использования для расширения
Классический сценарий использования
Классический сценарий использования — это избегание добавления базового класса. Например, если у вас есть
.animal {
background-color: black;
color: white;
}
и вы хотите иметь подтип животного, который перезаписывает цвет фона, у вас есть два варианта: во-первых, изменить ваш HTML
<a class="animal bear">Bear</a>
.animal {
background-color: black;
color: white;
}
.bear {
background-color: brown;
}
или иметь упрощённый HTML и использовать расширение в вашем Less. Например,
<a class="bear">Bear</a>
.animal {
background-color: black;
color: white;
}
.bear {
&:extend(.animal);
background-color: brown;
}
Сокращение размера CSS
Миксины копируют все свойства в селектор, что может привести к ненужному дублированию. Поэтому вы можете использовать расширения вместо миксинов, чтобы переместить селектор в свойства, которые вы хотите использовать, что приводит к меньшему генерируемому CSS.
Пример — с миксином:
.my-inline-block() {
display: inline-block;
font-size: 0;
}
.thing1 {
.my-inline-block;
}
.thing2 {
.my-inline-block;
}
Вывод:
.thing1 {
display: inline-block;
font-size: 0;
}
.thing2 {
display: inline-block;
font-size: 0;
}
Пример (с расширениями):
.my-inline-block {
display: inline-block;
font-size: 0;
}
.thing1 {
&:extend(.my-inline-block);
}
.thing2 {
&:extend(.my-inline-block);
}
Вывод:
.my-inline-block,
.thing1,
.thing2 {
display: inline-block;
font-size: 0;
}
Объединение стилей / Более продвинутый миксин
Ещё один случай использования — это альтернатива миксину, поскольку миксины могут использоваться только с простыми селекторами. Если у вас есть два разных блока HTML, но вам нужно применить те же стили к обоим, вы можете использовать расширения для связи двух областей.
Пример:
li.list > a {
// list styles
}
button.list-style {
&:extend(li.list > a); // use the same list styles
}
Миксины
«Включение» свойств из существующих стилей
Вы можете включать селекторы классов и селекторы id, например:
.a, #b {
color: red;
}
.mixin-class {
.a();
}
.mixin-id {
#b();
}
что приводит к:
.a, #b {
color: red;
}
.mixin-class {
color: red;
}
.mixin-id {
color: red;
}
Обратите внимание, что при вызове миксина скобки необязательны.
// these two statements do the same thing: .a(); .a;
Не выводить миксин
Если вы хотите создать миксин, но не хотите, чтобы этот миксин выводился, вы можете поместить скобки после него.
.my-mixin {
color: black;
}
.my-other-mixin() {
background: white;
}
.class {
.my-mixin;
.my-other-mixin;
}
выводит
.my-mixin {
color: black;
}
.class {
color: black;
background: white;
}
Селекторы в миксинах
Миксины могут содержать больше, чем просто свойства, они также могут содержать селекторы.
Например:
.my-hover-mixin() {
&:hover {
border: 1px solid red;
}
}
button {
.my-hover-mixin();
}
Вывод:
button:hover {
border: 1px solid red;
}
Пространства имён
Если вы хотите включить свойства миксина внутри более сложного селектора, вы можете указать несколько id или классов.
#outer {
.inner {
color: red;
}
}
.c {
#outer > .inner;
}
и снова, как > , так и пробелы необязательны
// all do the same thing #outer > .inner; #outer > .inner(); #outer .inner; #outer .inner(); #outer.inner; #outer.inner();
Одно из применений этого известно как пространства имён. Вы можете поместить свои миксины под селектор id, и это гарантирует, что они не будут конфликтовать с другой библиотекой.
Пример:
#my-library {
.my-mixin() {
color: black;
}
}
// which can be used like this
.class {
#my-library > .my-mixin();
}
Защищённые пространства имён
Если пространство имён имеет охранник, определённые им миксины используются только если условие охранника возвращает true. Охранник пространства имён оценивается точно так же, как охранник миксина, поэтому следующие два миксина работают одинаково:
#namespace when (@mode=huge) {
.mixin() { /* */ }
}
#namespace {
.mixin() when (@mode=huge) { /* */ }
}
Функция default предполагается одинаковой для всех вложенных пространств имён и миксина. Следующий миксин никогда не оценивается, так как одно из условий его охранника гарантированно ложно:
#sp_1 when (default()) {
#sp_2 when (default()) {
.mixin() when not(default()) { /* */ }
}
}
Ключевое слово !important
Используйте ключевое слово !important после вызова миксина, чтобы пометить все унаследованные им свойства как !important:
Пример:
.foo (@bg: #f5f5f5, @color: #900) {
background: @bg;
color: @color;
}
.unimportant {
.foo();
}
.important {
.foo() !important;
}
Результат:
.unimportant {
background: #f5f5f5;
color: #900;
}
.important {
background: #f5f5f5 !important;
color: #900 !important;
}
Параметрические миксины
Как передавать аргументы миксинам
Миксины также могут принимать аргументы, которые являются переменными, передаваемыми в блок селекторов при включении.
Например:
.border-radius(@radius) {
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
border-radius: @radius;
}
И вот как мы можем включить его в различные наборы правил:
#header {
.border-radius(4px);
}
.button {
.border-radius(6px);
}
Параметрические миксины также могут иметь значения по умолчанию для своих параметров:
.border-radius(@radius: 5px) {
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
border-radius: @radius;
}
Теперь мы можем вызвать его так:
#header {
.border-radius;
}
И он включит радиус границы 5px.
Вы также можете использовать параметрические миксины, которые не принимают параметры. Это полезно, если вы хотите скрыть набор правил от вывода CSS, но хотите включить его свойства в другие наборы правил:
.wrap() {
text-wrap: wrap;
white-space: -moz-pre-wrap;
white-space: pre-wrap;
word-wrap: break-word;
}
pre { .wrap }
Что выведет:
pre {
text-wrap: wrap;
white-space: -moz-pre-wrap;
white-space: pre-wrap;
word-wrap: break-word;
}
Миксины с несколькими параметрами
Параметры разделяются либо точкой с запятой, либо запятой. Рекомендуется использовать точку с запятой. Символ запятой имеет двойное значение: он может интерпретироваться как разделитель параметров миксина или разделитель списка CSS.
Использование запятой в качестве разделителя миксина делает невозможным создание разделяемых запятыми списков в качестве аргумента. С другой стороны, если компилятор видит хотя бы одну точку с запятой внутри вызова или объявления миксина, он предполагает, что аргументы разделены точками с запятой, а все запятые относятся к спискам CSS:
- два аргумента, каждый из которых содержит список, разделённый запятыми:
.name(1, 2, 3; something, else), - три аргумента, каждый из которых содержит одно число:
.name(1, 2, 3), - использование фиктивной точки с запятой для создания вызова миксина с одним аргументом, содержащим разделяемый запятыми список CSS:
.name(1, 2, 3;), - значение по умолчанию, разделённое запятыми:
.name(@param1: red, blue;).
Допустимо определять несколько миксинов с одинаковым именем и количеством параметров. Less будет использовать свойства всех, которые могут быть применены. Если вы использовали миксин с одним параметром, например, .mixin(green);, то будут использоваться свойства всех миксинов с ровно одним обязательным параметром:
.mixin(@color) {
color-1: @color;
}
.mixin(@color; @padding: 2) {
color-2: @color;
padding-2: @padding;
}
.mixin(@color; @padding; @margin: 2) {
color-3: @color;
padding-3: @padding;
margin: @margin @margin @margin @margin;
}
.some .selector div {
.mixin(#008000);
}
компилируется в:
.some .selector div {
color-1: #008000;
color-2: #008000;
padding-2: 2;
}
Параметры с именами
Ссылка на миксин может передавать значения параметров по их именам, а не по их позициям. Любой параметр может быть указан по имени, и они не должны быть в каком-либо специальном порядке:
.mixin(@color: black; @margin: 10px; @padding: 20px) {
color: @color;
margin: @margin;
padding: @padding;
}
.class1 {
.mixin(@margin: 20px; @color: #33acfe);
}
.class2 {
.mixin(#efca44; @padding: 40px);
}
компилируется в:
.class1 {
color: #33acfe;
margin: 20px;
padding: 20px;
}
.class2 {
color: #efca44;
margin: 10px;
padding: 40px;
}
Переменная @arguments
@arguments имеет специальное значение внутри миксинов, она содержит все аргументы, которые были переданы при вызове миксина. Это полезно, если вы не хотите иметь дело с отдельными параметрами:
.box-shadow(@x: 0; @y: 0; @blur: 1px; @color: #000) {
-webkit-box-shadow: @arguments;
-moz-box-shadow: @arguments;
box-shadow: @arguments;
}
.big-block {
.box-shadow(2px; 5px);
}
что приводит к:
.big-block {
-webkit-box-shadow: 2px 5px 1px #000;
-moz-box-shadow: 2px 5px 1px #000;
box-shadow: 2px 5px 1px #000;
}
Продвинутые аргументы и переменная @rest
Вы можете использовать ... если хотите, чтобы ваш миксин принимал переменное количество аргументов. Использование этого после имени переменной присвоит эти аргументы переменной.
.mixin(...) { // matches 0-N arguments
.mixin() { // matches exactly 0 arguments
.mixin(@a: 1) { // matches 0-1 arguments
.mixin(@a: 1; ...) { // matches 0-N arguments
.mixin(@a; ...) { // matches 1-N arguments
Кроме того:
.mixin(@a; @rest...) {
// @rest is bound to arguments after @a
// @arguments is bound to all arguments
}
Сопоставление с образцом
Иногда вам может потребоваться изменить поведение миксина в зависимости от параметров, которые вы передаете ему. Давайте начнем с чего-то базового:
.mixin(@s; @color) { ... }
.class {
.mixin(@switch; #888);
}
Теперь предположим, что мы хотим, чтобы .mixin вел себя по-разному в зависимости от значения @switch, мы можем определить .mixin следующим образом:
.mixin(dark; @color) {
color: darken(@color, 10%);
}
.mixin(light; @color) {
color: lighten(@color, 10%);
}
.mixin(@_; @color) {
display: block;
}
Теперь, если мы выполним:
@switch: light;
.class {
.mixin(@switch; #888);
}
Мы получим следующий CSS:
.class {
color: #a2a2a2;
display: block;
}
Где цвет, переданный .mixin, был осветлен. Если значение @switch было dark, результат будет более темным цветом.
Вот что произошло:
- Первое определение миксина не совпало, потому что оно ожидает
darkв качестве первого аргумента. - Второе определение миксина совпало, потому что оно ожидает
light. - Третье определение миксина совпало, потому что оно ожидает любое значение.
Использовались только определения миксинов, которые совпали. Переменные сопоставляются и привязываются к любому значению. Все, что не является переменной, сопоставляется только со значением, равным себе.
Мы также можем сопоставлять по арности, вот пример:
.mixin(@a) {
color: @a;
}
.mixin(@a; @b) {
color: fade(@a; @b);
}
Теперь, если мы вызовем .mixin с одним аргументом, мы получим вывод первого определения, но если мы вызовем его с двумя аргументами, мы получим второе определение, а именно @a с оттенком @b.
Миксины как функции
Возвращаемые переменные или миксины из миксинов
Переменные и миксины, определенные в миксине, видны и могут быть использованы в области вызывающей функции. Существует только одно исключение, переменная не копируется, если вызывающая функция содержит переменную с тем же именем (включая переменные, определенные другим вызовом миксина). Только переменные, присутствующие в локальной области вызывающей функции, защищены. Переменные, унаследованные от родительских областей, переопределяются.
Пример:
.mixin() {
@width: 100%;
@height: 200px;
}
.caller {
.mixin();
width: @width;
height: @height;
}
Результаты:
.caller {
width: 100%;
height: 200px;
}
Таким образом, переменные, определенные в миксине, могут выступать в качестве его возвращаемых значений. Это позволяет нам создавать миксин, который можно использовать почти как функцию.
Пример:
.average(@x, @y) {
@average: ((@x + @y) / 2);
}
div {
.average(16px, 50px); // "call" the mixin
padding: @average; // use its "return" value
}
Результаты:
div {
padding: 33px;
}
Переменные, определенные непосредственно в области вызывающей функции, не могут быть переопределены. Однако переменные, определенные в родительской области вызывающей функции, не защищены и будут переопределены:
.mixin() {
@size: in-mixin;
@definedOnlyInMixin: in-mixin;
}
.class {
margin: @size @definedOnlyInMixin;
.mixin();
}
@size: globaly-defined-value; // callers parent scope - no protection
Результаты:
.class {
margin: in-mixin in-mixin;
}
Наконец, миксин, определенный в миксине, также действует как возвращаемое значение:
.unlock(@value) { // outer mixin
.doSomething() { // nested mixin
declaration: @value;
}
}
#namespace {
.unlock(5); // unlock doSomething mixin
.doSomething(); //nested mixin was copied here and is usable
}
Результаты:
#namespace {
declaration: 5;
}
Передача наборов правил миксинам
Разрешение обертывания блока CSS, определенного в миксине
Выпущено v1.7.0
Отделенный набор правил — это группа свойств CSS, вложенных наборов правил, объявлений медиа или чего-либо еще, хранящихся в переменной. Вы можете включить его в набор правил или другую структуру, и все его свойства будут скопированы туда. Вы также можете использовать его в качестве аргумента миксина и передавать его как любую другую переменную.
Простой пример:
// declare detached ruleset
@detached-ruleset: { background: red; };
// use detached ruleset
.top {
@detached-ruleset();
}
компилируется в:
.top {
background: red;
}
Скобки после вызова отдельного набора правил являются обязательными. Вызов @detached-ruleset; НЕ будет работать.
Это полезно, когда вы хотите определить миксин, который абстрагирует либо обертывание фрагмента кода в медиазапрос, либо имя класса браузера, которое не поддерживается. Наборы правил могут быть переданы в миксин, так что миксин может обернуть содержимое, например:
.desktop-and-old-ie(@rules) {
@media screen and (min-width: 1200px) { @rules(); }
html.lt-ie9 & { @rules(); }
}
header {
background-color: blue;
.desktop-and-old-ie({
background-color: red;
});
}
Здесь миксин desktop-and-old-ie определяет медиазапрос и корневой класс, чтобы вы могли использовать миксин для обертывания фрагмента кода. Это выведет
header {
background-color: blue;
}
@media screen and (min-width: 1200px) {
header {
background-color: red;
}
}
html.lt-ie9 header {
background-color: red;
}
Теперь набор правил может быть назначен переменной или передан в миксин и может содержать полный набор функций Less, например:
@my-ruleset: {
.my-selector {
background-color: black;
}
};
Вы даже можете воспользоваться всплыванием медиазапросов, например
@my-ruleset: {
.my-selector {
@media tv {
background-color: black;
}
}
};
@media (orientation:portrait) {
@my-ruleset();
}
что выведет
@media (orientation: portrait) and tv {
.my-selector {
background-color: black;
}
}
Вызов отдельного набора правил разблокирует (возвращает) все его миксины в вызывающую функцию так же, как и вызовы миксина. Однако он НЕ возвращает переменные.
Возвращаемый миксин:
// detached ruleset with a mixin
@detached-ruleset: {
.mixin() {
color:blue;
}
};
// call detached ruleset
.caller {
@detached-ruleset();
.mixin();
}
Результаты:
.caller {
color: blue;
}
Приватные переменные:
@detached-ruleset: {
@color:blue; // this variable is private
};
.caller {
color: @color; // syntax error
}
Области
Отдельный набор правил может использовать все переменные и миксины, доступные там, где он определен, и где он вызывается. Другими словами, доступны обе области определения и вызова. Если обе области содержат одну и ту же переменную или миксин, значение области объявления имеет приоритет.
Область объявления — это та, в которой определен тело отдельного набора правил. Копирование отдельного набора правил из одной переменной в другую не может изменить его область. Набор правил не получает доступа к новым областям просто путем ссылки на них.
Наконец, отдельный набор правил может получить доступ к области, разблокировав (импортировав) его в нее.
Видимость области определения и вызова
Отдельный набор правил видит переменные и миксины вызывающей функции:
@detached-ruleset: {
caller-variable: @caller-variable; // variable is undefined here
.caller-mixin(); // mixin is undefined here
};
selector {
// use detached ruleset
@detached-ruleset();
// define variable and mixin needed inside the detached ruleset
@caller-variable: value;
.caller-mixin() {
variable: declaration;
}
}
компилируется в:
selector {
caller-variable: value;
variable: declaration;
}
Переменные и миксины, доступные от определения, имеют приоритет над теми, которые доступны в вызывающей функции:
@variable: global;
@detached-ruleset: {
// will use global variable, because it is accessible
// from detached-ruleset definition
variable: @variable;
};
selector {
@detached-ruleset();
@variable: value; // variable defined in caller - will be ignored
}
компилируется в:
selector {
variable: global;
}
Ссылка не изменяет область отдельного набора правил
Набор правил не получает доступа к новым областям просто путем ссылки на них:
@detached-1: { scope-detached: @one @two; };
.one {
@one: visible;
.two {
@detached-2: @detached-1; // copying/renaming ruleset
@two: visible; // ruleset can not see this variable
}
}
.use-place {
.one > .two();
@detached-2();
}
выбрасывает ошибку:
ERROR 1:32 The variable "@one" was not declared.
Разблокирование изменит область отдельного набора правил
Отдельный набор правил получает доступ, будучи разблокированным (импортированным) в область:
#space {
.importer-1() {
@detached: { scope-detached: @variable; }; // define detached ruleset
}
}
.importer-2() {
@variable: value; // unlocked detached ruleset CAN see this variable
#space > .importer-1(); // unlock/import detached ruleset
}
.use-place {
.importer-2(); // unlock/import detached ruleset second time
@detached();
}
компилируется в:
.use-place {
scope-detached: value;
}
Директивы импорта
Импортировать стили из других таблиц стилей
В стандартном CSS директивы @import должны предшествовать всем другим типам правил. Но Less.js не заботится о том, где вы помещаете @import инструкции.
Пример:
.foo {
background: #900;
}
@import "this-is-valid.less";
Расширения файлов
Директивы @import могут обрабатываться Less по-разному в зависимости от расширения файла:
- Если файл имеет расширение
.css, он будет обрабатываться как CSS, а директива@importостанется в том же виде (см. опцию inline ниже). - Если у него есть любое другое расширение, он будет обрабатываться как Less и импортирован.
- Если у него нет расширения,
.lessбудет добавлен, и он будет включен в качестве импортированного файла Less.
Примеры:
@import "foo"; // foo.less is imported @import "foo.less"; // foo.less is imported @import "foo.php"; // foo.php imported as a less file @import "foo.css"; // statement left in place, as-is
Следующие параметры могут использоваться для переопределения этого поведения.
Параметры импорта
Less предлагает несколько расширений директивы CSS @import CSS, чтобы предоставить больше гибкости в том, что вы можете делать с внешними файлами.
Синтаксис: @import (keyword) "filename";
Следующие директивы импорта были реализованы:
-
reference: использовать файл Less, но не выводить его -
inline: включить исходный файл в выходные данные, но не обрабатывать его -
less: обрабатывать файл как файл Less, независимо от расширения файла -
css: обрабатывать файл как CSS-файл, независимо от расширения файла -
once: включить файл только один раз (это поведение по умолчанию) -
multiple: включать файл несколько раз -
optional: продолжать компиляцию, когда файл не найден
Можно использовать несколько ключевых слов в одной директиве @import, вам нужно будет использовать запятые для разделения ключевых слов:
Пример: @import (optional, reference) "foo.less";
reference
Используйте @import (reference) для импорта внешних файлов, но не добавляйте импортированные стили в выходные данные компиляции, если они не сосланы.
Выпущено v1.5.0
Пример: @import (reference) "foo.less";
Представьте, что reference помечает каждую директиву и селектор флагом ссылка в импортированном файле, импортирует как обычно, но при генерации CSS, селекторы "ссылка" (а также любые медиазапросы, содержащие только селекторы ссылки) не выводятся. reference стили не появятся в вашем сгенерированном CSS, если стили ссылки не используются как миксины или расширения.
Кроме того, reference дает разные результаты в зависимости от использованного метода (миксин или расширение):
-
расширение: При расширении селектора, только новый селектор помечается как не сосланы, и он вставляется в позицию директивы ссылки
@import. -
миксины: Когда
referenceстиль используется как неявный миксин, его правила смешиваются, помечаются "не ссылка", и появляются в сосланой позиции как обычно.
пример reference
Это позволяет вам импортировать только определенные, целевые стили из библиотеки, такой как Bootstrap, сделав что-то вроде этого:
.navbar:extend(.navbar all) {}
И вы импортируете только .navbar связанные стили из Bootstrap.
inline
Используйте @import (inline) для включения внешних файлов, но не обрабатывайте их.
Выпущено v1.5.0
Пример: @import (inline) "not-less-compatible.css";
Вы будете использовать это, когда файл CSS может быть несовместим с Less; это потому, что хотя Less поддерживает большинство известных стандартов CSS, он не поддерживает комментарии в некоторых местах и не поддерживает все известные CSS-хаки без модификации CSS.
Так что вы можете использовать это для включения файла в выходные данные, чтобы все CSS были в одном файле.
less
Используйте @import (less) для обработки импортированных файлов как Less, независимо от расширения файла.
Выпущено v1.4.0
Пример:
@import (less) "foo.css";
css
Используйте @import (css) для обработки импортированных файлов как обычного CSS, независимо от расширения файла. Это означает, что директива импорта останется как есть.
Выпущено v1.4.0
Пример:
@import (css) "foo.less";
выводит
@import "foo.less";
once
Поведение по умолчанию для @import директив. Это означает, что файл импортируется только один раз, и последующие директивы импорта для этого файла будут проигнорированы.
Выпущено v1.4.0
Это поведение по умолчанию для операторов @import.
Пример:
@import (once) "foo.less"; @import (once) "foo.less"; // this statement will be ignored
multiple
Используйте @import (multiple) для разрешения импорта нескольких файлов с одинаковым именем. Это противоположное поведение по сравнению с once.
Выпущено v1.4.0
Пример:
// file: foo.less
.a {
color: green;
}
// file: main.less
@import (multiple) "foo.less";
@import (multiple) "foo.less";
Выходные данные
.a {
color: green;
}
.a {
color: green;
}
optional
Используйте @import (optional) для разрешения импорта файла только в случае его существования. Без ключевого слова optional Less генерирует ошибку FileError и останавливает компиляцию при импорте файла, который не найден.
Выпущено v2.3.0
Защиты миксинов
Условные миксины
Защиты полезны, когда вы хотите соответствовать выражениям, а не простым значениям или арности. Если вы знакомы с функциональным программированием, вы, вероятно, уже сталкивались с ними.
Стремясь максимально приблизиться к декларативной природе CSS, Less выбрал реализацию условного выполнения с помощью защищённых миксинов вместо if/else операторов, в духе @media спецификаций функций запроса.
Давайте начнём с примера:
.mixin (@a) when (lightness(@a) >= 50%) {
background-color: black;
}
.mixin (@a) when (lightness(@a) < 50%) {
background-color: white;
}
.mixin (@a) {
color: @a;
}
Ключевым словом является when , которое вводит последовательность защит (здесь только одна защита). Теперь, если мы выполним следующий код:
.class1 { .mixin(#ddd) }
.class2 { .mixin(#555) }
Вот что мы получим:
.class1 {
background-color: black;
color: #ddd;
}
.class2 {
background-color: white;
color: #555;
}
Операторы сравнения защит
Полный список операторов сравнения, используемых в защитах: >, >=, =, =<, < . Кроме того, ключевое слово true является единственным истинным значением, делающим эти два миксина эквивалентными:
.truth (@a) when (@a) { ... }
.truth (@a) when (@a = true) { ... }
Любое значение, отличное от ключевого слова true, ложно:
.class {
.truth(40); // Will not match any of the above definitions.
}
Обратите внимание, что вы также можете сравнивать аргументы друг с другом или с неаргументами:
@media: mobile;
.mixin (@a) when (@media = mobile) { ... }
.mixin (@a) when (@media = desktop) { ... }
.max (@a; @b) when (@a > @b) { width: @a }
.max (@a; @b) when (@a < @b) { width: @b }
Логические операторы защит
Вы можете использовать логические операторы с защитами. Синтаксис основан на запросах CSS.
Используйте ключевое слово and для объединения защит:
.mixin (@a) when (isnumber(@a)) and (@a > 0) { ... }
Вы можете эмулировать оператор или, разделяя защиты запятой ,. Если любая из защит оценивается как истинная, это считается совпадением:
.mixin (@a) when (@a > 10), (@a < -10) { ... }
Используйте ключевое слово not для отрицания условий:
.mixin (@b) when not (@b > 0) { ... }
Функции проверки типов
Наконец, если вы хотите сопоставить миксины на основе типа значения, вы можете использовать функции is.
Вот базовые функции проверки типов:
iscolorisnumberisstringiskeywordisurl
Если вы хотите проверить, является ли значение числом в определённой единице измерения, вы можете использовать одну из:
ispixelispercentageisemisunit
Условные миксины
(FIXME) Кроме того, функция default может использоваться для сопоставления миксина в зависимости от других совпадений миксинов, и вы можете использовать её для создания «условных миксинов», подобных операторам else или default (соответственно, структур if и case):
.mixin (@a) when (@a > 0) { ... }
.mixin (@a) when (default()) { ... } // matches only if first mixin does not, i.e. when @a <= 0
Защиты CSS
"if"'s вокруг селекторов
Выпущено v1.5.0
Защиты также могут применяться к CSS-селекторам, что является синтаксическим сахаром для объявления миксина и его немедленного вызова.
Например, до версии 1.5.0 вам пришлось бы сделать это:
.my-optional-style() when (@my-option = true) {
button {
color: white;
}
}
.my-optional-style();
Теперь вы можете применить защиту непосредственно к стилю.
button when (@my-option = true) {
color: white;
}
Вы также можете достичь оператора типа if, объединив это с функцией &, что позволяет группировать несколько защит.
& when (@my-option = true) {
button {
color: white;
}
a {
color: blue;
}
}
Циклы
Создание циклов
В Less миксин может вызывать себя. Такие рекурсивные миксины в сочетании с Выражениями защит и Сопоставлением шаблонов могут использоваться для создания различных итерационных/циклических структур.
Пример:
.loop(@counter) when (@counter > 0) {
.loop((@counter - 1)); // next iteration
width: (10px * @counter); // code for each iteration
}
div {
.loop(5); // launch the loop
}
Вывод:
div {
width: 10px;
width: 20px;
width: 30px;
width: 40px;
width: 50px;
}
Общий пример использования рекурсивного цикла для генерации классов CSS-сетки:
.generate-columns(4);
.generate-columns(@n, @i: 1) when (@i =< @n) {
.column-@{i} {
width: (@i * 100% / @n);
}
.generate-columns(@n, (@i + 1));
}
Вывод:
.column-1 {
width: 25%;
}
.column-2 {
width: 50%;
}
.column-3 {
width: 75%;
}
.column-4 {
width: 100%;
}
Объединение
Объединение свойств
Функция merge позволяет агрегировать значения из нескольких свойств в список, разделённый запятыми или пробелами, под одним свойством. merge полезна для свойств, таких как background и transform.
Запятая
Добавление значения свойства с запятой
Выпущено v1.5.0
Пример:
.mixin() {
box-shadow+: inset 0 0 10px #555;
}
.myclass {
.mixin();
box-shadow+: 0 0 20px black;
}
Выходные данные
.myclass {
box-shadow: inset 0 0 10px #555, 0 0 20px black;
}
Пробел
Добавление значения свойства с пробелом
Выпущено v1.7.0
Пример:
.mixin() {
transform+_: scale(2);
}
.myclass {
.mixin();
transform+_: rotate(15deg);
}
Выходные данные
.myclass {
transform: scale(2) rotate(15deg);
}
Чтобы избежать случайных объединений, merge требует явного флага + или +_ на каждом ожидающем объявлении объединения.
Селекторы родителя
Ссылка на селекторы родителя с помощью &
Оператор & представляет селекторы родителей вложенного правила вложенного правила и чаще всего используется при применении изменяющего класса или псевдокласса к существующему селектору:
a {
color: blue;
&:hover {
color: green;
}
}
результат:
a {
color: blue;
}
a:hover {
color: green;
}
Обратите внимание, что без & вышеприведённый пример даст результат a :hover (селектор потомка, который соответствует выделенным элементам внутри тегов <a>), и это не то, что мы обычно хотим сделать с вложенным :hover.
Оператор "селекторов родителя" имеет множество применений. По существу, каждый раз, когда вам нужны селекторы вложенных правил, объединённые другими способами, кроме стандартных. Например, ещё одно типичное использование оператора & — это создание повторяющихся имён классов:
.button {
&-ok {
background-image: url("ok.png");
}
&-cancel {
background-image: url("cancel.png");
}
&-custom {
background-image: url("custom.png");
}
}
вывод:
.button-ok {
background-image: url("ok.png");
}
.button-cancel {
background-image: url("cancel.png");
}
.button-custom {
background-image: url("custom.png");
}
Несколько &
& может появляться более одного раза в селекторе. Это позволяет неоднократно ссылаться на селектор родителя без повторения его имени.
.link {
& + & {
color: red;
}
& & {
color: green;
}
&& {
color: blue;
}
&, &ish {
color: cyan;
}
}
выведет:
.link + .link {
color: red;
}
.link .link {
color: green;
}
.link.link {
color: blue;
}
.link, .linkish {
color: cyan;
}
Обратите внимание, что & представляет все селекторы родителей (а не только ближайшего предка), поэтому следующий пример:
.grand {
.parent {
& > & {
color: red;
}
& & {
color: green;
}
&& {
color: blue;
}
&, &ish {
color: cyan;
}
}
}
результат:
.grand .parent > .grand .parent {
color: red;
}
.grand .parent .grand .parent {
color: green;
}
.grand .parent.grand .parent {
color: blue;
}
.grand .parent,
.grand .parentish {
color: cyan;
}
Изменение порядка селекторов
Полезно добавлять селектор перед унаследованными (родительскими) селекторами. Это можно сделать, поместив & после текущего селектора. Например, при использовании Modernizr вы можете задавать разные правила, основанные на поддерживаемых функциях:
.header {
.menu {
border-radius: 5px;
.no-borderradius & {
background-image: url('images/button-background.png');
}
}
}
Селектор .no-borderradius & добавит .no-borderradius перед своим родительским селектором .header .menu для формирования .no-borderradius .header .menu на выходе:
.header .menu {
border-radius: 5px;
}
.no-borderradius .header .menu {
background-image: url('images/button-background.png');
}
Комбинаторный взрыв
& также может использоваться для генерации всех возможных перестановок селекторов в списке, разделённом запятыми:
p, a, ul, li {
border-top: 2px dotted #366;
& + & {
border-top: 0;
}
}
Это расширяется до всех возможных (16) комбинаций указанных элементов:
p,
a,
ul,
li {
border-top: 2px dotted #366;
}
p + p,
p + a,
p + ul,
p + li,
a + p,
a + a,
a + ul,
a + li,
ul + p,
ul + a,
ul + ul,
ul + li,
li + p,
li + a,
li + ul,
li + li {
border-top: 0;
}
© 2009–2016 The Core Less Team
Licensed under the Creative Commons Attribution License 3.0.
http://lesscss.org/features