Привет, Хабр. Я продолжаю рассказывать про неизвестные широкому кругу разработчиков CSS-фишки. Я отбираю их так, чтобы они были полезны в разного рода проектах. Неважно, верстаете ли вы сайт для малого бизнеса или создаёте супермодное React-приложение. Они поддерживаются большинством браузеров. Отдельно отмечу, что я не считаю IE11 современным браузером. По этой причине я не учитывал его.


Сегодня мы рассмотрим:

  • как перестать вредить пользователям свойствами justify-content и align-items;
  • недавно появившиеся возможности разделять CSS на части и управлять их приоритетом;
  • неизвестный нюанс применения псевдо-класса :nth-child.

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


▍ Как однажды свойства justify-content и align-items заблокировали мой экран


Начну сразу с боли. У меня десятидюймовый ноутбук. И постоянно у меня не помещаются модальные окна в экран. Но это ещё мелкая неприятность. Реальная проблема заключается в том, что я не могу их закрыть. А всё почему?


Всегда мысленно говорю «Спасибо» разработчикам, использующим свойства justify-content и align-items для центрирования элемента. На примере покажу, что происходит с вашим модальным окном.


У нас будет один родительский элемент, являющийся флекс-контейнером. В него будет вложен элемент с текстом. Такая имитация модального окна с информацией.


<body>
  <div class="flex-container">
    <div class="flex-item">
      <span>Будет ли виден этот текст?</span>
    </div>
  </div>
</body>

Дочерний элемент с текстом будет отцентрован с помощью свойств justify-content и align-items, и у него будет установлена высота больше, чем у родительского элемента.


.flex-container {
  box-sizing: border-box;
  width: 400px;
  height: 300px;
  margin: 30px;
  border: 2px solid;
  overflow: auto;

  display: flex;
  justify-content: center;
  align-items: center;
}

.flex-item {
  width: 100px;
  height: 110%;
  background-image: linear-gradient(to bottom, lightgreen 5%, pink 5% 95%, lightgreen 95%);
}

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



Часть текста обрезана. Именно так я вижу ваши модальные окна. А закрыть я их не могу, потому что кнопка «Крестик» скрылась за пределы экрана.


По этой причине раньше я советовал использовать метод центрирования на основе ключевого слова auto для свойства margin. В этом случае проблем нет. Только если быть честным, этот способ не пользуется популярностью среди разработчиков. Надеюсь, новый подход вам зайдёт. Встречайте, ключевое слово safe.


Его суть заключается в том, что если флекс-элементы выходят за пределы родителя, то браузеры автоматически подставляют значение start вместо установленного. Таким образом переполнения не происходит. Мы видим весь контент элемента.


Посмотрим на это поведение в нашем примере. Только сначала добавим ключевое слово safe для свойств justify-content и align-items.


.flex-container {
  box-sizing: border-box;
  width: 400px;
  height: 300px;
  margin: 30px;
  border: 2px solid;
  overflow: auto;

  display: flex;
  justify-content: safe center;
  align-items: safe center;
}

.flex-item {
  width: 100px;
  height: 110%;
  background-image: linear-gradient(to bottom, lightgreen 5%, pink 5% 95%, lightgreen 95%);
}


Теперь текст «Будет ли виден этот текст?» можно прочитать полностью. Так что пользуйтесь на здоровье. Ещё замечу, что с осени этого года ключевое слово поддерживается во всех современных браузерах. А где не поддерживается, то там ничего не cломаетcя. Такие браузеры отобразят страницу так, как будто ключевое слово safe не использовалось вовсе.


▍ CSS позволяет управлять приоритетом правил


Давайте я проверю вашу осведомлённость недавними нововведениями в CSS. Скажите, пожалуйста, какой цвет текста будет у элемента с классом heading?


.heading {
  color: pink;
}

@layer template {
	
  .heading {
    color: red;
  }
}

Правильный ответ — pink. Удивлены? Отлично. Значит, я не зря добавил этот пример в статью. Перед вами CSS-слои, а именно часть кода, начинающаяся с правила @layer. С помощью неё я сбил вас с толку, потому что я поменял привычное понимание специфичности. Да, CSS-слои такие. Могут немного управлять специфичностью селекторов.


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


Если у вас есть опыт подключения CSS от готовых библиотек и компонентов, то вы могли столкнуться с неожиданным переопределением стилей. Та самая ситуация, когда открыл страницу, а там всё разъехалось. Приходилось танцевать с четырьмя бубнами.


Люди добавляли !important, создавали отдельные классы, переписывали CSS. Я вообще соединял !important с пользовательскими CSS-свойствами. В общем, все изобретали свои «велосипеды».


CSS-слои решают эту проблему. У нас появилась возможность указать приоритет специфичности и присвоить его определённой группе правил. Например, я сделаю так, чтобы у CSS из потусторонних библиотек приоритет был меньше, чем у основного.


