← HTML & CSS/Clip-path и маски: нестандартные формы#36 из 383← ПредыдущийСледующий →+15 XP
Полезно по теме:Гайд: старт в frontendПрактика: DOM и событияТермин: DOMМаршрут: старт с нуля

Clip-path и маски: нестандартные формы

Не все элементы дизайна — прямоугольники. Hexagon-аватары, диагональные секции, звёздные рейтинги, волнообразные разделители — всё это делается через clip-path и mask-image.

clip-path — базовые формы

/* Круг: circle(radius at center-x center-y) */
.avatar {
  clip-path: circle(50%);                /* Круг по центру */
  clip-path: circle(40px at 50% 50%);   /* Явный радиус и центр */
}

/* Эллипс */
.ellipse {
  clip-path: ellipse(60px 40px at center);
}

/* Прямоугольник с закруглением */
.rounded-clip {
  clip-path: inset(10px 20px round 8px);
  /* inset(top right bottom left round radius) */
}

/* Полигон — произвольный многоугольник */
.triangle {
  clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}

.hexagon {
  clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
}

path() — SVG-путь в clip-path

.star {
  clip-path: path('M 50 0 L 61 35 L 98 35 L 68 57 L 79 91 L 50 70 L 21 91 L 32 57 L 2 35 L 39 35 Z');
}

path() принимает SVG path data. Мощно, но координаты абсолютные, а не процентные.

Анимация clip-path

.reveal {
  clip-path: inset(0 100% 0 0);         /* Полностью скрыт справа */
  transition: clip-path 0.6s ease;
}

.reveal.visible {
  clip-path: inset(0 0% 0 0);           /* Полностью виден */
}

/* Hover-эффект: квадрат → круг */
.card {
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
  transition: clip-path 0.4s ease;
}
.card:hover {
  clip-path: circle(50%);
}

mask-image — маски из градиентов и изображений

/* Gradient mask — fade out снизу */
.faded {
  mask-image: linear-gradient(to bottom, black 60%, transparent 100%);
}

/* Круговая маска */
.vignette {
  mask-image: radial-gradient(ellipse at center, black 60%, transparent 100%);
}

