Фигурные вырезки

Функции для сайтов: Маски

Обзор

Маски CSS позволяют обрезать элемент по произвольной форме, например добавить вырез на карточку или создать фигурную границу. При объединении фигур для сложных макетов выбирайте стратегию маскирования в зависимости от типа контента, который содержит элемент:

Стратегия маскирования Устройства Влияние текста
Прямое маскирование элементов SVG Изображения, значки, декоративные фигуры, сложные фигуры Не рекомендуется (текст может быть обрезан)
Маскирование SVG-элементов, расположенных рядом Карточки с текстом, важный контент Текст остается полностью читаемым.
Градиенты на чистом CSS Простые геометрические фигуры Не рекомендуется (текст может быть обрезан)

Реализация

Чтобы реализовать фигурные вырезы:

Использование маски SVG

Маски SVG позволяют определять фигуры, которые вычитаются из видимой области или добавляются к ней с помощью белой (показать) и черной (скрыть) заливки.

Маскирование по яркости и альфа-маскирование. По умолчанию маски SVG работают в режиме яркости, поэтому мы используем fill="white", чтобы показать области, и fill="black", чтобы вырезать их. Если вы хотите использовать прозрачность SVG (альфа-канал) вместо цветов, вы можете задать mask-type: alpha; в CSS или mask-type="alpha" в элементе <mask> SVG.

Прямое маскирование элементов SVG

Если в элементе нет текста (например, это аватар профиля, изображение товара или иллюстрация), вы можете применить маску SVG непосредственно к элементу.

Использование maskContentUnits="objectBoundingBox" в маске SVG гарантирует, что маска автоматически масштабируется по ширине и высоте любого элемента, к которому она применяется.

<!-- 1. Define the mask in SVG (hidden from view) -->
<svg width="0" height="0" style="position: absolute;" aria-hidden="true">
  <defs>
    <!-- objectBoundingBox makes the mask scale from 0 to 1 along the element's borders -->
    <mask id="splat-mask" maskContentUnits="objectBoundingBox">
      <!-- Organic Bezier path defining an artistic paint splat shape -->
      <path d="M 0.5 0.05 C 0.58 0.05, 0.58 0.21, 0.67 0.18 C 0.76 0.15, 0.79 0.08, 0.85 0.15 C 0.91 0.22, 0.83 0.32, 0.89 0.38 C 0.95 0.44, 1.03 0.45, 0.99 0.55 C 0.95 0.65, 0.82 0.62, 0.8 0.72 C 0.78 0.82, 0.89 0.92, 0.8 0.97 C 0.71 1.02, 0.64 0.88, 0.55 0.93 C 0.46 0.98, 0.44 1.06, 0.35 1.01 C 0.26 0.96, 0.31 0.81, 0.22 0.79 C 0.13 0.77, 0.01 0.88, 0.01 0.77 C 0.01 0.66, 0.16 0.62, 0.14 0.52 C 0.12 0.42, -0.02 0.39, 0.03 0.29 C 0.08 0.19, 0.23 0.27, 0.29 0.19 C 0.35 0.11, 0.3 0.01, 0.4 0.01 C 0.5 0.01, 0.42 0.05, 0.5 0.05 Z" fill="white" />
    </mask>
  </defs>
</svg>

<!-- 2. Apply the mask to the image element -->
<img src="avatar.jpg" alt="User Profile" class="shaped-avatar">