@layer libs {

  .heading {
    color: green;
  }
}

.heading {
  color: pink;
}

Прикол заключается в том, что неважно, где находится слой. У правил в нём всегда будет более низкий приоритет, чем у правил без слоёв. Так что следующий код идентичен предыдущему.


.heading {
  color: pink;
}

@layer libs {

  .heading {
    color: green;
  }
}

В обоих вариант браузер применят значение pink для свойства color. Суперклассная штука. Эх, вот бы её лет десять назад. Так, надо вернуться. Ведь я рассказал только половину.


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


@layer my-awesome-website {

  .heading {
    color: red;
  }
}

@layer external-components {

  .heading {
    color: green;
  }
}

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


@layer my-awesome-website {

  .heading {
    color: red;
  }
}

@layer external-components {

  .heading {
    color: green; /* это значение победило */
  }
}

Казалось бы, мы снова пришли к тому, что надо контролировать порядок. Только раньше были обычные правила, а теперь CSS-слои.


Спешу успокоить. У нас есть возможность сообщить нужный порядок слоёв с помощью директивы @layer. Я сразу на примере покажу, как она выглядит.


@layer external-components, my-awesome-website; /* здесь я указываю, в каком порядке будет приоритет слоёв */

@layer my-awesome-website {

  .heading {
    color: red;
  }
}

@layer external-components {

  .heading {
    color: green; 
  }
}

Первый слой является с наиболее меньшим приоритетом, а последний — с наивысшим. И неважно, в каком порядке далее в коде они идут. Таким образом, в нашем примере победило значение из слоя my-awesome-website, потому что мы для него указали наивысший приоритет.


@layer external-components, my-awesome-website;

@layer my-awesome-website {

  .heading {
    color: red; /* это значение победило */
  }
}

@layer external-components {

  .heading {
    color: green; 
  }
}

На этом мой краткий обзор закончен. Я считаю, что эта возможность ещё в полной мере не оценена сообществом. CSS-слои — мощнейший инструмент, позволяющий работать с CSS без боли. А вы уже используете их? Если да, поделитесь, пожалуйста, в комментариях вашим опытом.


▍ У нас есть возможность отобрать диапазон элементов


Знаете, я тринадцать лет занимаюсь вёрсткой и постоянно нахожу неизвестные мне нюансы в уже знакомых аспектах. Недавно собирал материал про синтаксис of S для псевдо-класса :nth-child. Я использую его уже больше десяти лет. Казалось, что мне всё уже известно про него. И что вы думаете? Я нашёл новый момент для себя.


Сразу перейду к примеру и создам разметку.


<body>
  <span class="awesome-box">1</span>
  <span class="awesome-box">2</span>
  <span class="awesome-box">3</span>
  <span class="awesome-box">4</span>
  <span class="awesome-box">5</span>
  <span class="awesome-box">6</span>
</body>

Как нужно написать стили, чтобы свойство outline применялось для диапазона элементов? Например, со второго по пятый. Результат должным быть как на изображении.



Месяц назад я не знал, как такое можно сделать без дополнительных классов. За всю свою карьеру в продакшене всегда встречал только это решение. Ладно, не буду больше тянуть. Мы можем использовать комбинацию из псевдо-классов :nth-child, чтобы добавить свойство outline со второго по пятый элемент.


.awesome-box:nth-child(n+2):nth-child(-n+5) {
  outline: 4px dashed coral;
  outline-offset: 5px;
}

Первый псевдо-класс :nth-child(n+2) создаёт счётчик, работающий на увеличение значения, начиная с двойки. Так создаётся минимальное значение из диапазона. Максимальное же мы получаем с помощью второго псевдо-классе :nth-child(-n+5). В нём используется -n, поэтому счётчик работает на уменьшение значения, начиная с пятёрки.


Браузеры для поиска элементов используют пересекающиеся значения счётчиков. Так они находят со второго по пятый.


▍ Заключение


Давайте подведём итог. В этой статье мы рассмотрели:

  • ключевое слово safe, которое не позволяет флекс-элементам выйти за пределы флекс-контейнера при использовании свойств justify-content и align-items;
  • встроенный в CSS метод управления приоритетом правил;
  • использование псевдо-класса nth-child для создания диапазона отбора элементов.

Оставляю ссылки на все выпуски:

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


P.S. Помогаю больше узнать про CSS в своём ТГ-канале CSS isn't magic. Присоединяйтесь. Ссылка в профиле.


Telegram-канал со скидками, розыгрышами призов и новостями IT ?

Комментарии (1)


  1. gruzoveek
    16.10.2024 10:06

    :nth-child прикольный, не знал что его неоднократно можно писать. Пригодится, спасибо!