Правила вложенности в LESS

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

Рис.7 Вложенность в Less.

Вложенные селекторы

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

nav {
    width: 600px; // ширина элемента
    margin: 0 auto; // центрируем внешними отступами
    background: #000; // цвет заднего фона
    color: yellow; // цвет текста
    text-align: center; // выравнивание текста по центру
}
nav ul {
    list-style: none; // маркер не отображается
    margin: 0; // внешние отступы отсутствуют
    padding: 0; // внутренние отступы отсутствуют
}
nav ul li {
    display: inline-block; // выстраиваем элементы в линейку
    width: 200px; // ширина элементов
}

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

С помощью LESS мы можем структурировать все наши селекторы потомков в одном блоке следующим образом:

nav {
    width: 600px; // ширина элемента
    margin: 0 auto; // центрируем внешними отступами
    background: #000; // цвет заднего фона
    color: yellow; // цвет текста
    text-align: center; // выравнивание текста по центру
    ul { // элемент ul вложен в nav
        list-style: none; // маркер не отображается
        margin: 0; // внешние отступы отсутствуют
        padding: 0; // внутренние отступы отсутствуют
        li { // элемент li вложен в ul, который вложен в nav
            display: inline-block; // выстраиваем элементы в линейку
            width: 200px; // ширина элементов
        }
    }
}

Благодаря вложенности мы получили структуру, которая интуитивна понятна даже при беглом чтении кода, в дальнейшем её будет легко поддерживать и при необходимости оперативно вносить изменения.

Обратите внимание, что теперь нам нет необходимости описывать селекторам полный путь от родительского элемента, LESS это сделает за нас автоматически при компиляции. Результат компиляции будет соответствовать первоначальным стилям CSS, которые мы привели в начале примера. Более подробную информацию об использовании различных типов селекторов в LESS вы узнаете в последующих статьях этого учебника.

Вложенные правила

В этом разделе статьи мы с Вами научимся использовать в LESS CSS правила (директивы), рассмотрим нюансы их применения и поймем в чем заключаются принципиальные отличия при их компиляции.

Правила с условием

Правила (директивы) с условием могут ссылаться на какой-то тип состояния, который в любой момент может оказаться истинным, или ложным. Например, если условие истинно, то будет использован один блок объявлений, а если ложно, то другой. К правилам с условием относятся следующие директивы CSS:

В этой статье я предлагаю Вам остановится на рассмотрении использования только правил (директив) @mediacss3, так как они в отличии от правил @document и @supports поддерживаются всеми актуальными браузерами. Обращаю Ваше внимание, что любое правило может быть вложено по аналогии с селекторами, давайте разберем эту полезную возможность LESS на следующем примере:

nav {
    width: 600px; // ширина элемента
    margin: 0 auto; // центрируем внешними отступами
    background: #000; // цвет заднего фона
    color: yellow; // цвет текста
    text-align: center; // выравнивание текста по центру
    @media (max-width: 599px) { // медиа запрос вложен в nav
        width: 100%;
    }
    ul { // элемент ul вложен в nav
        list-style: none; // маркер не отображается
        margin: 0; // внешние отступы отсутствуют
        padding: 0; // внутренние отступы отсутствуют
        li { // элемент li вложен в ul, который вложен в nav
            display: inline-block; // выстраиваем элементы в линейку
            width: 200px; // ширина элементов
            @media (max-width: 599px) { // медиа запрос вложен в li
                width: 33.333333%;
            }
        }
    }
}

В этом примере мы вложили два медиа запроса, первый из них определяет, что если ширина области просмотра устройства 599 пикселей и ниже, то панель навигации (элемент <nav>html5) имеет ширину равную 100% от родительского элемента, то есть растягивается на весь экран, а второй медиа запрос определяет, что элемент списка (элемент <li>) имеет ширину максимально приближенную к трети от родительского элемента.

В результате компиляции мы получим следующий результат:

nav {
    width: 600px; // ширина элемента
    margin: 0 auto; // центрируем внешними отступами
    background: #000; // цвет заднего фона
    color: yellow; // цвет текста
    text-align: center; // выравнивание текста по центру
}
@media (max-width: 599px) { // максимальная ширина области просмотра
    nav {
        width: 100%; // ширина элемента
    }
}
nav ul {
    list-style: none; // маркер не отображается
    margin: 0; // внешние отступы отсутствуют
    padding: 0; // внутренние отступы отсутствуют
}
nav ul li {
    display: inline-block; // выстраиваем элементы в линейку
    width: 200px; // ширина элементов
}
@media (max-width: 599px) { // максимальная ширина области просмотра
    nav ul li {
        width: 33.333333%; // ширина элемента
    }
}

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

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

