Закругленные углы в CSS3
В документации CSS 3 Backgrounds and Borders module описано свойство border-radius
, позволяющее создать закругленную границу вокруг прямоугольного блока. Браузеры на основе движка Gecko (Firefox и SeaMonkey), а также Webkit браузеры (Safari и Chrome) частично поддерживают данное свойство. В Firefox 3.5 добавлена поддержка эллиптических углов и доведена реализация Gecko на уровень стандартов во многих деталям.
На момент написания статьи модуль фона и границ (Backgrounds and Borders module) остаются черновым документом W3C, поэтому при именовании данных свойств все браузеры должны использовать вендорные префиксы. В примерах данной статьи мы будем использовать стандартные названия свойств. Вендорные префиксы можно найти в этой заметке. Согласно политики компании Mozilla стандартные имена начинают использовать как только модуль становится рекомендованным или правильнее сказать, достигает состояния Candidate Recommendation stage (bug 451134)
Введение в закругленные углы
В простейшей форме свойство border-radius
принимает единственное значение <length>
, закругляя все четыре угла блока. Если необходимо задать разные радиусы закругления, то необходимо перечислить значения <length>
привычным способом, начиная сверху и по часовой стрелке. При указании двух или трех значений, пропущенные значения берутся из противоположных углов (top, right, bottom, left). Для контроля закругления каждого отдельного угла можно также использовать т.н. «longhand» свойства:
border-top-left-radius,
border-top-right-radius,
border-bottom-right-radius и
border-bottom-left-radius
Backgrounds module добавляет возможность создания эллиптических углов. При использовании «longhand»-свойств необходимо просто добавить в свойство второе значение <length>
; первое значение определяет горизонтальную полуось эллипса, второе — вертикальную. При сокращенной форме записи свойства border-radius
сначала указываются значения радиуса горизонтальной полуоси, далее прямой слеш / и значения радиуса вертикальной. Если слеш отсутствует и указано только одно значение <length>
, то горизонтальный и вертикальный радиусы равны.
Например,
border-radius: 4em;
эквивалентно
border-top-left-radius: 4em;
border-top-right-radius: 4em;
border-bottom-right-radius: 4em;
border-bottom-left-radius: 4em;
или
border-radius: 2em 1em 4em / 0.5em 3em;
эквивалентно
border-top-left-radius: 2em 0.5em;
border-top-right-radius: 1em 3em;
border-bottom-right-radius: 4em 0.5em;
border-bottom-left-radius: 1em 3em;
Без вендорного префикса | Gecko (-moz) | Webkit (-webkit) | Правильное отображение |
---|---|---|---|
border-radius:10px;
|
-moz-border-radius: 10px;
|
-webkit-border-top-left-radius:10px;
|
![]() |
border-radius:10px 0;
|
-moz-border-radius: 10px 0;
|
-webkit-border-top-left-radius:10px;
|
![]() |
border-radius:10px 0px 20px;
|
-moz-border-radius:10px 0px 20px;
|
-webkit-border-top-left-radius:10px;
|
![]() |
border-radius:10px 0px 20px 30px;
|
-moz-border-radius:10px 0px 20px 30px;
|
-webkit-border-top-left-radius:10px;
|
![]() |
border-top-left-radius:20px 30px;
|
-moz-border-radius-topleft:20px 30px;
|
-webkit-border-top-left-radius:20px 30px;
|
![]() |
border-radius:10px 0 / 30px 0;
|
-moz-border-radius:10px 0 / 30px 0;
|
-webkit-border-top-left-radius:10px 30px;
|
![]() |
border-radius: 10px / 30px 30px 10px 10px;
|
-moz-border-radius:10px / 30px 30px 10px 10px;
|
-webkit-border-top-left-radius:10px 30px;
|
![]() |
Webkit не воспринимает border-radius
как сокращенную форму записи и принимает только одно значение <length>
. Если вам необходимо задать разные значения закругления углов, необходимо использовать полную «longhand» форму записи свойства.
Закругления углов. Немного теории
Свойство border-radius
контролирует горизонтальную и вертикальную полуоси внешней дуги границы. Радиус внутренней границы равен радиусу внешний (border-radius
) минус толщина границы (border-width
). Если это значение будет отрицательным или равным нулю, то радиус внутренней дуги будет равен нулю. Таким образом, если две смежные границы имеют различную толщину появится плавный переход от более широкой к более узкой границе. (Рис. 1)
Место перехода цвета и стиля между соединяющимися границами находится в точке кривой, которая располагается под углом пропорциональным соотношению значений ширины смежных границ. Например, если значения ширины смежных границ равны, то точка перехода расположена под углом 45°, если ширина одной границы больше другой в два раза, то точка перехода находится под углом 30° и т.д. Линия, разделяющая переход проходит под этим углом через внутреннюю и внешнюю границу дуги. Линия раздела создает видимую границу между смежными границами различного цвета. W3C не говорит, как должен выглядеть переход, но рекомендует применять градиент, который не относится к dotted или dashed границам.
Посмотрим, что произойдет, если радиус дуги превысит размеры блока. Если сумма радиусов двух смежных углов превышает размеры блока (речь идет о ширине и высоте блока, что больше) ПА должны уменьшить один или несколько радиусов. Алгоритм уменьшения следующий:
Сумма двух смежных радиусов не может быть больше ширины/высоты блока. Если сумма радиусов превышает это значение, то значение радиуса рассчитывается по следующей формуле:
Пусть f = min(Li/Si), где i ∈ {top, right, bottom, left}, Si сумма радиусов угла стороны i, и Ltop = Lbottom = ширине блока, Lleft = Lright = высоте блока. Если f < 1, тогда все радиусы углов уменьшаются путем умножения в f.
Данная формула имеет преимущества и недостатки:
… формула проверяет чтобы четверти круга оставались четвертями и бóльшие радиусы оставались больше, чем меньшие, однако формула может уменьшить и меньшие углы, что изменит вид границ, которые должны выглядеть неизменными.
На момент написания статьи данная формула работает в Firefox 3.5 и последних версиях Webkit (library version 1.1.8 и позже; 8736). Более старые версии Gecko-браузеров масштабируют каждую дугу угла независимо и ограничивает угол до половины размера блока. Старые версии Webkit-браузеров игнорируют все угловые радиусы, если сумма радиусов больше размера блока.
Если граница не solid
?
С границами inset
, outset
, double
, groove
и ridge
в принципе все в порядке.
Границы dotted
и dashed
в местах закруглений должны отображаться точками или пунктирными линиями соответственно. Gecko-браузеры вообще не поддерживают точки и пунктир в дугах и отображают их сплошной линией (bug 382721). Webkit-браузеры рисуют точки или пунктир, однако могут наблюдаться артефакты.
Clipping
Цветовой фон и фон с изображениями обрезается по краям закруглений. Наличие границы при этом не является обязательным условием. border-image
не обрезается, а вот фон по прежнему обрезается по дуге, даже если не задана граница.
Контент не обрезается в принципе. Однако, если воспользоваться свойством overflow:hidden
контент должен обрезаться по дуге. Webkit поддерживает частично (bug 9543), Gecko, как и старые версии WebKit не поддерживают (bug 459144).
Спецификация говорит: Если в закругленном угле находится scrolling ПА могут уменьшить или обнулить border-radius
. Другими словами, если есть скроллбар (overflow:scroll
или overflow:auto
), закругленных углов можно не увидеть Обосновано это тем, что скроллбар сам по себе не может быть обрезан.
По умолчанию, clipping path представляет из себя внешний закругленный прямоугольник, и фон будет виден под границей, при условии что граница не полностью прозрачная. Backgrounds module включает свойство background-clip
, которое определяет границу заливки фона. Gecko и Webkit частично поддерживают это свойство, однако соответствуют устаревшей спецификации и вместо border-box
и padding-box
используют border
и padding
; content-box
и no-clip
не поддерживаются.
Источники:
- CSS Backgrounds and Borders Module Level 3
- Boxes with Rounded Corners
Спасибо за материал. Все по полочкам.
Узнал несколько полезных мелких штук, в которых раньше сомневался и руки не доходили проверить.
Остается только дождаться широкой поддержки браузерами третьей спецификации, пока использую в проектах (редко, оно ведь невалидно)симбиоз всех трех способов.
P.S. В первом абзаце есть пару описок в слове Geck(t)o.
— rotor Aug 30, 03:25 PM #
Спасибо, поправил.
— higher Aug 30, 03:46 PM #