Основы CSS
CSS (Cascading Style Sheets) — язык каскадных таблиц стилей, который отвечает за внешний вид HTML-документа: цвета, размеры, отступы, расположение элементов, шрифты и анимацию.
CSS-правило состоит из селектора и блока объявлений:
.card {
color: #222;
background-color: #fff;
padding: 16px;
}.card— селектор, выбирающий элементы.color— CSS-свойство.#222— значение свойства.color: #222;— объявление.{ ... }— блок объявлений.
Комментарий в CSS:
/* Это комментарий */Содержание
- Подключение стилей
- Селекторы
- Псевдоклассы и псевдоэлементы
- Каскад, специфичность и наследование
- Бокс-модель
- Единицы измерения
- Цвет и фон
- Типографика
- `display` и поток документа
- Позиционирование
- Размеры и переполнение
- Кастомные свойства и организация CSS
- Переходы и анимация
- Общий пример
Подключение стилей
CSS можно подключать к HTML несколькими способами.
Внешний файл <link>
Основной и рекомендуемый способ:
<head>
<link rel="stylesheet" href="styles.css">
</head>Файл styles.css:
body {
margin: 0;
font-family: Arial, sans-serif;
}Преимущества:
- стили можно использовать на нескольких страницах;
- HTML и CSS хранятся отдельно;
- браузер может кэшировать CSS-файл;
- код проще поддерживать.
Элемент <style>
CSS размещается непосредственно в HTML-документе:
<head>
<style>
body {
background-color: #f5f5f5;
}
h1 {
color: #2c3e50;
}
</style>
</head>Подходит для небольших страниц, экспериментов и стилей, относящихся только к одному документу.
Инлайн-атрибут style
Стили указываются прямо в HTML-элементе:
<p style="color: red; font-weight: 700;">
Важное сообщение
</p>Инлайн-стили имеют высокую специфичность, но их не рекомендуется использовать для основной стилизации:
- они смешивают разметку и оформление;
- их сложно переиспользовать;
- их неудобно переопределять;
- они усложняют поддержку проекта.
Правило @import
Один CSS-файл может подключить другой:
@import url("fonts.css");
@import url("layout.css");
body {
margin: 0;
}Можно указать условие подключения:
@import url("print.css") print;Правила @import должны находиться в начале файла, до обычных CSS-правил. Исключением являются некоторые служебные правила, например @charset.
Для основных стилей предпочтительнее использовать <link>, поскольку цепочки @import могут замедлять загрузку.
Порядок подключения
При одинаковой специфичности применяется правило, объявленное позже:
<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="theme.css">
<link rel="stylesheet" href="page.css">В этом примере theme.css может переопределить base.css, а page.css — оба предыдущих файла.
Типичный порядок:
<link rel="stylesheet" href="normalize.css">
<link rel="stylesheet" href="fonts.css">
<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="components.css">
<link rel="stylesheet" href="pages.css">Селекторы
Селектор определяет, к каким HTML-элементам применяются стили.
Селектор по тегу
Выбирает все элементы указанного типа:
p {
color: #333;
}
button {
cursor: pointer;
}Селектор по классу
Класс записывается через точку:
<p class="message">Сообщение</p>.message {
padding: 12px;
background-color: #eef5ff;
}Один класс можно назначить нескольким элементам:
<p class="note">Первая заметка</p>
<p class="note">Вторая заметка</p>У элемента может быть несколько классов:
<button class="button button--primary">Сохранить</button>Селектор по id
Идентификатор записывается через #:
<section id="contacts">...</section>#contacts {
background-color: #f5f5f5;
}Значение id должно быть уникальным в пределах страницы. Для стилизации обычно удобнее использовать классы, поскольку id обладает высокой специфичностью.
Атрибутные селекторы
Выбирают элементы по наличию или значению атрибута:
/* Любой элемент с атрибутом disabled */
[disabled] {
opacity: 0.5;
}
/* Поле с точным значением атрибута */
input[type="text"] {
border: 1px solid #aaa;
}
/* Ссылка, адрес которой начинается с https */
a[href^="https"] {
color: green;
}
/* Ссылка на PDF-файл */
a[href$=".pdf"] {
font-weight: 700;
}
/* Атрибут содержит указанную подстроку */
[class*="card"] {
box-sizing: border-box;
}Группировка селекторов
Одинаковые стили можно назначить нескольким селекторам:
h1,
h2,
h3 {
font-family: Georgia, serif;
line-height: 1.2;
}Комбинаторы
Комбинаторы описывают отношения между элементами.
| Комбинатор | Название | Описание |
|---|---|---|
| пробел | Потомок | Элемент на любом уровне вложенности |
> |
Дочерний элемент | Только непосредственный потомок |
+ |
Следующий сосед | Первый соседний элемент после выбранного |
~ |
Последующие соседи | Все подходящие соседи после выбранного |
Потомок — пробел
article p {
color: #444;
}Выбирает все <p>, находящиеся внутри <article> на любом уровне вложенности.
Дочерний элемент — >
.menu > li {
display: inline-block;
}Выбирает только <li>, которые являются непосредственными дочерними элементами .menu.
Следующий сосед — +
h2 + p {
margin-top: 0;
}Выбирает первый <p>, расположенный сразу после <h2>.
Последующие соседи — ~
h2 ~ p {
color: #666;
}Выбирает все <p>, расположенные после <h2> и имеющие с ним общего родителя.
Псевдоклассы и псевдоэлементы
Псевдоклассы
Псевдокласс выбирает элемент с учётом его состояния или положения.
:hover
Применяется при наведении указателя:
.button:hover {
background-color: #174ea6;
}На сенсорных устройствах наведение может отсутствовать, поэтому важные действия не должны зависеть только от :hover.
:focus
Выбирает элемент, получивший фокус:
input:focus {
border-color: #2563eb;
outline: 2px solid #93c5fd;
}Не рекомендуется без замены отключать outline, поскольку он помогает пользователям клавиатуры видеть текущий элемент.
:focus-visible
Обычно показывает фокус только тогда, когда браузер считает его необходимым, например при навигации клавиатурой:
.button:focus {
outline: none;
}
.button:focus-visible {
outline: 3px solid #f59e0b;
outline-offset: 3px;
}:nth-child()
Выбирает элементы по их позиции среди всех дочерних элементов родителя:
/* Второй дочерний элемент */
li:nth-child(2) {
font-weight: 700;
}
/* Нечётные элементы */
tr:nth-child(odd) {
background-color: #f5f5f5;
}
/* Чётные элементы */
tr:nth-child(even) {
background-color: #fff;
}
/* Каждый третий элемент */
li:nth-child(3n) {
color: red;
}
/* Первые три элемента */
li:nth-child(-n + 3) {
font-weight: 700;
}:not()
Исключает элементы, соответствующие указанному селектору:
button:not(.button--primary) {
background-color: #ddd;
}Несколько условий:
input:not([type="checkbox"]):not([type="radio"]) {
width: 100%;
}Псевдоэлементы
Псевдоэлемент стилизует условную часть элемента или создаёт декоративный фрагмент.
::before и ::after
Создают псевдоэлемент до или после содержимого:
.link::after {
content: " →";
}
.required::after {
content: " *";
color: red;
}Для ::before и ::after обычно необходимо свойство content:
.card::before {
content: "";
display: block;
width: 40px;
height: 4px;
background-color: #2563eb;
}Псевдоэлементы лучше использовать для декоративного контента, а не для важной информации.
Каскад, специфичность и наследование
Каскад
Если к элементу подходят несколько правил, браузер определяет победителя с учётом:
- важности объявления;
- источника стилей;
- специфичности селектора;
- порядка правил.
При одинаковой специфичности побеждает правило, записанное позже:
.message {
color: blue;
}
.message {
color: red;
}Текст будет красным.
Специфичность
Специфичность можно условно записывать четырьмя группами:
инлайн-стили | id | классы, атрибуты, псевдоклассы | теги, псевдоэлементы| Селектор | Условный вес |
|---|---|
p |
0-0-0-1 |
p::before |
0-0-0-2 |
.message |
0-0-1-0 |
[type="text"] |
0-0-1-0 |
button:hover |
0-0-1-1 |
#header |
0-1-0-0 |
style="" |
1-0-0-0 |
Пример:
p {
color: black; /* 0-0-0-1 */
}
.article p {
color: blue; /* 0-0-1-1 */
}
#content .article p {
color: red; /* 0-1-1-1 */
}Если элемент находится внутри #content и .article, победит последнее правило.
Комбинаторы >, +, ~ и пробел не добавляют специфичность.
!important
!important повышает важность объявления:
.message {
color: red !important;
}Переопределить его обычным правилом нельзя. Среди нескольких !important-объявлений снова учитываются каскад и специфичность.
Частое применение !important усложняет поддержку CSS. Обычно лучше исправить порядок подключения или селектор.
Наследование
Некоторые свойства передаются дочерним элементам:
body {
color: #333;
font-family: Arial, sans-serif;
}Текст внутри body обычно унаследует цвет и шрифт.
Часто наследуются:
color;font-family;font-size;font-weight;line-height;text-align.
Обычно не наследуются:
margin;padding;border;width;height;background.
inherit, initial, unset
.element {
color: inherit;
}inherit принудительно наследует значение от родителя.
.element {
color: initial;
}initial устанавливает начальное значение свойства согласно спецификации CSS.
.element {
color: unset;
}unset работает как inherit для наследуемых свойств и как initial для ненаследуемых.
Бокс-модель
Каждый HTML-элемент рассматривается как прямоугольный блок.
Бокс-модель состоит из:
content— содержимое;padding— внутренний отступ;border— граница;margin— внешний отступ.
.card {
width: 300px;
padding: 20px;
border: 2px solid #333;
margin: 16px;
}При стандартном box-sizing: content-box указанная ширина относится только к содержимому:
300px + 40px padding + 4px border = 344pxВнешние отступы margin в размер элемента не входят.
box-sizing: border-box
При border-box свойства width и height включают содержимое, внутренние отступы и границы:
.card {
box-sizing: border-box;
width: 300px;
padding: 20px;
border: 2px solid #333;
}Итоговая ширина останется 300px.
Обычно border-box включают для всех элементов:
*,
*::before,
*::after {
box-sizing: border-box;
}Схлопывание внешних отступов
Вертикальные margin блочных элементов в обычном потоке могут объединяться:
.first {
margin-bottom: 30px;
}
.second {
margin-top: 20px;
}Расстояние между элементами обычно будет 30px, а не 50px.
Схлопывание может происходить:
- между соседними блочными элементами;
- между родителем и первым или последним дочерним элементом;
- у пустого блочного элемента.
Отступы не схлопываются во Flexbox и Grid. Схлопывание также можно предотвратить, например, с помощью внутреннего отступа, границы или нового контекста форматирования:
.parent {
display: flow-root;
}Единицы измерения
| Единица | Значение |
|---|---|
px |
CSS-пиксель |
% |
Процент от значения, определяемого свойством |
em |
Относительно размера шрифта текущего элемента |
rem |
Относительно размера шрифта корневого элемента |
vw |
Один процент ширины области просмотра |
vh |
Один процент высоты области просмотра |
ch |
Приблизительная ширина символа 0 текущего шрифта |
fr |
Доля свободного пространства в CSS Grid |
px
Подходит для границ, небольших отступов и точных размеров:
.card {
border: 1px solid #ddd;
border-radius: 8px;
}%
Зависит от контекста:
.image {
width: 100%;
}Процентная ширина обычно рассчитывается от ширины содержащего блока.
em
Зависит от вычисленного размера шрифта элемента:
.button {
font-size: 16px;
padding: 0.75em 1.5em;
}Отступы будут изменяться вместе с размером текста кнопки.
При вложенности em может накапливаться:
.list {
font-size: 1.2em;
}Если списки вложены друг в друга, размер текста может увеличиваться на каждом уровне.
rem
Зависит от размера шрифта корневого <html>:
html {
font-size: 16px;
}
h1 {
font-size: 2rem; /* 32px */
}Удобен для согласованной системы размеров и отступов.
vw и vh
.hero {
min-height: 100vh;
}
.title {
font-size: 5vw;
}Для текста обычно следует ограничивать масштабирование:
.title {
font-size: clamp(2rem, 5vw, 4rem);
}ch
Удобен для ограничения длины текстовой строки:
.article {
max-width: 65ch;
}fr
Применяется в CSS Grid:
.layout {
display: grid;
grid-template-columns: 1fr 2fr;
}Вторая колонка получит в два раза больше свободного пространства, чем первая.
Критерии выбора
px— границы, иконки и небольшие точные значения.rem— шрифты, отступы и размеры интерфейса.em— размеры, которые должны зависеть от текущего шрифта.%— адаптивные размеры относительно контейнера.vwиvh— размеры относительно окна браузера.ch— ширина текстовых блоков.fr— распределение свободного пространства в Grid.
Цвет и фон
Шестнадцатеричная запись
.element {
color: #2563eb;
background-color: #fff;
}Краткая форма:
.element {
color: #333; /* #333333 */
}Альфа-канал:
.element {
background-color: #00000080;
}rgb()
.element {
color: rgb(37, 99, 235);
}С прозрачностью:
.overlay {
background-color: rgb(0 0 0 / 50%);
}hsl()
HSL описывает цвет через тон, насыщенность и светлоту:
.element {
color: hsl(217 91% 60%);
}С прозрачностью:
.element {
background-color: hsl(217 91% 60% / 30%);
}Альфа-канал
Альфа-канал определяет прозрачность:
0или0%— полностью прозрачный цвет;1или100%— полностью непрозрачный цвет.
Прозрачный цвет и opacity работают по-разному:
.card {
opacity: 0.5;
}opacity делает полупрозрачным весь элемент вместе с его содержимым.
.card {
background-color: rgb(0 0 0 / 50%);
}Здесь полупрозрачным будет только фон.
Фоновое изображение
.hero {
background-image: url("images/hero.jpg");
background-repeat: no-repeat;
background-position: center;
background-size: cover;
}background-size
.element {
background-size: auto;
background-size: cover;
background-size: contain;
background-size: 300px 200px;
}cover— заполняет область, при необходимости обрезая изображение.contain— полностью помещает изображение, но может оставить свободное место.
background-position
.element {
background-position: center;
background-position: top right;
background-position: 50% 25%;
}linear-gradient()
.banner {
background-image: linear-gradient(
135deg,
#2563eb,
#7c3aed
);
}Полупрозрачный слой поверх изображения:
.hero {
background-image:
linear-gradient(rgb(0 0 0 / 60%), rgb(0 0 0 / 60%)),
url("images/hero.jpg");
background-position: center;
background-size: cover;
}Типографика
font-family
body {
font-family: Arial, sans-serif;
}Если имя шрифта содержит пробелы, оно заключается в кавычки:
body {
font-family: "Open Sans", sans-serif;
}Стек шрифтов
Браузер последовательно ищет доступный шрифт:
body {
font-family:
Inter,
Arial,
Helvetica,
sans-serif;
}В конце рекомендуется указывать обобщённое семейство:
sans-serif;serif;monospace;cursive;fantasy;system-ui.
Системный стек:
body {
font-family:
system-ui,
-apple-system,
"Segoe UI",
sans-serif;
}Основные свойства
.text {
font-size: 1rem;
line-height: 1.5;
font-weight: 400;
letter-spacing: 0.01em;
}| Свойство | Назначение |
|---|---|
font-size |
Размер шрифта |
line-height |
Высота строки |
font-weight |
Насыщенность шрифта |
letter-spacing |
Расстояние между символами |
Для основного текста часто используют безразмерный line-height:
body {
line-height: 1.5;
}Он вычисляется относительно размера шрифта каждого элемента.
Типичные значения font-weight:
.text {
font-weight: 400;
}
.title {
font-weight: 700;
}Доступные значения зависят от подключённого шрифта.
@font-face
Позволяет подключить локальный файл шрифта:
@font-face {
font-family: "Inter";
src: url("fonts/inter-regular.woff2") format("woff2");
font-style: normal;
font-weight: 400;
font-display: swap;
}
@font-face {
font-family: "Inter";
src: url("fonts/inter-bold.woff2") format("woff2");
font-style: normal;
font-weight: 700;
font-display: swap;
}Использование:
body {
font-family: "Inter", Arial, sans-serif;
}font-display: swap разрешает временно показывать текст системным шрифтом, пока загружается основной.
display и поток документа
В обычном потоке элементы располагаются в порядке, в котором они записаны в HTML.
display: block
Блочный элемент обычно занимает всю доступную ширину и начинается с новой строки:
section {
display: block;
}Для блочных элементов работают width, height, вертикальные margin и padding.
display: inline
Строчный элемент располагается внутри строки:
span {
display: inline;
}Для обычных строчных элементов width и height не задают размер так же, как у блоков.
display: inline-block
Элемент располагается в строке, но принимает размеры и отступы как блок:
.badge {
display: inline-block;
padding: 4px 8px;
width: 120px;
}display: none
Полностью удаляет элемент из визуального потока:
.hidden {
display: none;
}Элемент не занимает место и обычно недоступен для вспомогательных технологий.
visibility: hidden
Скрывает элемент, но сохраняет занимаемое им место:
.invisible {
visibility: hidden;
}Схлопывание пробелов
В обычном HTML несколько пробелов и переносов строк отображаются как один пробел:
<p>
Один два
три
</p>На странице текст обычно будет выглядеть так:
Один два триПоведение регулирует white-space:
.text {
white-space: normal;
}
.code {
white-space: pre;
}
.no-wrap {
white-space: nowrap;
}
.multiline {
white-space: pre-wrap;
}Позиционирование
Свойство position определяет способ размещения элемента.
static
Значение по умолчанию:
.element {
position: static;
}Свойства top, right, bottom и left обычно не влияют на статический элемент.
relative
Элемент остаётся в обычном потоке, но может быть визуально смещён:
.element {
position: relative;
top: 10px;
left: 20px;
}Исходное место элемента сохраняется.
position: relative также часто задаёт систему координат для абсолютно позиционированных потомков.
absolute
Элемент исключается из обычного потока:
.card {
position: relative;
}
.card__badge {
position: absolute;
top: 8px;
right: 8px;
}Абсолютный элемент позиционируется относительно ближайшего предка, у которого position отличается от static. Если такого предка нет, позиционирование выполняется относительно начального содержащего блока.
fixed
Элемент исключается из потока и обычно фиксируется относительно окна браузера:
.chat-button {
position: fixed;
right: 24px;
bottom: 24px;
}Он остаётся на месте при прокрутке страницы.
sticky
Элемент ведёт себя как обычный до достижения указанной границы, после чего временно фиксируется:
.header {
position: sticky;
top: 0;
background-color: white;
}Для работы sticky необходимо указать хотя бы одну границу, например top: 0. На поведение также влияет прокручиваемый контейнер и его overflow.
inset
Краткая запись для координат:
.overlay {
position: absolute;
inset: 0;
}Эквивалентно:
.overlay {
top: 0;
right: 0;
bottom: 0;
left: 0;
}z-index
Управляет порядком наложения элементов:
.modal {
position: fixed;
z-index: 1000;
}Элемент с большим z-index обычно отображается поверх элемента с меньшим значением, если они находятся в сопоставимых контекстах наложения.
Стекинг-контекст
Стекинг-контекст — независимая область управления слоями. z-index дочернего элемента не может вывести его за пределы контекста родителя.
Новый стекинг-контекст могут создавать:
- корневой элемент;
- позиционированный элемент с
z-index, отличным отauto; position: fixedилиsticky;opacityменьше1;transform, отличный отnone;- некоторые значения
filter,isolationи других свойств.
.parent {
position: relative;
z-index: 1;
}
.child {
position: absolute;
z-index: 9999;
}Даже большой z-index дочернего элемента действует внутри контекста .parent.
Размеры и переполнение
width и height
.card {
width: 320px;
height: 200px;
}Для адаптивных элементов часто используют:
.card {
width: 100%;
height: auto;
}Фиксированная высота для текстовых блоков может привести к переполнению, если содержимое увеличится.
Минимальные и максимальные размеры
.container {
width: 100%;
max-width: 1200px;
min-width: 320px;
}.panel {
min-height: 200px;
max-height: 600px;
}Типичный контейнер страницы:
.container {
width: min(100% - 32px, 1200px);
margin-inline: auto;
}overflow
Определяет поведение содержимого, которое не помещается:
.element {
overflow: visible;
overflow: hidden;
overflow: auto;
overflow: scroll;
}visible— содержимое выходит за границы.hidden— лишнее содержимое обрезается.auto— прокрутка появляется при необходимости.scroll— область прокрутки создаётся постоянно.
Можно управлять осями отдельно:
.table-wrapper {
overflow-x: auto;
overflow-y: hidden;
}object-fit
Определяет, как изображение или видео помещается в заданную область:
.avatar {
width: 120px;
height: 120px;
object-fit: cover;
}| Значение | Поведение |
|---|---|
fill |
Растягивает содержимое без сохранения пропорций |
contain |
Полностью помещает содержимое |
cover |
Заполняет область с возможной обрезкой |
none |
Сохраняет исходный размер |
scale-down |
Выбирает меньший вариант между none и contain |
Положение содержимого задаёт object-position:
.photo {
object-fit: cover;
object-position: center top;
}aspect-ratio
Задаёт соотношение сторон:
.video {
width: 100%;
aspect-ratio: 16 / 9;
}Квадратная карточка:
.square {
aspect-ratio: 1;
}Пример адаптивного изображения:
.card__image {
display: block;
width: 100%;
aspect-ratio: 4 / 3;
object-fit: cover;
}Кастомные свойства и организация CSS
Кастомные свойства
CSS-переменные объявляются с префиксом --:
:root {
--color-primary: #2563eb;
--color-text: #1f2937;
--spacing-medium: 16px;
--border-radius: 8px;
}Использование через var():
.button {
color: white;
background-color: var(--color-primary);
padding: var(--spacing-medium);
border-radius: var(--border-radius);
}Резервное значение
.element {
color: var(--element-color, #333);
}Если --element-color не определена, будет использовано значение #333.
Область видимости
Кастомные свойства участвуют в наследовании:
:root {
--accent: blue;
}
.warning {
--accent: red;
}
.warning__title {
color: var(--accent);
}Внутри .warning переменная --accent будет равна red.
БЭМ-именование
БЭМ — методология именования CSS-классов: блок, элемент, модификатор.
<article class="card card--featured">
<img class="card__image" src="photo.jpg" alt="">
<h2 class="card__title">Заголовок</h2>
<p class="card__text">Описание карточки</p>
</article>.card {
padding: 16px;
}
.card__image {
width: 100%;
}
.card__title {
font-size: 1.5rem;
}
.card--featured {
border: 2px solid #2563eb;
}card— блок;card__title— элемент блока;card--featured— модификатор блока.
Не рекомендуется привязывать БЭМ-классы к структуре тегов:
/* Менее устойчивый вариант */
.card article h2 {
color: blue;
}
/* Более устойчивый вариант */
.card__title {
color: blue;
}Reset CSS
CSS Reset удаляет или переопределяет большую часть стандартных браузерных стилей:
* {
margin: 0;
padding: 0;
}
ul,
ol {
list-style: none;
}
button,
input,
textarea {
font: inherit;
}Полный сброс требует последующего явного оформления элементов.
Normalize.css
normalize.css не удаляет все стили, а приводит браузерные значения к более единообразному поведению.
Различие:
- Reset — максимально сбрасывает стандартное оформление.
- Normalize — сохраняет полезные стандартные стили и устраняет различия браузеров.
Минимальная базовая настройка:
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
}
body {
margin: 0;
min-height: 100vh;
font-family: system-ui, sans-serif;
line-height: 1.5;
}
img,
picture,
video {
display: block;
max-width: 100%;
}
button,
input,
textarea,
select {
font: inherit;
}Переходы и анимация
transition
Плавно изменяет значение CSS-свойства:
.button {
background-color: #2563eb;
transform: scale(1);
transition:
background-color 200ms ease,
transform 200ms ease;
}
.button:hover {
background-color: #1d4ed8;
transform: scale(1.05);
}Основные составляющие:
.element {
transition-property: transform;
transition-duration: 300ms;
transition-timing-function: ease;
transition-delay: 0ms;
}Краткая запись:
.element {
transition: transform 300ms ease 0ms;
}Не все CSS-свойства можно плавно анимировать. Например, переход от display: none к display: block обычным transition не выполняется.
Не рекомендуется без необходимости писать:
.element {
transition: all 300ms ease;
}Лучше явно перечислять изменяемые свойства.
transform
Трансформации меняют визуальное представление элемента, обычно не влияя на расположение соседей.
translate()
.element {
transform: translate(20px, 10px);
}Отдельно по осям:
.element {
transform: translateX(20px);
transform: translateY(-10px);
}Центрирование абсолютно позиционированного элемента:
.element {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}scale()
.element {
transform: scale(1.1);
}Значение больше 1 увеличивает элемент, а меньше 1 — уменьшает.
Несколько трансформаций можно объединять:
.element {
transform: translateY(-4px) scale(1.05);
}Порядок функций имеет значение.
@keyframes
Определяет этапы анимации:
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}То же самое в процентах:
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}animation
Применяет созданную анимацию:
.notification {
animation: fade-in 400ms ease-out;
}Полная запись:
.element {
animation-name: pulse;
animation-duration: 1s;
animation-timing-function: ease-in-out;
animation-delay: 0s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-fill-mode: both;
animation-play-state: running;
}Краткая запись:
.element {
animation: pulse 1s ease-in-out 0s infinite alternate both;
}Отключение анимации по настройкам пользователя
Пользователь может включить уменьшение движения в настройках системы:
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
scroll-behavior: auto;
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}Общий пример
Файл index.html:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Карточка товара</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<main class="page">
<article class="card card--featured">
<span class="card__badge">Новинка</span>
<img
class="card__image"
src="product.jpg"
alt="Описание товара"
>
<div class="card__content">
<h1 class="card__title">Название товара</h1>
<p class="card__description">
Краткое описание товара с его основными преимуществами.
</p>
<button class="button" type="button">
Добавить в корзину
</button>
</div>
</article>
</main>
</body>
</html>Файл styles.css:
:root {
--color-primary: #2563eb;
--color-primary-hover: #1d4ed8;
--color-text: #1f2937;
--color-surface: #fff;
--color-background: #f3f4f6;
--radius: 12px;
--shadow: 0 10px 25px rgb(0 0 0 / 10%);
}
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: 0;
color: var(--color-text);
background-color: var(--color-background);
font-family: system-ui, sans-serif;
line-height: 1.5;
}
.page {
display: grid;
min-height: 100vh;
padding: 24px;
place-items: center;
}
.card {
position: relative;
width: min(100%, 360px);
overflow: hidden;
background-color: var(--color-surface);
border-radius: var(--radius);
box-shadow: var(--shadow);
}
.card__badge {
position: absolute;
z-index: 1;
top: 12px;
right: 12px;
padding: 4px 8px;
color: white;
background-color: var(--color-primary);
border-radius: 999px;
font-size: 0.875rem;
}
.card__image {
display: block;
width: 100%;
aspect-ratio: 4 / 3;
object-fit: cover;
}
.card__content {
padding: 20px;
}
.card__title {
margin: 0 0 8px;
font-size: 1.5rem;
line-height: 1.2;
}
.card__description {
margin: 0 0 20px;
color: #4b5563;
}
.button {
display: inline-block;
width: 100%;
padding: 12px 20px;
color: white;
background-color: var(--color-primary);
border: 0;
border-radius: 8px;
font: inherit;
font-weight: 700;
cursor: pointer;
transition:
background-color 200ms ease,
transform 200ms ease;
}
.button:hover {
background-color: var(--color-primary-hover);
transform: translateY(-2px);
}
.button:focus-visible {
outline: 3px solid #93c5fd;
outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
.button {
transition: none;
}
}