body { // медиа запросы для элемента <body>
    @media screen { // медиа запрос для экранов компьютеров
        background: black; // цвет заднего фона
        color: white; // цвет текста
        @media (max-width: 600px) {  // медиа запрос для экранов компьютеров, чья максимальная ширина области просмотра 600 пикселей, или меньше 
            background: white; // цвет заднего фона
            color: black; // цвет текста
        }
    }
    @media print { // медиа запрос для печатных страниц и для режима предварительного просмотра печати
        background: white; // цвет заднего фона
        color: black; // цвет текста
        @media (color) {  // медиа запрос для печатных страниц и для режима предварительного просмотра печати, при этом устройство должно быть цветным
            color: green; // цвет текста
        }
    }
}

В этом примере мы для элемента <body>, который определяет видимое содержимое страницы определили три медиа запроса:

Результат компиляции будет следующим:

@media screen { // медиа запрос для экранов компьютеров
    body {
        background: black; // цвет заднего фона
        color: white; // цвет текста
    }
}
@media screen and (max-width: 600px) {  // медиа запрос для экранов компьютеров, чья максимальная ширина области просмотра 600 пикселей, или меньше 
    body {
        color: black; // цвет текста
        background: white; // цвет заднего фона
    }
}
@media print { // медиа запрос для печатных страниц и для режима предварительного просмотра печати
    body {
        color: black; // цвет текста
        background: white; // цвет заднего фона
    }
}
@media print and (color) {  // медиа запрос для печатных страниц и для режима предварительного просмотра печати, при этом устройство должно быть цветным
    body {
        color: green; // цвет текста
    }
}

Прочие правила

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

Для понимания сразу перейдем к рассмотрению примера в котором мы используем правило @keyframescss3, которое позволяет контролировать промежуточные этапы анимации путем создания ключевых кадров в процессе анимации и правило @font-facecss3, которое позволяет веб-сайтам скачать и использовать шрифты, отличные от "безопасных веб-шрифтов".

<!DOCTYPE html>
<html>
<head>
    <title>Использование правил @keyframes и @font-face в LESS</title>
    <link rel = "stylesheet/less" href = "8.less"> <!-- подключаем less файл к документу -->
    <script src = "less.min.js"></script> <!-- подключаем скрипт JavaScript для преобразования метаязыка LESS в CSS -->
</head>
    <body>
        <h1>Заголовок первого уровня.</h1>
        <p>И один абзац для примера.</p>
    </body>
</html>

В этом примере я для своего удобства подключил скрипт JavaScript, который выступает в роли компилятора и преобразует файл 8.less в каскадные таблицы стилей CSS на "лету". В файле less я разместил следующие стили:

article {
    animation: showOn 5s; // имя и длительность анимации
    p {
        color: forestgreen; // цвет текса
        font-family: "Roboto", sans-serif; // указываем название шрифта и в качестве альтернативы шрифт без засечек
        @font-face {
            font-family: "Roboto"; //  задаем произвольное имя для шрифта
            src: url("/fonts/Roboto-Regular.ttf")  format("truetype"); // задаем путь и тип шрифта
            font-style: normal; // стиль шрифта обычный
            font-weight: normal; // нормальное начертание символов
        }
        @keyframes showOn { // назначаем ключевые кадры для анимации
            0% { // начало цикла анимации
                opacity: 0; // уровень прозрачности для элемента (полностью прозрачный)
            }
            50% { // середина цикла анимации
                opacity: .5; // уровень прозрачности для элемента (среднее значение)
            }
            100% { // конец цикла анимации
                opacity: 1; // уровень прозрачности для элемента (элемент непрозрачный)
            }
        }
    }
}

Обратите внимание, что мы вложили правило @keyframescss3 и правило @font-facecss3 внутри элемента <p>. Для того, чтобы увидеть результат преобразования (компиляции) воспользуйтесь компилятором Koala. В результате у Вас должно получиться следующее:

article {
    animation: showOn 5s; // имя и длительность анимации
}
article p {
    color: forestgreen; // цвет текса
    font-family: "Roboto", sans-serif; // указываем название шрифта и в качестве альтернативы шрифт без засечек
}
@font-face {
    font-family: "Roboto"; //  задаем произвольное имя для шрифта
    src: url("/fonts/Roboto-Regular.ttf")  format("truetype"); // задаем путь и тип шрифта
    font-style: normal; // стиль шрифта обычный
    font-weight: normal; // нормальное начертание символов
}
@keyframes showOn { // назначаем ключевые кадры для анимации
    0% { // начало цикла анимации
        opacity: 0; // уровень прозрачности для элемента (полностью прозрачный)
    }
    50% { // середина цикла анимации
        opacity: .5; // уровень прозрачности для элемента (среднее значение)
    }
    100% { // конец цикла анимации
        opacity: 1; // уровень прозрачности для элемента (элемент непрозрачный)
    }
}

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

Результат нашего примера:

Рис. 8 Пример использования правил @keyframes и @font-face в LESS.
Рис.8 Пример использования правил @keyframes и @font-face в LESS.