Иногда кажется, что дизайнеры придумывают интерфейсные паттерны, чтобы поиздеваться над разработчиками. Впуклый угол — один из них.
«Инвертированный», «вогнутый», «впуклый» угол, а также negative border radius или inverted border radius. Когда слышите это — знайте, дальше будут страдания.
Проблема в том, что приём выглядит просто, но нативного способа сделать такой угол в CSS нет. Поэтому в ход идут тучи дополнительных обёрток и море стилей для их позиционирования. И всё это ломается на неоднородном фоне.
В этой статье я покажу простой способ создания впуклых углов с помощью опенсорсной CSS‑библиотеки, которую я разработал специально под эту задачу.
Почему инвертированные углы — это боль
Знакомьтесь с нашим героем на скриншоте:

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

Проблемы с фоном
Типовые решения работают только на сплошных фонах. Как только появляется неоднородный фон, нужно использовать SVG. И CSS‑боль превращается в SVG‑боль.
Решение мечты для впуклых углов
О чём мечтает разработчик, когда видит впуклый угол:
простое решение на чистом CSS;
работающее из коробки, в том числе на неоднородных фонах;
с возможностью нативной кастомизации размеров и формы углов.
И такое решение существует! Это библиотека nebo.css, с которой мы познакомимся в этой статье. Название происходит от названия паттерна — negative border radius.
Подключение nebo.css и первый впуклый угол
nebo.css — это один CSS‑файл, по духу очень похожий на normalize.css: подключил — и используешь. Внутри нет JavaScript, всё сделано на чистом CSS.
Подключаем библиотеку
<link rel="stylesheet" href="nebo.css">Этого уже достаточно, чтобы начать.
Добавляем один угол карточке
Чтобы добавить инвертированный угол, элементу нужен базовый класс nebo. По умолчанию угол появляется снизу справа.
<article class="card nebo">...</article>Результат:

Меняем сторону угла
Сторона задаётся модификаторами:
nebo--tr— сверху справа,nebo--tl— сверху слева,nebo--bl— снизу слева,nebo--br— снизу справа.
<article class="card nebo nebo--tr">...</article>Результат:

На этом этапе уже видно важную вещь: угол корректно работает даже на неоднородном фоне, без дополнительных ухищрений.
Базовая кастомизация
Все параметры nebo.css настраиваются через нативные CSS‑переменные, которые подчиняются обычному каскаду.
Общий радиус скруглений: --nb-r
Эта переменная управляет радиусами скруглений в угле. Значение по умолчанию — 20px. Немного уменьшим его.
.nebo {
--nb-r: 16px;
}Ширина и высота выреза: --nb-w и --nb-h
Эти переменные задают дополнительные смещения между внутренним и внешними радиусами.
.card--cat1 {
--nb-w: 42px;
--nb-h: 16px;
}Результат:

Разные настройки для разных элементов
Так как мы работаем с обычным каскадом, каждый элемент можно настраивать по‑своему:
.card--cat1 { --nb-w: 42px; --nb-h: 16px; }
.card--cat2 { --nb-w: 32px; --nb-h: 42px; }
.card--cat3 { --nb-w: 64px; --nb-h: 42px; }
.card--cat4 { --nb-w: 42px; --nb-h: 16px; }Результат:

Кстати, углы корректно отображаются даже при нулевых значениях (0px) — главное не забывать единицы измерения.
Несколько инвертированных углов у одного элемента
nebo.css изначально решает одну задачу: один элемент — один угол. Но если нужно несколько углов, в ход идёт проверенный приём — дополнительная обёртка.
Используем обёртки
<div class="card-wrapper nebo nebo--bl">
<article class="card nebo nebo--tr">...</article>
</div>Результат:

Каждый уровень можно настраивать отдельно через CSS‑переменные. Можно собрать и три, и четыре угла — просто добавляя обёртки.
Продвинутая кастомизация
Общий радиус для всех скруглений, который задаётся с помощью переменной --nb-r, можно переопределить для каждого из трёх скруглений: двух внешних и одного внутреннего. Причём можно отдельно задать как вертикальные, так и горизонтальные радиусы. Это делаетс�� с помощью шести дополнительных CSS-переменных:
--nb-cor1-rw,
--nb-cor1-rh,
--nb-cor2-rw,
--nb-cor2-rh,
--nb-curve-rw,
--nb-curve-rh,Благодаря этим переменным можно получать впуклые углы очень сложных форм. Например:
.card--cat1 {
--nb-r: 30px;
--nb-w: 0px;
--nb-h: 0px;
--nb-curve-rw: 120px;
--nb-curve-rh: 90px;
--nb-cor1-rw: 90px;
--nb-cor1-rh: 90px;
--nb-cor2-rw: 60px;
--nb-cor2-rh: 60px;
--_nb-smooth: 99.5%;
}Результат:

Пример кейса: карточка из двух блоков
Теперь посмотрим на более жизненный кейс — карточку, состоящую из верхнего блока с изображением и нижнего блока с информацией.
Разметка
<div class="card">
<div class="card-header"></div>
<div class="card-body">
<div class="price">$114,000</div>
...
</div>
</div>Добавляем инвертированные углы
<div class="card-header nebo nebo--bl"></div>
<div class="card-body nebo nebo--tr">...</div>Настраиваем параметры и совмещаем блоки
В примере использован быстрый грязный приём с отрицательным маргином, чтобы подтянуть блок с картинкой к блоку с описанием. Но цель была — показать простоту создания вырезов.
.card-header {
--nb-r: 10px;
--nb-w: 130px;
--nb-h: 44px;
margin-bottom: -54px;
}
.card-body {
--nb-r: 10px;
--nb-w: 160px;
--nb-h: 44px;
}Результат:

Обратите внимание, что всё отлично работает с неоднородным фоном.
Где взять nebo.css
nebo.css — это бесплатная опенсорсная библиотека, разработанная автором. Лежит на GitHub.
Репозиторий:
https://github.com/htmlacademy/nebo.css
Библиотеку можно просто подключить отдельным файлом или скопировать код прямо в свои стили. Пользуйтесь и наслаждайтесь!
А где взять ещё больше сложного CSS и код всех примеров?
Подписывайтесь на мой телеграм‑канал «CSS Боль». Там собраны все материалы, видеоролики, ссылки на интерактивные пошаговые демки
