Правила вложенности в LESS
В этой статье мы с Вами научимся грамотно структурировать стили в наших LESS файлах, используя правила вложенности. Вложенность это одна из множества причин за которую разработчики так любят и используют 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:
- @media - медиа запросы, которые используются для изменения CSS стилей на основании определенных характеристик устройства, связанных с отображением контента, таких как ширина, высота, ориентация, разрешение экрана и тому подобное.
- @supports - позволяет проверить, поддерживает ли браузер пользователя, то или иное свойство CSS, указанное в виде пары ( свойство: значение ) и на основании этого задать стили для необходимого элемента, или элементов.
- @document (отложено до 4 уровня спецификации CSS) - позволяет ограничить стилистические правила в зависимости от URL адреса документа (набор стилей будет применен только к определенным страницам сайта).
В этой статье я предлагаю Вам остановится на рассмотрении использования только правил (директив) @media, так как они в отличии от правил @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>) имеет ширину равную 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>, который определяет видимое содержимое страницы определили три медиа запроса:
- Первый медиа запрос предназначается для всех экранов компьютеров и определяет цвет текста и заднего фона.
- Второй медиа запрос вложен внутри первого медиа запроса и определяет, что если максимальная ширина области просмотра 600 пикселей, или меньше, то цвет текста и заднего фона инвертируются (будут противоположными).
- Третий медиа запрос предназначен для печатных страниц и для режима предварительного просмотра печати и определяет, что цвет заднего фона будет белым, а цвет текста черным.
- Четвертый медиа запрос вложен внутри третьего медиа запроса и предназначен для печатных страниц и для режима предварительного просмотра печати, при этом устройство должно быть "цветным", в этом случае пользователь увидит цвет текста зеленым, конечно, если он при этом не страдает дальтонизмом.
Результат компиляции будет следующим:
@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).
Для понимания сразу перейдем к рассмотрению примера в котором мы используем правило @keyframes, которое позволяет контролировать промежуточные этапы анимации путем создания ключевых кадров в процессе анимации и правило @font-face, которое позволяет веб-сайтам скачать и использовать шрифты, отличные от "безопасных веб-шрифтов".
<!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; // уровень прозрачности для элемента (элемент непрозрачный) } } } }
Обратите внимание, что мы вложили правило @keyframes и правило @font-face внутри элемента <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; // уровень прозрачности для элемента (элемент непрозрачный) } }
Главное, что необходимо понять из этого примера, это то, что правила, которые не имеют определенных условий могут быть вложены по аналогии с селекторами, но при компиляции будут размещаться с теми же телами в общем потоке стилей.
Результат нашего примера: