От автора: в настоящее время в CSS есть четыре хорошо поддерживаемых математических функции. Я обнаружил, что каждая из них чрезвычайно полезена в повседневной работе. Эти функции могут использоваться, возможно, неожиданными способами, например, в градиентах и цветовых функциях, а также в сочетании с пользовательскими свойствами CSS. Мы изучим синтаксис каждой из них, рассмотрим основные демонстрации их функций а также практические варианты их использования.
calc()
Практическое назначение calc(): выполнение основных математических операций с возможностью интерполяции между типами единиц.
Эта математическая функция дольше всех из четырех исследуемых нами поддерживается разными браузерами. Она имеет широкий спектр применений в любое время, когда вы хотите иметь возможность выполнять математические вычисления на стороне клиента в своих стилях.
Например, вы можете захотеть, чтобы что-то занимало большую часть высоты области просмотра, кроме высоты навигации. Для этой цели вы можете смешивать единицы измерения, чтобы передать относительную единицу vh (высоту просмотра) с абсолютной единицей пикселей:
1 2 3 |
.content { height: calc(100vh - 60px); } |
По мере изменения размера окна просмотра или использования пользователем больших или меньших устройств значение 100vh будет динамически обновляться.
Преимущество calc() заключается в том, что вы можете избежать жесткого кодирования диапазона магических чисел или добавления решения JavaScript для вычисления значения, необходимого для его применения в качестве встроенного стиля.
Использование calc() для генеративных цветовых палитр
Мы можем расширить возможности calc(), передав в CSS пользовательские свойства. Примером этого, является создание согласованной цветовой палитры с использованием hsl() (что означает оттенок, насыщенность и яркость). Учитывая значения насыщенности, яркости и начального оттенка, мы можем вычислить дополнительные значения для создания полной палитры. Из-за общности значений насыщенности и яркости палитра будет казаться цельной.
CSS для примера «Использование calc() для создания цветовой палитры HSL»:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
.colors { --base-hue: 140; --saturation: 95%; --lightness: 80%; --rotation: 60; color: #222; text-align: center; } .color { padding: 0.25rem; background-color: hsl(var(--hue), var(--saturation), var(--lightness)); } .color1 { --hue: calc(var(--base-hue)); } .color2 { --hue: calc(var(--base-hue) + var(--rotation)); } .color3 { --hue: calc(var(--base-hue) + var(--rotation) * 2); } |
clamp()
Практическая цель clamp(): установить границы диапазона допустимых значений. Функция clamp() принимает три значения, их порядок имеет значение. Первое — это самое низкое значение в вашем диапазоне, среднее — ваше идеальное значение, а третье — самое высокое значение в вашем диапазоне.
Область, в которой вы, возможно, уже сталкивались с clamp() — это гибкая типографика. Основная идея заключается в том, что значение font-size можно плавно регулировать в зависимости от размера области просмотра. Это сделано для того, чтобы большие заголовки не вызывали переполнение или занимали слишком много места в области просмотра.
Вот очень простое определение плавного стиля h1:
1 2 3 |
h1 { font-size: clamp(1.75rem, 4vw + 1rem, 3rem); } |
Относительное заполнение с clamp()
Другой пример можно увидеть в моей демонстрации от Smol CSS об адаптивном заполнении. В использовании процентов для заполнения интересно то, что они относятся к ширине элемента. Это означает, что это немного похоже на относительную к контейнеру единицу, которую мы можем использовать так же, как vw.
В примере от SmolCSS используется следующее определение заполнения, в котором заполнение будет увеличиваться и уменьшаться относительно ширины элемента. Оно никогда не будет меньше 1rem и никогда не будет больше 3rem:
1 2 3 |
.element { padding: 1.5rem clamp(1rem, 5%, 3rem); } |
Возможно, вы поняли, что это удаляет некоторые сценарии, в которых вы могли использовать медиа-запросы. Вместо того, чтобы управлять этим интервалом на микроуровне или беспокоиться о строгом соблюдении линейного изменения пикселей (например, 8, 12, 24, 36), вы можете установить разумные рекомендации для гибкого перехода.
Наиболее значительным преимуществом здесь по сравнению с медиа-запросами является то, что, поскольку это определение заполнения является относительным элементом, оно будет больше, если у элемента больше места на странице, и меньше, если, например, он помещен в узкий столбец. Это потребует большой координации с служебными классами на основе медиа-запросов!
min()
Практическая цель min() — установка границ максимально допустимого значения таким образом, чтобы охватить реагирующий контекст элемента.
Правильно — несмотря на то, что это функция min(), в результате предоставленные значения будут действовать как максимально допустимое значения для свойств.
Установив значение width:min(80ch, 100vw), в большем окне просмотра будет выбрано 80ch, потому что это меньшее значение из двух вариантов, но оно действует как максимум на основе контекстно доступного пространства. Как только область просмотра сжимается, будет использоваться 100vw, потому что оно вычисляется как меньше чем 80ch, но фактически обеспечивает максимальную границу для ширины элемента.
Современный класс CSS container
Только что приведенный пример — это мой предпочтительный способ определения container с помощью одной маленькой настройки. Функция min() позволяет вложенные основные математические операции, а значит, мы можем использовать вычитание некоторого пространства в качестве замены для определения левых и правых отступов, следующим образом:
1 2 3 |
.container { width: min(80ch, 100vw - 2rem); } |
На больших экранах, элемент может вырасти до max равно 80ch, и как только окно просмотра сжимается ниже этой ширины, она будет иметь возможность расти до 100vw — 2rem. Это определение эффективно создает «отступы» 1rem по обе стороны от элемента.
В этом примере вы также можете использовать 100% вместо vw, чтобы настроить ширину элемента в родительском контейнере. CSS для «современного класса CSS container»:
1 2 3 4 5 |
.container { width: min(40ch, 100% - 2rem); margin-right: auto; margin-left: auto; } |
Краткое примечание: единица измерения ch равна ширине символа 0 с учетом всех текущих свойств font на момент ее применения. Это делает ee отличным выбором для приблизительного определения длины строки, например, для лучшего чтения.
Какая польза? Адаптивный размер без медиа-запросов! Функция min() — моя наиболее часто используемая математическая функция. Давайте посмотрим на еще несколько удивительных улучшений практических сценариев.
Размер адаптивного элемента с помощью min()
Каждый раз, когда вы хотите изменить размер элемента, функция min() может быть отличным выбором. Например, я исследовал использование min() для управления размером аватарки в ветке комментариев в 26-м эпизоде Modern CSS.
В примере аватарки, мы применяли три значения с различными единицами: min(64px, 15%, 10vw). Размер аватарки не будет превышать одно из этих значений в любой момент времени, при этом браузер выбирает минимальное вычисленное значение.
Это определение позволяет никогда не иметь аватарки больше, чем 64px. В частности, при увеличении масштаба изображение размером 10vw кажется более относительным. И 15% помогает сохранить размер относительно элемента, что может дать более визуально привлекательный результат до применения 10vw.
Использование min() в других свойствах
Математические функции CSS можно использовать в большинстве свойств, допускающих числовое значение. Одно уникальное место для их использования — внутри background-size.
Почему? Возможно, вы создаете многослойный эффект цвета фона и изображения. И вместо того, чтобы использовать значение размера cover, которое заставило бы изображение заполнять пространство, вы хотели бы ограничить рост изображения. Это идеальное место для использования min().
Рассмотрим следующий пример, где min() используется, чтобы гарантировать, что изображение не выходит за пределы 600px, при этом изменяет свой размер относительно ширины элемента, установив значение 100%. Другими словами, оно вырастет до 600px а затем изменит свой размер в соответствии с шириной элемента, если он меньше 600px.
CSS для примера «Управление размером фона с помощью min()»:
1 2 3 4 |
.background-image { background: #1F1B1C url(https://source.unsplash.com/RapCPd_mJTU/800x800) no-repeat center; background-size: min(600px, 100%); } |
max()
Практическая цель max(): установить границы минимально допустимого значения таким образом, чтобы охватить адаптивный контекст элемента.
Ага, max() это полная противоположность min()! Итак, теперь мы устанавливаем определения для минимально допустимых значений. Приступим к примерам!
Контекстные отступы с max()
Узнав о критерии успеха 1.4.10 Руководства по обеспечению доступности веб-контента (WCAG), в котором говорится, что пользователь должен иметь возможность использовать масштабирование для увеличения вашего сайта до 400%, я заметил, что пиксели и rems становятся второстепенной единицей в этом контексте.
Учитывая размер рабочего стола 1280 пикселей при масштабировании 400%, ваш контент эквивалентен устройству с разрешением 320 пикселей. Однако, по сравнению с мобильным телефоном, ориентация по-прежнему альбомная. Область просмотра такого размера означает значительно уменьшенную область для чтения и выполнения действий. Кроме того, размеры, которые казались подходящими для телефона, становятся намного большими в контексте при просмотре в увеличенном окне.
К счастью, max() дает нам способ, более изящно обрабатывать поля. Я избегаю значений пикселей в работе и обычно предпочитаю rem для малых размеров. Я использую следующий пример, который позволяет относительный рост для больших экранов и уменьшение для более малых.
1 2 3 |
.element + .element { margin-top: max(8vh, 2rem); } |
На больших экранах будет использоваться 8vh, а на меньших или при увеличении изображения будет использоваться 2rem. Я рекомендую вам попробовать это и потратить некоторое время на тестирование на разных экранах, устройствах, а также с масштабированием макета и без него. Этот метод представляет собой небольшое обновление, которое может иметь большое значение для конечного пользователя.
Запрет масштабирования браузера для полей ввода в iOS с помощью max()
Был ли у Вас опыт принудительного масштабирования браузера после того, как сфокусировали форму ввода на iOS? Для любого ввода, размер шрифта которого меньше 16px будут последствия.
1 2 3 |
input { font-size: max(16px, 1rem); } |
Где 1rem можно поменять на переменную Sass или пользовательское свойство CSS. Такое использование max() гарантирует, что независимо от другого предоставленного значения, font-size будет по крайней мере 16px и, следовательно, предотвращает принудительное масштабирование браузера.
Контуры относительного фокуса с max()
Я часто использую min() для применения относительного размера контуров фокуса. Это сокращенный фрагмент, но, используя max(), мы гарантируем минимальный размер контура 2px, позволяя ему увеличиваться относительно элемента, используя значение, относящееся к шрифту em.
1 2 3 4 5 6 7 8 9 10 |
a { --outline-size: max(2px, 0.08em); --outline-style: solid; --outline-color: currentColor; } a:focus { outline: var(--outline-size) var(--outline-style) var(--outline-color); outline-offset: var(--outline-size); } |
Доступные целевые размеры с max()
Термин «целевой размер» описан в критериях успеха WCAG (SC) 2.5.5, где «цель» относится к области, которая получит событие указателя (например, клик мыши). В грядущей версии WCAG 2.2 SC 2.5.5 теперь является «улучшенной» версией, минимальный размер которой составляет 44px.
Рассмотрим кнопки, которые используют только значки или аватарки из нашего предыдущего примера, который ссылается на профиль. Или, возможно, кнопка двойного действия, где стрелка раскрывающегося списка является отдельным действием от основного элемента управления кнопки.
В этих случаях мы можем использовать max() аналогично тому, как мы установили запрет для предотвращения масштабирования ввода. Мы установим 44px как одно из значений внутри max() так, чтобы это был минимальный размер элемента.
1 2 3 4 |
.icon-button { width: max(44px, 2em); height: max(44px, 2em); } |
Следует отметить, что этот критерий также учитывает пространство вокруг элемента, которое в сочетании с фактическим размером элемента составляет не менее 44 пикселей.
Использование max() в качестве запасного варианта для aspect-ratio
Другой способ, где я использовал max() — установить высоту изображения при использовании aspect-ratio чтобы обеспечить приемлемый опыт для браузеров, которые еще не поддерживают это свойство.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
img { /* Fallback for `aspect-ratio` of defining a height */ height: max(18vh, 12rem); object-fit: cover; width: 100%; } /* When supported, use `aspect-ratio` */ @supports (aspect-ratio: 1) { img { aspect-ratio: var(--img-ratio); height: auto; } } |
Собираем все вместе
В последней демонстрации показан пример применения нескольких математических функций CSS для обеспечения гибкого изменения размеров для нескольких свойств. Обратите внимание на комментарии рядом с продемонстрированным кодом.
Дополнительные примеры использования математических функций CSS и других современных функций CSS можно найти в моем видео на YouTube.
Автор: Stephanie Eckles
Источник: moderncss.dev
Редакция: Команда webformyself.
Читайте нас в Telegram, VK, Яндекс.Дзен