Используйте shape() для адаптивного обрезки

Опубликовано: 8 апреля 2025 г.

Свойство clip-path позволяет изменить форму элемента, обрезав его до круга, многоугольника или даже пути SVG. Однако до Chrome 135 и Safari 18.4 вам приходилось выбирать между адаптивными многоугольниками и более сложными фигурами, которые не реагируют на использование путей SVG. С помощью новой функции shape() clip-path может обрезать элемент до формы, не являющейся многоугольником, которая также является адаптивной.

Browser Support

  • Хром: 135.
  • Край: 135.
  • Предварительная версия технологии Firefox: поддерживается.
  • Сафари: 18.4.

Source

Создайте форму флага

В качестве примера сравните создание формы флага с помощью clip-path: path() и clip-path: shape() .

Форма зеленого флага с изогнутыми линиями вверху и внизу.

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

Создайте флаг с помощью clip-path: path()

Форму, подобную этому флагу, можно представить с помощью пути SVG:

.flag {
  clip-path: path(
    "M 0 20 \
     C 25 0 75 40 100 20 \
     V 80 \
     C 75 100 25 60 0 80 \
     z");
}

Чтобы разобраться в этом, путь SVG представляет собой серию команд пути:

  1. Переместитесь на 0, 20.
  2. Постройте кривую до 100, 20, используя контрольные точки (25,0 и 75, 40).
  3. Вертикальная линия до 80.
  4. Кривая до 0, 80, используя контрольные точки (75,100 и 25,50).
  5. Закройте путь (линия до 0,20).

Это рисует форму флага, но все единицы измерения указаны в пикселях. SVG может масштабировать эти пиксели в поле просмотра, но таким образом, чтобы это всегда выглядело как геометрический масштаб всей фигуры.

Например, если вы хотите, чтобы весь прямоугольник масштабировался, но сохранял высоту и ширину кривых 20 пикселей, SVG не справился бы с этой задачей.

Создайте флаг с помощью shape()

Сравните тот же результат, используя shape() . Функция shape принимает ряд команд, аналогичных командам пути SVG. Однако эти команды принимают длины и проценты CSS в любых единицах CSS.

Следующий CSS преобразует флаг shape() в процентные единицы:

.flag {
  clip-path: shape(from 0% 20%,
     curve to 100% 20% with 25% 0% / 75% 40%,
     vline to 80%,
     curve to 0% 80% with 75% 100% / 25% 60%,
     close
  );
}

Сделайте его отзывчивым

Имея полный диапазон доступных длин CSS, вы можете выбрать, какие из них использовать для каждой координаты.

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

.flag {
  clip-path: shape(from 0% 20px,
     curve to 100% 20px with 25% 0% / 75% 40px,
     vline to calc(100% - 20px),
     curve to 0% calc(100% - 20px) 
           with 75% 100% / 25% calc(100% - 40px),
     close
  );
}

Добавляйте пользовательские свойства и анимацию

Теперь, когда форма определена в CSS, вы также можете использовать пользовательские свойства, чтобы упростить управление высотой:

.flag {
  --wave-height: 40px;
  clip-path: shape(
    from 0px var(--wave-height),
    curve to 100% var(--wave-height) 
          with 25% 0px / 75% calc(var(--wave-height) * 2),
    vline to calc(100% - var(--wave-height)),
    curve to 0 calc(100% - var(--wave-height))
          with 75% 100% / 25% calc(100% - var(--wave-height) * 2),
    close
  )
}

Вы даже можете анимировать свойство CSS, используя дескриптор @property , и зафиксировать его, чтобы оно не выходило за рамки:

@property --animated-wave-height {
  syntax: "<length>";
  inherits: false;
  initial-value: 40px;
}

@keyframes curve {
  from { --animated-wave-height: 0px; }
  to { --animated-wave-height: 180px; }
}

.flag {
  width: 600px;
  height: 400px;
  background: green;
  animation: curve 1s infinite alternate;
  --wave-height: calc(min(var(--animated-wave-height, 40px), 40%));
  clip-path: shape(
    from 0px var(--wave-height),
    curve to 100% var(--wave-height)
          with 25% 0px / 75% calc(var(--wave-height) * 2),
    vline to calc(100% - var(--wave-height)),
    curve to 0 calc(100% - var(--wave-height)) 
          with 75% 100% / 25% calc(100% - var(--wave-height) * 2),
    close
  )
}

Попробуйте демо

В Chrome 135 или Safari 18.4 вы можете увидеть форму анимационного флага, созданную с помощью clip-path: shape() в этой демонстрации CodePen .

Краткое содержание

clip-path: shape() позволяет обрезать элемент, используя произвольные и адаптивные формы, что ранее было возможно только с использованием таких методов, как конические градиенты или SVG, созданный на JavaScript.

Полный синтаксис см. в спецификации .

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