Пару лет назад в CSS произошла тихая революция, вызвавшая тектонический сдвиг в разработке интерфейсов. Вкратце — нам разрешили «сверлить» настоящие дырки в блоках.

Создание блоков с вырезами всегда было трудоёмким, даже для вырезов простейшей формы. Фронтендеры годами тренировались мысленно рассекать блоки на части: прямоугольничек для контента, прямоугольничек для выреза и ещё парочка рядом с ним. И вдруг парадигма поменялась...

Простые вырезы теперь делаются в десять раз быстрее. Одной строчкой кода. Да, надо менять мышление и забывать про нарезку блоков. И как же это приятно!

В статье мы сверстаем карточку с круглым вырезом двумя способами: традиционно‑дедовским и современным. Затем сравним объём кода, простоту и гибкость получившихся реализаций. И порадуемся, что будущее уже наступило!

Типовые требования к поведению компонента

Мы будем верстать эту карточку:

Дизайнерская карточка про реку Устью Архангельской области
Дизайнерская карточка про реку Устью Архангельской области

При реализации блоков с такими вырезами обычно учитывают два требования:

  • Под карточкой находится неоднородный фон: фотография или градиент, который должен по‑настоящему «просвечивать» в вырезе.

  • Карточка может изменять размеры. Если карточка резиновая, то она может изменять ширину, а при изменении контента может изменяться высота.

Парадигма приклеивания к блокам

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

Схема нарезки блока для создания выреза
Схема нарезки блока для создания выреза

Мы ищем прямоугольную область, в которой будет «жить» контент (выделена жёлтым). А затем «приклеиваем» к ней дополнительные элементы, которые формируют вырез.

Обычно вырез раскладывается на три части:

  • центральную — с фиксированными размерами (выделена зелёным);

  • верхнюю и нижнюю — которые растягиваются по высоте карточки (выделены красным).

Абсолютно типичный и рабочий подход. Давайте его реализуем.

Классическая реализация

Шаг 0. Базовая разметка

Начнём с самой простой разметки: одна карточка и контент внутри.

<div class="card">
  <p class="tag">Устьянский район</p>
  <h1 class="headline">Осенние берега Устьи</h1>
  <p class="lead">Здесь природа говорит шёпотом —<br> ощути северную тишину.</p>
  <button class="button">Купить билет</button>
</div>

Пока это просто набор текстовых элементов.

Разметка контентных элементов. Без жёлтого фона даже лучше, но дизайнер хочет и фон, и вырез
Разметка контентных элементов. Без жёлтого фона даже лучше, но дизайнер хочет и фон, и вырез

Шаг 1. Планируем "нарезку" компонента

Классическую реализацию мы сделаем с помощью флексбокса, чтобы она была понятна всем. Да, можно использовать и гриды, и позиционирование, но сути это не изменит. Поэтому используем флексбокс и планируем дополнительные обёртки с учётом этого.

Чтобы получить карточку с вырезом, нам понадобится две колонки. В одной колонке будет «жить» вырез, в другой — контент. Внутри колонки с вырезом будет три блока: верхний, центральный и нижний.

Центральный блок будет иметь фиксированную высоту, а крайние — растягиваться, подстраиваясь под высоту карточки.

Шаг 2. Добавляем обёртки в разметку

Добавим дополнительные обёртки.

<div class="card">
  <div class="cutout">
    <div class="cutout-top"></div>
    <div class="cutout-center"></div>
    <div class="cutout-bottom"></div>
  </div>
  <div class="card-content">
    <p class="tag">Устьянский район</p>
    <h1 class="headline">Осенние берега Устьи</h1>
    <p class="lead">Здесь природа говорит шёпотом —<br> ощути северную тишину.</p>
    <button class="button">Купить билет</button>
  </div>
</div>

Уже сейчас видно, как DOM начал разрастаться.

Шаг 3. Базовая геометрия карточки

Делаем карточку флекс‑контейнером и задаём ширины колонок. Нам приходится подбирать ширину блоков и внутренние отступы, чтобы получить нужное расстояние от контента до выреза.

.card {
  display: flex;
  width: 620px;
}

