Pull to refresh
88.83
Skillfactory
Онлайн-школа IT-профессий

Как понять свойство clip-path в CSS

Reading time7 min
Views58K
Original author: Ahmad Shadeed
В те далёкие времена, когда я впервые столкнулся со свойством CSS clip-path, мне потребовалось больше времени, чем я ожидал, и я изо всех сил старался запомнить, как работает свойство. Не знаю точно, почему так получилось, но, может быть, потому, что я не пользовался им часто? Во всяком случае, я изучу его снова вместе с вами. В этой статье я стремлюсь дать чёткое, детальное объяснение того, как работает clip-path, когда его использовать и как вы можете воспользоваться им в своих проектах веб-разработки. Вы готовы?



Вступление


Свойство clip-path создаёт область отсечения: внутри неё контент видно, а вне её – нет. Вот простой пример круга с применением clip-path.

.card {
  background-color: #77cce9;
  clip-path: circle(80px at 50% 50%);
}


Когда применяется clip-path, видимой областью оказывается только синий круг. Мы не видим ничего за пределами круга. Вот анимация, которая показывает отсечение круга из примера выше:


Система координат


Прежде чем углубляться в детали clip-path, стоит упомянуть о том, как работает система координат. Начало координат – это верхний левый угол, ось x направлена вправо, а ось y – вниз.

Учитывая это, чтобы увидеть, как обрезается элемент, давайте возьмём простой пример. В нём обрезанная область – это круг размером 100 px, его центр расположен в точке 0,0 (вверху слева).


Обратите внимание, что пользователь видит только выделенную тёмно синюю область. Оставшаяся часть круга обрезана. Вопрос в том, как сделать видимым весь круг? Для этого нужно изменить точки осей x и y.


Центр круга расположен в 100 px левее и 100 px выше. Теперь, когда вы понимаете, как работает система координат, я расскажу о возможных значениях свойства clip-path.

Значения clip-path


inset


Значение inset определяет вставляемый прямоугольник. Мы можем контролировать четыре края, точно так же, как это делается с краями или отступом. В примере ниже .card имеет свойство inset 20px со всех  краёв (сверху, справа, снизу и слева).

.card {
  clip-path: inset(20px);
}

Если нужно, подправьте inset с одного из краёв. Вот пример, как это сделать:

.card {
  clip-path: inset(20 px 20 px 50 px 20 px);
}


Выше класс .card имеет свойство inset со значением 50px снизу.

Вопрос в том, возможна ли округлая вставка? Да! Благодаря ключевому слову round. Добавление ключевого слова слева от радиуса округляет углы, вот так: round <border-radius>.

.card {
  clip-path: inset(20px 20px 50px round 15px);
}


Кроме того, мы даже можем настроить радиус каждой стороны отдельно. Вот пример с нулевым радиусом верхнего правого и нижнего левого углов.
.card {
  clip-path: inset(20px 20px 50px round 15px 0);
}

circle()


Чтобы использовать значение circle(), нам понадобится радиус и его положение. Вот пример:

.card {
  clip-path: circle(80px at 50% 50%);
}

Радиус окружности равен 80px, и она позиционирована так: 50% на оси x, 50% на оси y.

ellipse()


С помощью функции ellipse() мы можем установить ширину и высоту, чтобы сделать отсечение овальным.

.card {
  clip-path: ellipse(100px 80px at center);
}


polygon()


Самое интересное для меня значение – polygon(). Можно управлять несколькими наборами значений по осям x и y.

.card {
  clip-path: polygon(x y, x y, x y, x y);
}

Вот пример, где polygon() используется, чтобы обрезать прямоугольник. Обратите внимание, что я сопоставил каждый набор точек с его координатами на осях.

.card {
  clip-path: polygon(5% 5%, 95% 5%, 95% 95%, 5% 95%);
}


Используя значение polygon(), можно рисовать сложные фигуры с несколькими точками.

path()


Значение path() позволяет использовать элемент SVG, чтобы обрезать определённую область. Сейчас его поддержка браузером непоследовательна. Чтобы заставить это свойство работать в разных браузерах, нам нужно использовать встроенный SVG, а затем функцию url() как значение для clip-path.

<svg class="svg">
  <clipPath id="triangle" clipPathUnits="objectBoundingBox">
    <path d="M0.05,0.05 h1 v1"></path>
  </clipPath>
</svg>

В коде CSS нужно добавить путь к clipPath при помощи url().

.card {
  clip-path: url("#triangle");
}


Теперь, когда мы рассмотрели теорию clip-path и возможные значения этого свойства, пришло время воспользоваться свойством по-настоящему и исследовать некоторые варианты его применения. Вы готовы?

Примеры применения


Эффект разворота плоскости


Так или иначе, нечто с подобной структурой вы уже видели. Это идеальный пример того, как использовать clip-path.
image

Можете ли вы предположить, как реализовать поворот? Здесь поможет polygon().

.section {
  clip-path: polygon(0 0, 100% 0, 100% 80%, 0 100%);
}

Иногда надоедает прописывать 8 значений полигона. На этот случай у меня есть для вас небольшой трюк: пусть положение точек зависит от браузера. Во-первых, добавим такой код:

.section {
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}

Исследуем эту часть с помощью DevTools. Открыв «Исследовать элемент», обратите внимание на маленький значок полигона в левой части значения polygon().


