Неизвестно полезный CSS. Часть 4

в 9:00, , рубрики: css, ruvds_статьи, web-разработка, верстка, лайфхаки
Неизвестно полезный CSS. Часть 4 - 1

Привет. Я продолжаю рассказывать про неизвестные широкому кругу разработчиков CSS фишки. Я отбираю их так, чтобы они были полезны в разного рода проектах.

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

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

  • сброс стилей до значений, взятых из веб-стандартов;
  • возврат значений свойств, установленных в браузере;
  • что можно сделать с прыжками контента при открытии и закрытии модального окна;
  • возможность отобразить текст «красиво» с помощью ключевого слова system-ui;
  • способ стилизации элементов на языке, отличающимся от основного.

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

▍ Ключевое слово unset и revert

Периодически я копаюсь в CSS коде популярных библиотек. Так, однажды я наткнулся на версию CSS Reset от Элада Шехтер.

Сама библиотека довольно старая. Я сам первый раз познакомился с ней в году 2015. Элад обновил её. Его решение основано на использовании ключевых слов unset и revert. Например, так автор сбрасывает стили почти у всех элементов:

/*
  Удаляет все "User-Agent-Stylesheet" стили, за исключением свойства display
*/
*:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) {
  all: unset;
  display: revert;
}

Что же делают ключевые слова? Разберём по порядку.

Для объяснения ключевого слова unset вспомним, что в CSS есть два типа свойств, а именно: наследуемые и ненаследуемые. Разница между ними заключается в том, что первые могут получить значение в результате механизма наследования от родительского элемента, а вторые так не могут.

Если ключевое слово unset используется для наследуемых свойств, то итоговое рассчитанное значение будет получено в результате механизма наследование. Например, в следующем примере значение у свойства color у элемента <p> будет получено из элемента <body>.

body {
  color: #222; 
}

p {
  color: unset; /* итоговое значение будет #222 */
}

А как будет работать ключевое слово для свойств, для которых механизм наследования не работает? Будет использоваться значение, определённое в веб-стандартах. Например, для свойства border-color будет ключевое слово currentColor.

body {
  color: #222; 
}

p {
  color: unset; /* итоговое значение будет #222 */
  border-width: 2px;
  border-style: solid;
  border-color: unset; /* итоговое значение будет #222, которое было получено с помощью currentColor */
}

Открыты инструменты разработчика. Отображается значение rgb(34, 34, 34) для свойства border

Здесь стоит пояснить, почему в devTools мы увидим rgb(34, 34, 34)(#222 в HEX формате). Ключевое слово currentColor передаёт в свойство значение свойства color. Поскольку для элемента <p> установлено ключевое слово unset, с помощью него браузеры установят значение #222. Оно же будет использовано для свойства border-color.

В итоге Элад в своём варианте CSS Reset строкой all: unset сбрасывает все значения, чтобы они либо наследовали значение от родителя, либо использовали установленные стандартами значения.

Такой подход в целом работает, но не без исключений. Первое исключение — это свойство display. После применения строки all: unset у всех элементов будет установлено значение inline, потому что оно установлено стандартами.

По этой причине Элад использует значение revert для свойства display.

/*
  Удаляет все "User-Agent-Stylesheet" стили, за исключением свойства display
*/
*:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) {
  all: unset;
  display: revert;
}

Таким способом браузеры возьмут итоговое значение из «User-Agent-Stylesheet» стилей, установленных в них по умолчанию. Например, для элемента <p> будет взято значение block, а для элемента <span>inline.

Для демонстрации принципа работы я добавлю код к элементам <p> и <span>.

p {
  all: unset;
  display: revert; /* здесь будет display: block */
}

span {
  all: unset;
  display: revert; /* здесь будет display: inline */
}

Открыты инструменты разработчика. Для элемента p отображается значение block для свойства display

Для элемента span отображается значение inline для свойства display

Мне лично не нравится подход «Сначала установим, а потом сбросим». По этой причине я не использую CSS Reset. Но сами значения unset и revert полезны.

Например, в компонентах, у которых меняется значение свойства display. Или в качестве значений по умолчанию для переменных. Кстати, поделитесь, пожалуйста, в комментариях, как вы используете данные значения.

▍ Избавляемся от прыжков текста контента при открытии и закрытии модального окна

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

Почему происходит смещение? Обратите внимание на полосу прокрутки браузера. Когда модальное окно закрыто — она есть, когда открыто — она убирается. Происходит это с помощью значение hidden для свойства overflow, добавленного к элементу <body>. Убирая и добавляя полосу прокрутки, браузеры смещают контент на её ширину.

