Радиус вложенных скруглений

Посчитайте border-radius вложенного элемента так, чтобы дуги шли на одинаковом расстоянии: Rᵢ = Rₑ − E. С наглядным превью угла и готовым CSS.

40px20px
17px
Внешний радиус 40pxВнутренний 17px

дуга внешнего радиуса, внутреннего. Когда расчёт верен, между дугами всюду один и тот же зазор — включите «крупно», чтобы рассмотреть угол.

.card {
	--radius: 40px;
	--padding: 20px;
	--border: 3px;
	border: var(--border) solid;
	border-radius: var(--radius);
	padding: var(--padding);
}

.card__inner {
	border-radius: max(0px, var(--radius) - var(--padding) - var(--border));
}

Правило: радиус внутреннего = радиус внешнего минус отступ

Когда одна скруглённая коробка лежит внутри другой, радиусы не должны совпадать. Внутренний элемент отодвинут от внешнего на величину отступа, и его угол начинается ближе к центру — значит, и загибаться он должен круче. Отсюда вся арифметика: Rᵢ = Rₑ − E, где E — расстояние между контурами, то есть padding плюс толщина рамки. То же самое с другой стороны: если задан внутренний радиус, внешний равен Rᵢ + E.

Как выглядит ошибка

Самый частый вариант — оставить обоим элементам один и тот же радиус. Тогда в углу зазор между контурами становится зрительно шире, чем по сторонам: дуги расходятся. Обратная крайность — оставить внутреннему нулевой радиус, и угол торчит острым в круглой рамке. Переключатель «Одинаковый» в инструменте показывает первый случай: включите его, сравните с расчётом и увидите разницу, ради которой формула и нужна.

Почему в CSS лучше переменные, а не два числа

Можно выписать оба радиуса вручную, но связь между ними при этом теряется: стоит поменять отступ, и углы разъедутся, а причину никто не вспомнит. Поэтому инструмент отдаёт код через кастомные свойства, где внутренний радиус вычисляется из внешнего прямо в стилях. Обёртка в max(0px, ...) нужна на случай, когда отступ больше радиуса: отрицательное значение браузер отбросил бы вместе со всем свойством, а так угол просто становится прямым.

Точность приёма

Строго математически дуги при таком расчёте не эквидистантны: центры окружностей не совпадают, и расстояние между линиями по ходу дуги чуть меняется. На практике расхождение меньше того, что различает глаз, поэтому приём давно принят в интерфейсной вёрстке и заложен в дизайн-системы. Включите «крупно» и посмотрите на угол вблизи — видно, насколько близко дуги идут друг к другу.

Похожие инструменты

Другие полезные инструменты из той же категории

Часто задаваемые вопросы

Потому что его угол начинается ближе к центру — он отодвинут от внешнего контура на величину отступа, и загибаться должен круче. Если оставить обоим один радиус, в углу зазор между контурами станет зрительно шире, чем по сторонам.

Всё, что физически раздвигает контуры: padding внешнего элемента плюс толщина его рамки. Рамку часто забывают, и тогда радиус промахивается ровно на её толщину — при рамке в один-два пикселя это почти незаметно, при более толстой уже видно.

Ничего: у внутреннего элемента получается прямой угол, и это правильно — скруглять там уже нечего. Важно только не оставить в CSS отрицательное значение, иначе браузер отбросит всё свойство целиком. Поэтому в выдаваемом коде стоит max(0px, ...).

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