.card-content {
  width: 420px;
  padding: 50px;
  padding-left: 75px;
  color: #6b5742;
  background-color: #fdf6f0;
}

.cutout {
  width: 75px;
}

Теперь у нас есть две колонки: контент и будущий вырез.

Геометрия колонок. Колонка для выреза временно обведена красным
Геометрия колонок. Колонка для выреза временно обведена красным

Шаг 4. Стилизуем блоки вокруг выреза

Превращаем блок .cutout во флекс‑контейнер и направляем его главную ось вниз. Верхний и нижний блоки растягиваем по высоте с помощью flex-grow: 1; и задаём им фон. Центральному блоку, внутри которого будет изображение для выреза, задаём фиксированную высоту.

.cutout {
  display: flex;
  flex-direction: column;
}

.cutout-top,
.cutout-bottom {
  flex-grow: 1;
  background-color: #fdf6f0;
}

.cutout-center {
  height: 150px;
}

При изменении высоты карточки крайние элементы растягиваются, центральный остаётся фиксированным.

Тянущиеся блоки вокруг блока с вырезом
Тянущиеся блоки вокруг блока с вырезом

Шаг 5. Рисуем сам вырез

Форму выреза можно реализовать по‑разному: использовать PNG с полупрозрачностью, или SVG, или нарисовать с помощью CSS‑градиента. Мы используем радиальный градиент, чтобы не подключать лишнюю картинку.

.cutout-center {
  height: 150px;
  background-image: radial-gradient(
    circle at 0 50%,
    transparent 74.5px,
    #fdf6f0 75px
  );
}

Вырез появился. Карточка выглядит как задумано.

Вырез готов
Вырез готов

Проверяем на переполнение

Добавим больше текста. Высота карточки увеличилась — вырез остался на месте. Всё работает.

Поведение выреза при увеличении высоты карточки
Поведение выреза при увеличении высоты карточки

Реализация готова. Можно подвести итог. Нам понадобилось 5 дополнительных обёрток и около 20 строчек кода. Это не смертельно. Карточка ведёт себя хорошо. За исключением одного неприятного ограничения.

Ограничение — неоднородный фон у карточки

Попробуем добавить карточке градиентный фон. Добавляем его блоку с контентом.