Существуют несколько техник, чтобы избежать смещения. Моя любимая основана на управлении пространством, выделяемым под полосу прокрутки. Отвечает за это поведение свойство scrollbar-gutter.

В нашей задаче оно позволит навсегда зарезервировать место. Для этого нужно использовать значение stable. Например, разработчики сайта Дока добавляют его к элементам <body> и <html>.

html,
body {
  scrollbar-gutter: stable;
}

Теперь сдвигов контента при открытии и закрытии модального окна нет. Только есть момент, который я не понимаю. Зачем добавлять сразу к двум элементам? Если вы знаете, пожалуйста, напишите в комментариях. Спасибо.

▍ Воспользуемся для контента встроенным в платформу шрифтом

Стилизация текста является обычной рутиной фронтендера. Я не исключение. Для минимизации телодвижений, я написал базовый набор правил. Его использую по умолчанию во всех проектах.

В нём у меня есть возможность установить шрифт для текста. Для этого я создал переменную --ds-typography-main-font-family и объявил её для элемента <body>.

body {
  font-family: var(--ds-typography-main-font-family, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Open Sans, Ubuntu, Fira Sans, Helvetica Neue, sans-serif);
}

Когда я реализовывал эту задачу, у меня был вопрос: «Какое значение по умолчанию установить?» Я погуглил и нашёл список шрифтов, которые рекомендуют для различных платформ. Его я стал использовать долгое время. А потом узнал про ключевое слово system-ui.

В стандарте CSS Fonts Module Level 4 ему дано определение. Я понял его так, что ключевое system-ui позволяет нам использовать для веб-контента шрифт, который встроен в операционную систему. Это помогает избежать отличий между текстом в интерфейсе ОС и текстом в веб-приложении.

«Блин, да это то, что нужно в моей задаче!» — подумал я. Так я добавил ключевое слово в свой сниппет.

body {
  font-family: var(--ds-typography-main-font-family, system-ui);
}

Вместо длинной портянки получилось краткое ёмкое значение по умолчанию.

▍ Стилизация элементов и псевдокласс :lang()

В интерфейсах обычная практика использовать слова из другого языка. Часто они должны быть как-то иначе стилизированы. Для примера возьмём страницу Википедии о CSS. На ней есть фраза «Cascading Style Sheets».

<!DOCTYPE html>
<html lang="ru">
  <head>
    <!-- здесь элементы -->
  </head>
  <body>
    <p>
      CSS (англ. <span lang="en">Cascading Style Sheets</span> «каскадные таблицы стилей») — формальный язык декодирования и описания внешнего вида документа (веб-страницы), написанного с использованием языка разметки (чаще всего HTML или XHTML). 
    </p>
  </body>
</html>

Параграф текста с определением CSS. Фраза Cascading Style Sheets отображается курсивом

Как её сделать курсивом? Да, легко! Добавить класс к элементу, написать font-style: italic и дело сделано. Конечно, это сработает. Но в CSS есть более элегантное решение, а именно псевдокласс :lang().

Он выбирает элементы, в зависимости от их языка. Есть несколько способов установить его. Самый популярный это — атрибут lang. На примере стилизации фразы «Cascading Style Sheets» разберём, как применить псевдоэлемент.

Для элемента <span> уже установлен атрибут lang со значением en. Осталось объявить псевдокласс :lang().

:lang(en) {
  font-style: italic;
}

Можно пойти дальше. Определение стилей для каждого конкретного языка приведёт к раздуванию кода. Можно сделать проще. Написать стили для любого языка, кроме основного.

Напомню, что основной язык определяется при установке атрибута lang для элемента html. В моём примере используется lang="ru". Получается, наша задача заключается в том, чтобы выбрать все элементы, у которых значение атрибута lang отличается от ru.

Псевдокласс :not() тут, как родной.

:not(:lang(ru)) {
  font-style: italic;
}

▍ Заключение

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

  • как ключевое слово unset позволяет сбросить стили до значений веб-стандартов, а ключевое слово revert вернуть их обратно;
  • способ избегать прыжков контента при открытии и закрытии модального окна, основанном на свойстве scrollbar-gutter;
  • ключевое слово system-ui для использования шрифта платформы;
  • псевдокласс :lang() для стилизации элементов на языке, отличающегося от основного.

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

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

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

Автор: melnik909

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js