/* SVG-маска */
.shaped {
  mask-image: url(#my-svg-mask);
}

mask-composite

.complex-mask {
  mask-image: url(mask1.svg), url(mask2.svg);
  mask-composite: subtract;  /* add | subtract | intersect | exclude */
}

Творческие UI-эффекты

Диагональная секция сайта:

.diagonal-section {
  clip-path: polygon(0 0, 100% 0, 100% 85%, 0 100%);
  /* Нижний правый угол — 85%, нижний левый — 100% */
}

Волна:

.wave-section {
  clip-path: ellipse(100% 55% at 50% 45%);
}

Производительность

clip-path не вызывает перерасчёт layout — браузер просто маскирует уже нарисованный элемент. Анимация clip-path происходит на GPU через compositing, если анимируются только clip-path и transform/opacity.

Примеры

Генерация clip-path значений для разных форм и применение их к элементам

// Генератор clip-path для разных геометрических форм
function makeHexagon() {
  return 'polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%)'
}

function makeStar(points = 5) {
  const coords = []
  for (let i = 0; i < points * 2; i++) {
    const angle = (i * Math.PI) / points - Math.PI / 2
    const r = i % 2 === 0 ? 50 : 22  // внешний/внутренний радиус в %
    const x = 50 + r * Math.cos(angle)
    const y = 50 + r * Math.sin(angle)
    coords.push(`${x.toFixed(1)}% ${y.toFixed(1)}%`)
  }
  return `polygon(${coords.join(', ')})`
}

function makeArrow(direction = 'right') {
  const shapes = {
    right:  'polygon(0% 20%, 60% 20%, 60% 0%, 100% 50%, 60% 100%, 60% 80%, 0% 80%)',
    left:   'polygon(100% 20%, 40% 20%, 40% 0%, 0% 50%, 40% 100%, 40% 80%, 100% 80%)',
    up:     'polygon(20% 100%, 20% 40%, 0% 40%, 50% 0%, 100% 40%, 80% 40%, 80% 100%)',
  }
  return shapes[direction] || shapes.right
}

function makeTriangle(type = 'up') {
  const shapes = {
    up:    'polygon(50% 0%, 0% 100%, 100% 100%)',
    down:  'polygon(0% 0%, 100% 0%, 50% 100%)',
    right: 'polygon(0% 0%, 100% 50%, 0% 100%)',
  }
  return shapes[type] || shapes.up
}

// Демонстрация форм
const shapes = [
  { name: 'Шестиугольник', clip: makeHexagon(), bg: '#7b2ff7' },
  { name: 'Звезда 5 лучей', clip: makeStar(5), bg: '#f59e0b' },
  { name: 'Звезда 6 лучей', clip: makeStar(6), bg: '#06b6d4' },
  { name: 'Стрелка →', clip: makeArrow('right'), bg: '#ef4444' },
  { name: 'Треугольник ↑', clip: makeTriangle('up'), bg: '#10b981' },
]

const container = document.createElement('div')
container.style.cssText = 'display: flex; gap: 20px; flex-wrap: wrap; padding: 20px; font-family: sans-serif;'
document.body.appendChild(container)

shapes.forEach(({ name, clip, bg }) => {
  const wrapper = document.createElement('div')
  wrapper.style.cssText = 'display: flex; flex-direction: column; align-items: center; gap: 8px;'

  const el = document.createElement('div')
  el.style.cssText = `width: 80px; height: 80px; background: ${bg}; clip-path: ${clip};`

  const label = document.createElement('span')
  label.textContent = name
  label.style.cssText = 'font-size: 12px; text-align: center; color: #4a5568;'

  wrapper.appendChild(el)
  wrapper.appendChild(label)
  container.appendChild(wrapper)

  console.log(`${name}: ${clip.substring(0, 50)}...`)
})

Clip-path и маски: нестандартные формы

Не все элементы дизайна — прямоугольники. Hexagon-аватары, диагональные секции, звёздные рейтинги, волнообразные разделители — всё это делается через clip-path и mask-image.

clip-path — базовые формы

/* Круг: circle(radius at center-x center-y) */
.avatar {
  clip-path: circle(50%);                /* Круг по центру */
  clip-path: circle(40px at 50% 50%);   /* Явный радиус и центр */
}

/* Эллипс */
.ellipse {
  clip-path: ellipse(60px 40px at center);
}

/* Прямоугольник с закруглением */
.rounded-clip {
  clip-path: inset(10px 20px round 8px);
  /* inset(top right bottom left round radius) */
}

/* Полигон — произвольный многоугольник */
.triangle {
  clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}

.hexagon {
  clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
}

path() — SVG-путь в clip-path

.star {
  clip-path: path('M 50 0 L 61 35 L 98 35 L 68 57 L 79 91 L 50 70 L 21 91 L 32 57 L 2 35 L 39 35 Z');
}

path() принимает SVG path data. Мощно, но координаты абсолютные, а не процентные.

Анимация clip-path

.reveal {
  clip-path: inset(0 100% 0 0);         /* Полностью скрыт справа */
  transition: clip-path 0.6s ease;
}

.reveal.visible {
  clip-path: inset(0 0% 0 0);           /* Полностью виден */
}

/* Hover-эффект: квадрат → круг */
.card {
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
  transition: clip-path 0.4s ease;
}
.card:hover {
  clip-path: circle(50%);
}

mask-image — маски из градиентов и изображений

/* Gradient mask — fade out снизу */
.faded {
  mask-image: linear-gradient(to bottom, black 60%, transparent 100%);
}

/* Круговая маска */
.vignette {
  mask-image: radial-gradient(ellipse at center, black 60%, transparent 100%);
}

/* SVG-маска */
.shaped {
  mask-image: url(#my-svg-mask);
}

mask-composite

.complex-mask {
  mask-image: url(mask1.svg), url(mask2.svg);
  mask-composite: subtract;  /* add | subtract | intersect | exclude */
}

Творческие UI-эффекты

Диагональная секция сайта:

.diagonal-section {
  clip-path: polygon(0 0, 100% 0, 100% 85%, 0 100%);
  /* Нижний правый угол — 85%, нижний левый — 100% */
}

Волна:

.wave-section {
  clip-path: ellipse(100% 55% at 50% 45%);
}

Производительность

clip-path не вызывает перерасчёт layout — браузер просто маскирует уже нарисованный элемент. Анимация clip-path происходит на GPU через compositing, если анимируются только clip-path и transform/opacity.

Примеры

Генерация clip-path значений для разных форм и применение их к элементам

// Генератор clip-path для разных геометрических форм
function makeHexagon() {
  return 'polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%)'
}

function makeStar(points = 5) {
  const coords = []
  for (let i = 0; i < points * 2; i++) {
    const angle = (i * Math.PI) / points - Math.PI / 2
    const r = i % 2 === 0 ? 50 : 22  // внешний/внутренний радиус в %
    const x = 50 + r * Math.cos(angle)
    const y = 50 + r * Math.sin(angle)
    coords.push(`${x.toFixed(1)}% ${y.toFixed(1)}%`)
  }
  return `polygon(${coords.join(', ')})`
}

function makeArrow(direction = 'right') {
  const shapes = {
    right:  'polygon(0% 20%, 60% 20%, 60% 0%, 100% 50%, 60% 100%, 60% 80%, 0% 80%)',
    left:   'polygon(100% 20%, 40% 20%, 40% 0%, 0% 50%, 40% 100%, 40% 80%, 100% 80%)',
    up:     'polygon(20% 100%, 20% 40%, 0% 40%, 50% 0%, 100% 40%, 80% 40%, 80% 100%)',
  }
  return shapes[direction] || shapes.right
}

function makeTriangle(type = 'up') {
  const shapes = {
    up:    'polygon(50% 0%, 0% 100%, 100% 100%)',
    down:  'polygon(0% 0%, 100% 0%, 50% 100%)',
    right: 'polygon(0% 0%, 100% 50%, 0% 100%)',
  }
  return shapes[type] || shapes.up
}

// Демонстрация форм
const shapes = [
  { name: 'Шестиугольник', clip: makeHexagon(), bg: '#7b2ff7' },
  { name: 'Звезда 5 лучей', clip: makeStar(5), bg: '#f59e0b' },
  { name: 'Звезда 6 лучей', clip: makeStar(6), bg: '#06b6d4' },
  { name: 'Стрелка →', clip: makeArrow('right'), bg: '#ef4444' },
  { name: 'Треугольник ↑', clip: makeTriangle('up'), bg: '#10b981' },
]

const container = document.createElement('div')
container.style.cssText = 'display: flex; gap: 20px; flex-wrap: wrap; padding: 20px; font-family: sans-serif;'
document.body.appendChild(container)

shapes.forEach(({ name, clip, bg }) => {
  const wrapper = document.createElement('div')
  wrapper.style.cssText = 'display: flex; flex-direction: column; align-items: center; gap: 8px;'

  const el = document.createElement('div')
  el.style.cssText = `width: 80px; height: 80px; background: ${bg}; clip-path: ${clip};`

  const label = document.createElement('span')
  label.textContent = name
  label.style.cssText = 'font-size: 12px; text-align: center; color: #4a5568;'

  wrapper.appendChild(el)
  wrapper.appendChild(label)
  container.appendChild(wrapper)

  console.log(`${name}: ${clip.substring(0, 50)}...`)
})

Задание

Создай галерею из трёх элементов с разными формами через `clip-path`. Первый элемент — шестиугольник (polygon с 6 точками), второй — треугольник, третий — стрелка вправо. Добавь анимацию `transition: clip-path 0.4s` и при наведении меняй форму на круг через `clip-path: circle(50%)`.

Подсказка

Шестиугольник: `polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%)`. Треугольник вверх: `polygon(50% 0%, 0% 100%, 100% 100%)`. При наведении: `clip-path: circle(50%)` превратит в круг. `transition: clip-path 0.4s` — плавный переход.

Загружаем среду выполнения...
Загружаем AI-помощника...