HTML-рендеринг построен на основе блочной модели, но жизнь (и веб-дизайн) — это не только прямоугольники. CSS поддерживает множество способов изменения отображаемых областей элемента, предоставляя разработчикам свободу создавать дизайны с поддержкой любых форм и размеров. Обрезка позволяет использовать геометрические фигуры, а маскирование влияет на видимость на уровне пикселей.
Пути и формы
CSS использует функции для определения фигур. Общая информация о функциях представлена в модуле «Функции CSS» . В этом разделе вы узнаете, как создавать фигуры в CSS. Во всех следующих примерах используются фигуры, созданные с помощью свойства clip-path
, которое ограничивает видимую область только тем, что находится внутри фигуры. Это позволяет визуально отличать элементы от их рамки. Мы более подробно рассмотрим обрезку позже.
Фигуры, определенные в CSS, могут быть как базовыми фигурами (такими как круги, прямоугольники и многоугольники), так и контурами (которые могут определять сложные и составные фигуры).
Базовые формы
circle()
и ellipse()
Функции circle()
и ellipse()
определяют круглые и овальные фигуры с радиусами, заданными относительно элемента. Функция circle()
принимает в качестве аргумента один размер или процентное значение. По умолчанию обе функции позиционируют фигуру относительно центра элемента. Обе принимают необязательное значение позиции после ключевого слова at
, которое может быть выражено длиной, процентным значением или ключевыми словами, указывающими положение.
.my-element {
width: 60px;
height: 60px;
background: blue;
clip-path: circle(50%);
}
В предыдущем примере показана круговая обрезка с использованием функции circle()
. Обратите внимание, что радиус 50%
создаёт круг, охватывающий всю ширину элемента. Функция ellipse()
принимает два аргумента, представляющие горизонтальный и вертикальный радиусы фигуры.
.my-element {
width: 60px;
height: 60px;
background: blue;
clip-path: ellipse(50% 25%);
}
В предыдущем примере показан эллиптический контур обрезки с использованием функции ellipse()
. Обратите внимание, что радиус 50% создаёт эллипс по всей ширине элемента. В следующем примере тот же эллипс показан с центром в верхней части элемента.
.my-element {
width: 60px;
height: 60px;
background: blue;
clip-path: ellipse(50% 25% at center top);
}
rect()
и inset()
Функции rect()
и inset()
предоставляют различные способы определения прямоугольника, устанавливая положение его сторон относительно сторон элемента. Это позволяет создавать прямоугольники, визуально отличающиеся от рамки элемента по умолчанию. Они также могут принимать ключевое слово round
для создания прямоугольника со скругленными углами, используя тот же синтаксис, что и для сокращённого свойства border-radius
.
Функция rect()
определяет положение верхней и нижней сторон прямоугольника относительно верхнего края элемента, а также левой и правой сторон относительно левого края элемента. Эта функция принимает четыре единицы измерения или процентные значения в качестве аргументов, определяющих верхнюю, правую, нижнюю и левую стороны. Функцию rect()
можно использовать, если вам нужен прямоугольник, который не масштабируется при изменении размера элемента или сохраняет пропорции при его изменении.
.my-element {
width: 80px;
height: 60px;
background: blue;
clip-path: rect(15px 75px 45px 10px);
}
В предыдущем примере показан прямоугольный контур обрезки, заданный с помощью функции rect()
. Размеры указаны относительно верхнего и левого краев элемента, как показано на схеме.
Функция inset()
определяет положение сторон прямоугольника, исходя из расстояния от каждой из сторон элемента внутрь. Эта функция принимает от одной до четырёх единиц размера или процентов в качестве аргументов, что позволяет определить сразу несколько сторон. Функцию inset()
можно использовать, если вам нужен прямоугольник, масштабируемый вместе с элементом, или прямоугольник с фиксированным расстоянием от его краёв.
.my-element {
width: 80px;
height: 60px;
background: blue;
clip-path: inset(15px 5px 15px 10px);
}
В предыдущем примере показан прямоугольный контур обрезки, заданный с помощью функции inset()
. Размеры указаны относительно сторон элемента.
Функции rect()
и inset()
могут опционально принимать ключевое слово round
для создания прямоугольника со скруглёнными углами, используя тот же синтаксис, что и для сокращённого свойства border-radius
. В следующем примере показаны скруглённые версии показанных ранее прямоугольников.
.rounded-rect {
width: 80px;
height: 60px;
background: blue;
clip-path: inset(15px 5px 15px 10px round 5px);
}
.rounded-inset {
width: 80px;
height: 60px;
background: blue;
clip-path: inset(15px 5px 15px 10px round 5px);
}
polygon()
Для других фигур, таких как треугольники, пятиугольники, звезды и т. д., функция polygon()
позволяет создавать фигуры, соединяя несколько точек прямыми линиями. Функция polygon()
принимает список пар, состоящий из двух единиц длины или процентов. Каждая пара описывает точку многоугольника: первое значение — это расстояние от левого края элемента, второе — расстояние от верхнего края элемента. Замыкать многоугольник не нужно, так как он будет завершён соединением последней точки с первой.
.my-element {
width: 60px;
height: 60px;
background: blue;
clip-path: polygon(
50% 0,
0 100%,
100% 100%
);
}
В предыдущем примере создается треугольный контур обрезки путем определения трех точек.
По умолчанию функция polygon()
отображает перекрывающиеся области как заполненные. Вы можете изменить это поведение с помощью необязательного первого аргумента, называемого правилом заливки. Чтобы чередовать заполненные и незаполненные области, установите для правила заливки значение evenodd
. Чтобы использовать правило заливки по умолчанию, установите для него значение nonzero
.
В предыдущем примере показана функция polygon()
с тригонометрическими функциями для создания правильных многоугольников и звёздчатых фигур. Это не создаёт максимально возможный правильный многоугольник, помещающийся внутри элемента, и не центрирует его — мы оставим это в качестве упражнения. Звёздчатые фигуры в этом примере также демонстрируют правила заливки nonzero
и evenodd
.
Сложные формы
Когда базовых функций для описания сложной фигуры недостаточно, CSS предлагает функции с более сложным синтаксисом для описания таких объектов, как кривые и линии. Эти функции также полезны для сложных фигур (фигур, состоящих из нескольких частей, например, круга с отверстием).
path()
Функция path()
принимает строку синтаксиса SVG-контура для описания фигуры. Это позволяет создавать сложные фигуры с помощью инструкций, описывающих линии и кривые, составляющие фигуру. Редактирование синтаксиса SVG может быть сложным, поэтому мы рекомендуем использовать специальный визуальный редактор, который может экспортировать синтаксис при создании фигур с помощью функции path()
.
Функция path()
не использует единицы измерения размера CSS, и все значения интерпретируются как пиксели. Это означает, что фигуры, созданные с помощью функции path, не реагируют на размер элемента или контейнера. Мы рекомендуем использовать path()
только для фигур с фиксированными размерами.
shape()
Функция shape()
использует синтаксис команд для описания фигуры, аналогичный функции path()
. Однако команды функции shape()
являются нативными для CSS и могут использовать единицы измерения CSS. Это позволяет адаптивно изменять размер фигур, заданных с помощью функции shape()
.
В предыдущем примере функции path()
и shape()
используются для определения формы сердца и круга с отверстием в центре. В примере для обеих функций используется одно и то же значение в пикселях, но функции shape()
могли бы использовать и другие единицы измерения размера CSS, например, проценты или единицы измерения относительно контейнера.
Вырезка
Отсечение определяет видимые области элемента, подобно отсечению изображения из журнала. Свойство clip-path
задаёт путь, используемый для определения области отсечения.
Как вы видели в примерах в предыдущем разделе, в качестве clip-path
можно использовать любую базовую функцию формы или пути. Свойство clip-path
также поддерживает пути, определённые в элементе SVG clipPath
, который может быть встроен или находиться в отдельном файле.
На предыдущей диаграмме показано, как добавление clip-path
к элементу изображения изменяет видимую область изображения. Верхний clip-path использует функцию circle()
, а нижний — функцию SVG clipPath
. Обратите внимание, что окружность, созданная с помощью функции circle()
по умолчанию располагается по центру элемента.
Свойство clip-path
принимает только один контур. Чтобы обрезать элемент с несколькими неперекрывающимися фигурами, используйте функции path()
или shape()
для определения составного контура или используйте SVG- clipPath
. Другой вариант для сложных сценариев — использовать маскирование вместо обрезки, о чём мы поговорим в следующем разделе.
Обрезка с помощью фигур
Чтобы выполнить обрезку с помощью базовой функции формы или пути, установите свойство clip-path
равным значению, возвращаемому функцией, как в предыдущих примерах. Каждая функция будет по-разному позиционировать обрезаемую фигуру относительно элемента, поэтому обратитесь к справочному руководству по каждой функции.
В предыдущем примере к двум элементам применен круговой clip-path
с помощью класса .clipped
. Обратите внимание, что clip-path
позиционируется относительно каждого элемента, и текст внутри clip-path
не перестраивается в соответствии с формой.
Справочное поле обтравочного контура
По умолчанию контур обрезки элемента включает его границу. При использовании одной из базовых функций формы можно задать опорный блок контура обрезки так, чтобы он включал только область элемента внутри границы. Допустимые значения для опорного блока: stroke-box
(по умолчанию) и fill-box
(включает только область внутри границы).
В предыдущем примере показаны элементы с большой ( 20px
) рамкой, каждый из которых использует функцию inset()
для установки clip-path
. Элемент, обрезаемый относительно границы элемента, всё ещё отображает часть рамки. Элементы, обрезаемые относительно области внутри рамки, не отображают рамку и имеют меньший размер, даже при одинаковом значении inset.
Вырезание с графикой
Обтравочный контур может быть определён в SVG-документе, либо встроен в HTML-документ, либо указан как внешняя ссылка. Это может быть полезно для определения сложных обтравочных контуров, созданных в графических программах, или обтравочных контуров, объединяющих несколько фигур.
<img id="kitten" src="kitten.png">
<svg>
<defs>
<clipPath id="kitten-clip-shape">
<circle cx="130" cy="175" r="100" />
</clipPath>
</defs>
</svg>
<style>
#kitten {
clip-path: url(#kitten-clip-shape);
}
</style>
В предыдущем примере clipPath
с id
kitten-clip-shape
применяется к элементу <img>
. В этом случае SVG-документ встроен в HTML. Если SVG-документ — это внешний файл с именем kitten-clipper.svg
, то clipPath
будет указываться как url(kitten-clipper.svg#kitten-clip-shape)
.
Маскировка
Маскирование — это ещё один метод определения отображаемых или скрытых областей элемента. В то время как обрезка использует базовые фигуры или контуры, маскирование определяет видимость с помощью пикселей изображения или градиента. В отличие от обрезки, маскирование позволяет сделать области элемента частично прозрачными. К элементу можно применить несколько изображений-масок для создания различных эффектов.
Чтобы применить маску, задайте свойство mask-image
. Это свойство принимает одно или несколько изображений, градиентов или ссылок на элементы <mask>
в документе SVG. Можно применить несколько изображений-масок, разделив их запятыми.
.my-element {
mask-image: url(my-mask.png),
linear-gradient(black 0%, transparent 100%);
}
В предыдущем примере .my-element
маскируется с помощью PNG-изображения, за которым следует линейный градиент. По умолчанию несколько масок суммируются для создания итоговой маски.
В предыдущем примере показано изображение с одной или несколькими примененными масками. Переключайте каждую маску, чтобы увидеть, как они суммируются, создавая конечный эффект.
Альфа и яркостное маскирование
Маску можно применить, используя либо alpha
, либо luminance
изображения. При маскировании по alpha
каналу к элементу применяется прозрачность каждого пикселя изображения маски, игнорируя цветовую информацию об этом пикселе. При маскировании по luminance
к элементу применяются как прозрачность, так и значение каждого пикселя (насколько ярким или тёмным). При маскировании по яркости более яркие цвета рассматриваются как видимые, а более тёмные — как невидимые.
Чтобы задать режим маскирования, используйте свойство mask-mode
. По умолчанию свойство mask-mode
имеет значение match-source
, которое задаёт режим на основе типа изображения маски. Для изображений и градиентов по умолчанию используется значение alpha
. Для масок SVG по умолчанию используется либо значение свойства mask-type
элемента <mask>
, либо luminance
, если свойство mask-type
не определено.
В предыдущем примере тестовый шаблон с различными значениями цвета и альфа-канала используется в качестве маски. Переключая mask-mode
, можно увидеть, что режим alpha
основан на прозрачности, а режим luminance
— как на яркости цвета, так и на прозрачности.
Дополнительные маскирующие свойства
CSS предоставляет дополнительные свойства для точной настройки поведения масок. Каждое свойство принимает список значений, разделённых запятыми, который будет сопоставляться со списком масок, заданным свойством mask-image
. Если значений меньше, чем масок, список будет повторяться, пока не будет установлено значение для каждой маски. Если значений больше, чем масок, все лишние значения отбрасываются.
Свойство | Описание |
---|---|
mask-clip | Устанавливает, к какому ссылочному полю применяются маски элементов. По умолчанию — |
mask-composite | Устанавливает взаимодействие между масками при применении нескольких масок к одному элементу. По умолчанию |
mask-origin | Задаёт опорный блок, который служит точкой отсчёта для маски. По умолчанию — |
mask-position | Устанавливает положение маски относительно |
mask-repeat | Устанавливает способ повторения маски, если маскируемый элемент больше маски. Значение по умолчанию — |
mask-size | Устанавливает, как изменяется размер маски относительно размера маскируемого элемента. Значение по умолчанию — |
Стенография маски
С помощью сокращённой записи «mask» можно задать сразу несколько свойств маски. Это упрощает настройку нескольких масок, группируя все свойства каждой маски вместе. Сокращённая запись «mask» эквивалентна заданию этих свойств по порядку: mask-image
, mask-mode
, mask-position
, mask-size
, mask-repeat
, mask-origin
, mask-clip
и mask-composite
. Не все свойства обязательно должны быть включены, и все невключённые будут сброшены до своих начальных значений. Поддержка до восьми свойств для одной маски позволяет иметь полный справочник .
.longhand {
mask-image: linear-gradient(white, black),
linear-gradient(90deg, black, transparent);
mask-mode: luminance, alpha;
mask-position: bottom left, top right;
mask-size: 50% 50%, 30% 30%;
}
.shorthand {
mask: linear-gradient(white, black) luminance bottom left / 50% 50%,
linear-gradient(90deg, black, transparent) alpha top right / 30% 30%;
}
В предыдущем примере к каждому классу применены две маски. Первая использует отдельные свойства, а вторая — сокращённую запись mask
. Оба стиля эквивалентны друг другу.
Обтекаемый текст вокруг плавающих элементов
При обрезке или маскировании элемента изменяется только видимая область внутри его рамки, но сама рамка остаётся неизменной. Это означает, что плавающий элемент будет влиять на обтекание документа, основываясь на его исходной ограничивающей рамке, а не на видимых частях элемента. Чтобы определить обтекание элемента, используйте свойство shape-outside
вместе с контуром обрезки.
Свойство shape-outside
определяет форму, которую контент будет обтекать вокруг элемента. Эта форма может быть любой из базовых функций формы, но не может быть задана с помощью функций path()
или shape()
, а также не может быть задана с помощью clipPath
в документе SVG.
Свойство shape-outside
также принимает изображение или градиент. Как и в случае с маскированием, границы фигуры определяются прозрачностью изображения или градиента. Свойство shape-image-threshold
задаёт уровни прозрачности, учитываемые внутри фигуры.
Формы в анимации
Анимация клип-траектории
Вы можете анимировать свойство clip-path
, переходя от одной формы к другой. Для получения плавной анимации необходимо использовать одну и ту же функцию shape для каждого ключевого кадра. При использовании функций polygon()
или shape()
в каждом ключевом кадре должно быть одинаковое количество точек.
В предыдущем примере clip-path
элемента переходит из формы пятиугольника в форму звезды, заданную с помощью функции polygon()
. В примере используется правило заливки evenodd
, чтобы показать, как анимационные точки создают перекрывающиеся области.
Анимация с помощью offset-path
Вы также можете анимировать элементы вдоль траекторий, созданных с помощью этих функций формы. Свойство offset-path
задаёт форму, используемую в качестве траектории, а offset-distance
— положение вдоль этой траектории. Вы также можете использовать функцию ray()
со свойством offset-path
для анимации вдоль прямой линии.
В предыдущем примере показано использование одного и того же полигона как для clip-path
, так и для offset-path
. Анимация использует offset-distance
для перемещения меньших звёзд вдоль , используя тот же полигон, который большая звезда использует в качестве clip-path
.
Проверьте свое понимание
Какие из следующих функций формы являются допустимыми?
circle()
square()
hexagon()
polygon()
rectangle()
inset()
Верно или неверно: Формы, заданные с помощью функции path()
можно определить с помощью процентов.
Верно или неверно: установка контура обрезки элемента не изменит обтекание элемента текстом.
Какой из следующих вариантов можно использовать в качестве контура обрезки?
clipMask
Что из перечисленного можно использовать в качестве маски?
circle()
или rect()