.card-content {
  background-image: linear-gradient(135deg, #fff6e9, #fdd9b5, #f4a261);
}

Нам нужно, чтобы фон заполнял всю карточку, поэтому добавим его и блокам .cutout-top и .cutout-bottom:

.cutout-top,
.cutout-bottom {
  background-image: linear-gradient(135deg, #fff6e9, #fdd9b5, #f4a261);
}

И тут становится больно. Карточка состоит из отдельных блоков и фон ломается на стыках.

Проблема с неоднородным фоном
Проблема с неоднородным фоном

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

Выводы по классическому подходу

Классический способ работает, но:

  • требует дополнительных обёрток;

  • заставляет писать много CSS;

  • не позволяет задавать неоднородный фон самой карточке.

А теперь давайте посмотрим, как ту же задачу можно решить иначе.

Современная реализация

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

Планируем место, где будет вырез на цельной карточке
Планируем место, где будет вырез на цельной карточке

Для этого нам понадобятся CSS‑маски.

Шаг 1. Возвращаемся к простой карточке

Убираем все дополнительные обёртки и оставляем один элемент .card. Единственное изменение — размер отступа слева. Увеличиваем его с учётом размера выреза.

.card {
  width: 420px;
  padding: 50px;
  padding-left: 150px;
  color: #6b5742;
  background-color: #fdf6f0;
}

Результат такой:

Базовая геометрия карточки
Базовая геометрия карточки

Шаг 2. Добавляем одно свойство — mask-image

.card {
  mask-image: radial-gradient(
    circle at 0 50%,
    transparent 74.5px,
    black 75px
  );
}

Всё. Карточка с вырезом готова.

Вырез на CSS-маске готов
Вырез на CSS-маске готов

Лирическое отступление: как работает эта маска

Не так много разработчиков знакомы с CSS‑масками, да и радиальные градиенты никогда не отличались популярностью. Поэтому давайте подробнее разберём, как сделан этот вырез.

Семейство свойств mask-* работает почти так же как семейство свойств background-*. Если вы работали с фоновыми изображениями, то и с масками разберётесь быстро.

Чтобы понять механику, заменим mask-image на background-image. Это позволит увидеть форму маски. Вначале создадим простейший радиальный градиент, круглой формы с двумя цветами (прозрачным и чёрным):

background-image: radial-gradient(
  circle,
  transparent,
  black
);

Результат:

Простейший радиальный градиент в качестве фона
Простейший радиальный градиент в качестве фона

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

background-image: radial-gradient(
  circle,
  transparent 74.5px,
  black 75px
);

Результат:

Градиент с резким переходом цветов
Градиент с резким переходом цветов

Сместим центр градиента на середину левой стороны блока с помощью at 0 50%. Форма маски готова.

background-image: radial-gradient(
  circle at 0 50%,
  transparent 74.5px,
  black 75px
);

Результат:

Центр градиента на середине левой стороны карточки. Заготовка для маски завершена
Центр градиента на середине левой стороны карточки. Заготовка для маски завершена

Прозрачная часть — это то, что будет вырезано. Чёрная — то, что останется. Чтобы получить вырез, остаётся только заменить background-image на mask-image.

Переполнение и неоднородный фон

Благодаря использованию маски карточка остаётся цельной. Поэтому:

  • она корректно реагирует на изменение высоты и ширины;

  • карточке можно задавать неоднородный фон (градиент, изображение);

  • можно комбинировать несколько фонов.

.card {
  background-image: 
    linear-gradient(to bottom, rgba(0, 0, 0, 0.1) 50%, transparent 51%), 
    linear-gradient(135deg, #fff6e9, #fdd9b5, #f4a261);
  background-repeat: repeat-y, no-repeat;
  background-size: 1.5px 20px, auto auto;
  background-position: 115px 4px, 0 0;
}

В результате мы получили карточку с неоднородным фоном и «линией отреза»:

Никаких проблем с неоднородным фоном
Никаких проблем с неоднородным фоном

Выводы по современной реализации

Реализация выреза на CSS‑масках на порядок лучше старого подхода:

  • дополнительные обёртки не нужны;

  • используется всего одно CSS‑свойство;

  • позволяет задавать неоднородный фон самой карточке.

Поддержка CSS-масок — всё отлично!

Маски доступны во всех современных браузерах уже несколько лет, а радиальные градиенты — и того дольше.

Смена парадигмы

Старая парадигма «приклеивания к блокам», в которой мы собирали вырезы из нескольких частей, умирает. На замену ей приходит парадигма «вырезания из блоков», которая на порядок упрощает создание вырезов и даёт дополнительную гибкость при использовании фонов.

Будущее уже здесь!

А где взять ещё больше сложного CSS и код всех примеров?

Подписывайтесь на мой телеграм‑канал «CSS Боль». Там собраны все материалы, видеоролики, ссылки на интерактивные пошаговые демки

Комментарии (24)


  1. howk
    06.02.2026 10:07

    Вот бы еще был способ делать такие сложные закругления при которых корректно отрабатывали внешние и внутренние тени для блоков


    1. AlexPershin Автор
      06.02.2026 10:07

      Внешние тени решаются обёрткой со свойством filter: drop-shadow(...) Не помню только, поддерживает ли этот фильтр внутренние тени


      1. goncharovyelisey
        06.02.2026 10:07

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


        1. AlexPershin Автор
          06.02.2026 10:07

          Посмотрите на скриншот ниже. С внешней тенью отлично справляется. С внутренней — нет.

          Но смысл статьи не в этом. Раньше для простых вырезов нужно было делать сложную реализацию, и для сложных вырезов тоже нужно было делать сложную реализацию.

          А сейчас для простых вырезов у нас есть простейшее решение в одну строчку. А для сложных вырезов остаются сложные решения, никуда не деться. Но как минимум появляется возможность искать компромисс с дизайнером "упрощаем дизайн и делаем блок за 5 минут" или "оставляем сложный дизайн и убиваем на реализацию день"


    1. AlexPershin Автор
      06.02.2026 10:07

      вот быстрый пример. специально сделал красную тень


  1. IvaYan
    06.02.2026 10:07

    Тьфу. Прочитал заголовок, подумал, что речь про декольте, заинтересовался. А оказался CSS какой-то.


    1. AlexPershin Автор
      06.02.2026 10:07

      Приятно видеть ценителя вырезов =)


    1. Newbilius
      06.02.2026 10:07

      А я думал, что речь пройдёт про вырезы телефонов... хабр на мобилке то хабы не показывает :(


    1. aamonster
      06.02.2026 10:07

      Думал, эротика, а оказалось порно?


  1. codaink
    06.02.2026 10:07

    Огонь, даже не подозревал что так можно. А что с поддержкой браузеров, в статье не уточнили?


    1. AlexPershin Автор
      06.02.2026 10:07

      отличная поддержка, в статье отдельный заголовок под это отведён. widely avaliable уже через пару месяцев будет


      1. aamonster
        06.02.2026 10:07

        Только чтобы нормально пользоваться – надо не "Wildely available", а чтобы "даже у последнего владельца нокии 3310" правильно отображалось.

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


        1. AlexPershin Автор
          06.02.2026 10:07

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


          1. aamonster
            06.02.2026 10:07

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


            1. AlexPershin Автор
              06.02.2026 10:07

              В случае с вырезами пользователи старых браузеров отлично обойдутся и без них


              1. aamonster
                06.02.2026 10:07

                И новых тоже, если честно :-)


  1. VVitaly
    06.02.2026 10:07

    :-) Да уж.... Вот такие "вырезы" современный веб и "тормозят"....


    1. AlexPershin Автор
      06.02.2026 10:07

      Это камень в огород дизайнеров или тех, кому приходится их задумки реализовывать? =)


      1. VVitaly
        06.02.2026 10:07

        :-) В первую очередь "в огород" тех кому это нравится....


  1. PaulZi
    06.02.2026 10:07

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


    1. AlexPershin Автор
      06.02.2026 10:07

      А можете прислать пример реализации такого же выреза на clip-path?

      И если под рукой завалялась спека или какая-то другая техническая статья про производительность двух методов, буду благодарен, хочу покопать этот вопрос


      1. PaulZi
        06.02.2026 10:07

        https://codesandbox.io/p/sandbox/s6wlgy

        Вот накидал варианты c clip-path с svg (потому что просто через path не масштабируется) и вариант через shape (с последним пока нет поддержки в firefox). Кривоватенько, но суть понятна.

        По производительности тесты не проводил, думаю это будет хорошей основой для новой статьи.


        1. AlexPershin Автор
          06.02.2026 10:07

          Спасибо, поигрался с вашими вариантами. Честно говоря, убедился что для таких простых задач маски намного лучше, чем clip-path

          С точки зрения поддержки вариант с SVG сопоставим с масками. Но он требует тащить в проект отдельное свг-изображение. Само это изображение надо предварительно где-то отрисовать. И вот вопрос — а зачем мне тащить в реализацию свг, если я справляюсь одним свойством без SVG

          Вариант на shape плохо поддерживается, синтаксис намного сложнее, да и форма выреза получилась не круглой, а какой-то овальной.

          Единственный аргумент за усложнение своей жизни с clip-path — это производительность. Но у меня огромные сомнения, что маски по производительности отличаются от клип-пасов. Может быть есть ссылки на статьи, где этот вопрос разбирается? Я где-то слышал (но сам не проверял), что маски рендерятся на GPU, и если это так, то с производительностью там должно быть всё отлично.


  1. Metotron0
    06.02.2026 10:07

    В перчую очередь пришла на ум маска, но я знал, что она работает с картинками, про градиенты не задумывался. Подумал было, что речь пойдёт про какое-то новое свойство, типа corder-shape. Но тоже пригодится. Хорошо, что мне обычно таких вещей верстать не приходится.

    К слову, в варианте с тремя блоками я бы сделал не дивы сверху и снизу, а after и before.