<style>
.shaped-avatar {
  width: 200px;
  height: 200px;
  object-fit: cover;
  
  /* Apply the SVG mask ID with standard and webkit-prefixed properties */
  -webkit-mask-image: url(#splat-mask);
  mask-image: url(#splat-mask);
}
</style>

Маскирование SVG-элементов, расположенных рядом

Примените маску к соседнему элементу, а не к родительскому элементу, содержащему текст. Это гарантирует, что текст не будет обрезан и останется читаемым.

Чтобы решить эту проблему, разделите компонент на две части:

  1. Безопасный контейнер для незамаскированного текста (.card-body) для всего читаемого контента.
  2. Пустой декоративный элемент div (.card-accent), размещенный рядом с ним, который получает пользовательскую маску SVG.

Если задать для обеих частей одинаковый цвет фона, они визуально объединятся в один компонент нестандартной формы.

<!-- 1. Define the SVG mask (hidden from view) -->
<svg width="0" height="0" style="position: absolute;" aria-hidden="true">
  <defs>
    <!-- Use objectBoundingBox to make the mask scale with the element -->
    <mask id="accent-stencil" maskContentUnits="objectBoundingBox">
      <!-- Fill the entire area with white (fully visible) -->
      <rect width="1" height="1" fill="white" />
      <!-- Draw a black shape to cut out a concave curve. Extending the path to x=1.1 guarantees it fully clears the right edge, preventing subpixel lines -->
      <path d="M 1.1,0 C 0.4,0.1 0.4,0.9 1.1,1 L 1.1,0 Z" fill="black" />
    </mask>
  </defs>
</svg>

<!-- 2. Create the unified card layout -->
<div class="unified-card">
  <!-- The text-bearing element remains unmasked and perfectly rectangular -->
  <div class="card-body">
    <h3>Premium Membership</h3>
    <p>Get exclusive weekly updates on modern web standards and premium UI designs.</p>
  </div>
  <!-- The empty accent element next to it is masked to form the custom shape -->
  <div class="card-accent"></div>
</div>

<style>
.unified-card {
  display: flex;
  width: 400px;
}

.card-body {
  flex: 1;
  background-color: #1e293b; /* Elegant slate color */
  color: #f8fafc;
  padding: 24px;
  border-top-left-radius: 16px;
  border-bottom-left-radius: 16px;
}

.card-accent {
  width: 60px;
  background-color: #1e293b; /* Same background color so they merge visually without seams */
  border-top-right-radius: 16px;
  border-bottom-right-radius: 16px;

  /* Reference the SVG mask */
  -webkit-mask-image: url(#card-accent-mask);
  mask-image: url(#card-accent-mask);
}
</style>

Использование одного градиента CSS для простых вырезов

Если вам нужны простые геометрические вырезы (например, полукруглый вырез сверху, боковые выемки или прямые диагональные вырезы), вам не нужно писать или ссылаться на внешний SVG. Вместо этого вы можете определить радиальный или линейный градиент CSS непосредственно в свойстве mask-image.

<div class="gradient-masked-card">
  <h3>Notched Coupon Card</h3>
  <p>This card uses a pure CSS radial gradient to cut out a semi-circular notch along its top edge.</p>
</div>

<style>
.gradient-masked-card {
  background: linear-gradient(135deg, #3b82f6, #1d4ed8);
  color: white;
  padding: 40px 24px 24px 24px; /* Extra top padding ensures content clears the notch */
  border-radius: 16px;
  text-align: center;

  /* radial-gradient places a circle at 50% (horizontal center) and 0% (top edge), cutting out a 20px transparent notch */
  -webkit-mask-image: radial-gradient(circle at 50% 0%, transparent 20px, black 21px);
  mask-image: radial-gradient(circle at 50% 0%, transparent 20px, black 21px);
}
</style>

Резервные стратегии

Если браузер не поддерживает mask-image или версию с префиксом:

  • Фигурные изображения. Элемент будет отображаться как обычный прямоугольник со стилями по умолчанию.
  • Для фигурных карточек. Смежный декоративный элемент .card-accent останется сплошным прямоугольником без маски. Поскольку у него тот же цвет фона, что и у контейнера с текстом, вся карточка будет выглядеть как стандартный прямоугольный контейнер.
  • Прогрессивное улучшение. Если текстовые слои находятся за пределами маски, контент гарантированно останется читаемым, структурированным и доступным в старых браузерах.