Нажав его, вы сможете отредактировать полигон в браузере. Посмотрите картинку ниже:



Угол относительно ширины видового экрана


Можно воспользоваться функцией calc() вместе с единицами viewport, чтобы угол зависел от ширины видового экрана. Я узнал об этом из замечательной статьи Килиана Валькхофа.

.section {
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 5vw), 0 100%);
}

Несколько углов


У меня в голове возник вопрос: захочется ли нам иметь несколько угловых секций? Посмотрите на рисунок ниже.


Первое, о чем я подумал, – просто добавить box-shadow или border. К сожалению, они будут обрезаны, так что, даже если добавить их, мы не увидим того, что хотим увидеть. Решение в таком случае – использовать несколько элементов, причём точка отсечения будет у каждого своя:

<div class="hero">
  <img src="bg.jpg" alt="" />
</div>

.hero {
  position: relative;
  min-height: 350px;
}

.hero img {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  clip-path: polygon(0 0, 100% 0, 100% 80%, 0 90%);
}

.hero:after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -20%;
  z-index: -1;
  width: 100%;
  height: 100%;
  background-color: #4545a0;
  clip-path: polygon(0 0, 100% 0, 100% 80%, 0 90%);
}

У нас есть псевдоэлемент с тем же размером и clip-path, что и у другого элемента. Разница в том, что он расположен под ним с bottom:-20% и z-index:-1. Я написал значение 20%, потому что это то же, что 100 − 80.

Появление при прокрутке


Используя API IntersectionObserver, мы можем проявлять определённые элементы на странице во время прокрутки.

Значение inset


Самое полезное значение clip-path для этого эффекта – inset. Почему? Посмотрите на рисунок ниже.


Обратите внимание, что синий прямоугольник может стать полностью невидимым, если написать inset(50%). Да, значение, которое сделает элемент невидимым, составляет 50%: мы применяем inset с четырёх сторон. Другими словами, inset применяется от края к центру прямоугольника. На рисунке ниже inset используется для показа изображений во время прокрутки:


Приведённый ниже код javascript добавляет класс is-visible к каждому изображению, которое находится в области просмотра. При этом мы можем увидеть изображение с помощью прокрутки.

const images = document.querySelectorAll("img");

function check(entries) {
  entries.map((entry) => {
    if (entry.isIntersecting) {
      entry.target.classList.add("is-visible");
      observer.unobserve(entry.target);
    }
  });
}

const observer = new IntersectionObserver(check);
images.forEach((image) => observer.observe(image));


img {
  clip-path: inset(50%);
  transition: 1.2s ease-in;
}

img.is-visible {
  clip-path: inset(0);
}

Всё просто. Мы создали простой эффект прокрутки с помощью нескольких строк CSS и JavaScript.


Кроме того, возможно контролировать направление перехода появления. Для этого нам нужно использовать одно из четырёх значений. Например, если нам нужен переход сверху вниз, нижнее значение должно быть изменено со 100% на 0. Посмотрите на картинку с объяснением:



А вот интерактивная демонстрация:


Эффекты наведения и анимации


clip-path – это безграничные возможности, чтобы создавать анимации. Вот ещё один пример:


Что нам нужно сделать – это добавить эффект наведения, который масштабируется из уже указанной позиции. Здесь давайте выберем значение circle().

Чтобы код поддерживался и читался проще, давайте воспользуемся переменными CSS. Так нам не нужно дублировать весь clip-path. Изменим только необходимые переменные CSS.

:root {
  --pos: left center;
  --size: 0;
}

.stats__item:before {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background-color: #7777e9;
  clip-path: circle(var(--size) at var(--pos));
  transition: 0.4s linear;
}

.stats__item:hover:before {
  --size: 300px;
}

Посмотрите ниже как это работает.


Мало того, мы можем очень легко изменить положение анимации. Я создал интерактивную демонстрацию, где можно изменять позиции в выпадающем меню.


Если вам захотелось углубиться в эффекты анимации, мистер Адам Аргайл написал крайне полезную библиотеку анимации CSS, которая абсолютно полностью полагается на clip-path. Вот она.

Эффект пульсации


Эффект ряби обрёл популярность с релиза Material Design. С помощью clip-path этот эффект легко воспроизводится, вот так:


<button class="button"><span>Sign up now</span></button>

.button {
  position: relative;
}

.button span {
  position: relative;
  z-index: 1;
}

.button:before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background-color: #fff;
  opacity: 0.1;
  clip-path: circle(0 at center);
  transition: 0.3s ease-out;
}

.button:hover:before {
  clip-path: circle(100px at center);
}



Полезно знать


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

Можно пользоваться относительными значениями.
Хочется привязать позицию clip-path к font-size? Это можно сделать! Воспользуйтесь единицами em или rem для clip-path – и всё готово.

Ресурсы и связанные статьи



Я рад сообщить вам, что написал электронную книгу об отладке CSS. Если вам интересно, отправляйтесь на debuggingcss.com, чтобы прочитать бесплатный фрагмент. Если вам нравится мой контент, то вы можете поддержать меня, заплатив за мой кофе. Большое спасибо!



image



Tags:
Hubs:
+11
Comments2

Articles

Information

Website
www.skillfactory.ru
Registered
Founded
Employees
501–1,000 employees
Location
Россия
Representative
Skillfactory School