Закругляем углы блоков. Часть первая.категории: html css , expression
Здравствуйте. Наконец дошли руки написать статью. Сегодня я поведаю вам о том, как закруглить углы у блоков наиболее компактным и гибким способом.
Статья подробная, с пояснениями что, как и почему. Пока писал — понял, что объем будет на столько велик, что укладывать всё в одну не стоит. Поэтому это — только первая часть.
К сожалению, одного универсального способа нет. Нет, ну есть один — при помощи javascript. Но он так грузит браузер, что несколько подобных блоков способны напомнить посетителю сайта о лихих временах floppy-дисков, DIMM-памяти и процессоров, измеряемых мегагерцами. Вряд ли человек обрадуется таким воспоминаниям…
Итак, рассмотрим случаи, в которых нам понадобятся разные методы округления углов:
- Одноцветный блок на одноцветном фоне.
- Пестрый блок на одноцветном фоне.
- Одноцветный блок с границей на одноцветном фоне.
- Одноцветный блок на пестром фоне.
- Пестрый блок на пестром фоне.
В первой части мы рассмотрим основы и первый случай — одноцветный блок на одноцветном фоне.
Во всех случаях главные условия:
- Минимум кода
- Редактирование через CSS
- «Резиновость» (т.е. блоки должны тянуться во все стороны) — с фиксированными блоками слишком просто, а блоки с одной зафиксированной стороной делаются так же, как и резиновые, только с упрощением.
- Соответствие стандартам W3C (т.е. всякие «хаки» для експлорера не проходят)
Общие свойства.
В основу всех методов заложена замечательная особенность взаимопозиционирования элементов со свойствами position: relative и position: absolute.
position: absolute, если не указывать ему атрибуты left/top/right/bottom перемещается в левый верхний угол родительского элемента. Если задать ему эти атрибуты — он будет ориентироваться относительно body. Но! Если родительский элемент обладает свойством position: relative, то дочерний элемент с position: absolute при наличии атрибутов left/top/right/bottom будет ориентироваться относительно родителя. Работает это везде, с одной только поправкой: в IE при позиционировании учитываются padding родителя, а в остальных браузерах — нет.
Руководствуясь вышеозначенными требованиями и свойствами, готовим, собственно, структуру. Для создания углов мы воспользуемся html-тегами. В идеальном случае, нам нужно определиться, какие теги внутри блока использоваться не будут. Это упростит и уменьшит код, т.к. в CSS можно будет углы описать вложениями, а не классами. Это могут быть любые элементы. Например, <h1>, <h2>, <h3>, <h4>.
Если вам нельзя ограничивать свободу содержимого блока, то воспользуйтесь любым тегом (например, <b>, для минимизации кода) и присвойте ему соответствующие углам классы (я зачастую использую идентификацию по сторонам света — c_nw, c_ne, c_sw, c_se, где c — corner, nw — north-west и т.п.). В примере я буду использовать <h1>, <h2>… Если у вас будет что-то другое — просто поменяете в CSS теги.
Конечно, нам нужны отступы от краёв блока. Использовать padding родителя можно, но тогда нужно учитывать, что общий размер блока складывается из width, margin и padding, что усложняет задание размера (особенно в процентах). Плюс, придется писать дополнительный CSS для IE, в котором отдельно расчитывать позиционирование углов и подключать его через условные комментарии. Поэтому я бы советовал внутрь добавить еще один элемент (div) с указанием margin.
Итак, в идеале, блок будет выглядеть так:
- <div class="r_block">
- <!--Это — углы. Их можно и в конец поставить, не принципиально.-->
- <h1></h1><h2></h2><h3></h3><h4></h4>
- <!--Далее — содержимое.-->
- <div class="r_b_content">
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam porttitor aliquet augue. Donec est lorem, dignissim eget, blandit ut, tincidunt et, est. Quisque quam. Aliquam arcu diam, bibendum ac, varius non, ornare a, metus. Nullam facilisis porta tellus. Nulla id sem. Quisque eu lorem ac mi lobortis ornare. Quisque scelerisque tempus turpis. Nullam et nibh. Curabitur sed nisl id quam pellentesque rhoncus. Duis eu tortor eu nunc cursus fringilla. Pellentesque faucibus quam quis tellus. Praesent ut turpis sed arcu tristique porta. Pellentesque consectetur lorem ac tortor. Phasellus id risus eu massa hendrerit tempor. Suspendisse sollicitudin nunc vel ipsum. Nunc quam leo, tristique eu, mattis eu, rutrum eget, leo. Pellentesque aliquam mi pretium risus. Nunc accumsan volutpat nibh. Nulla urna.
- </div>
- </div>
Достаточно компактно, по-моему.
Теперь переходим к картинкам (да, без картинок не обойдемся) и CSS. Теги <h1>, <h2>… Соответствуют углам, начиная с верхнего левого по часовой стрелке.
Собственно код.
Предположим, блок у нас серый, фон — белый. Для углов мы готовим CSS-sprite (спрайт). Т.е. это одна картинка, на которой собрано несколько, а в CSS она используется как фон определенных элементов и позиционируется свойством background-position.
Пусть радиус закругления будет 15 точек. Открываем Photoshop (или любой другой редактор, хоть paint), создаем полотно размером 30x30 точек и рисуем круг:
Это и будет нашим спрайтом. Сохраняем в любом формате для вэб (Cntrl + Alt + Shift + S). В данном случае лучше GIF.

Теперь очередь за CSS. Важный момент: т.к. углы позиционируются абсолютно, если отступ у содержимого будет меньше радиуса угла, то картинки с углами будут закрывать содержимое. Этот вопрос решается тем, что диву с содержимым присваивается position:relative и z-index больший, чем z-index у углов (в данном случае — 5 и 10).
Пояснения по атрибутам — в комментариях к коду.
- <style type="text/css">
- /*Параметры блока*/
- .r_block {
- position:relative;
- min-height:150px;
- width:500px;
- background:#777;
- }
- /*Общие свойства углов и радиус закругления*/
- .r_block h1, .r_block h2, .r_block h3, .r_block h4 {
- display:block;
- position:absolute;
- z-index:5;
- /*Обнуляем margin, т.к. у элементов h1, h2 и т.п. по-умолчанию присутствует внешний отступ*/
- margin:0;
- /*Задаём меньший шрифт, т.к. по-умолчанию у этих элементов шрифт больше, и IE раздвигает их под размер шрифта, не смотря на заданную высоту.*/
- font-size:1px;
- /*высота и ширина = радиус*/
- width:15px;
- height:15px;
- }
- /*Позиционируем углы и задаём им фон*/
- .r_block h1 {
- left:0;
- top:0;
- /*Описание свойств фона описано в краткой форме, где url — адрес изображения, no-repeat — свойство запрещающее повтор, left top — позиционирование фона*/
- background:url(r15.gif) no-repeat left top;
- }
- .r_block h2 {
- right:0;
- top:0;
- background:url(r15.gif) no-repeat right top;
- }
- .r_block h3 {
- right:0;
- bottom:0;
- background:url(r15.gif) no-repeat right bottom;
- }
- .r_block h4 {
- left:0;
- bottom:0;
- background:url(r15.gif) no-repeat left bottom;
- }
- /*Стиль и отступ для содержимого*/
- .r_b_content {
- color:#FFF;
- margin:5px;
- position:relative;
- z-index:10;
- }
- </style>
Если убрать все комментарии и записать код компактно, получится намного меньше:
- <style type="text/css">
- .r_block {position:relative;min-height:150px;width:500px;background:#777;}
- .r_block h1, .r_block h2, .r_block h3, .r_block h4 {display:block;position:absolute;z-index:5;margin:0;font-size:1px;width:15px;height:15px; }
- .r_block h1 {left:0;top:0;background:url(r15.gif) no-repeat left top;}
- .r_block h2 {right:0;top:0; background:url(r15.gif) no-repeat right top;}
- .r_block h3 {right:0;bottom:0; background:url(r15.gif) no-repeat right bottom;}
- .r_block h4 {left:0;bottom:0;background:url(r15.gif) no-repeat left bottom;}
- .r_b_content {color:#FFF;margin:5px;position:relative;z-index:10;}
- </style>
Проблемы в IE6.
Конечно же мы не можем обойти стороной этот подарок судьбы от Микрософта. Проблемы в нем следующие:
- IE6 не понимает атрибут min-height, а атрибут height в нем работает именно как min-height. Поэтому, если ваш блок тянется по высоте, для всех браузеров мы указываем min-height, а для IE6 — height.
- При нечетном размере, IE неправильно позиционирует элементы. Эта проблема решается через expression.
Для решения этих проблем мы пишем условный комментарий, который понимает только IE, в который записываем исправления. Это не нарушает W3C-валидативность. Выглядит это так:
- <!--[if IE 6]>
- <style type="text/css">
- .r_block {
- height:150px; }
- .r_block h3, .r_block h4 {
- bottom: expression( this.parentNode.offsetHeight % 2 ? -1 : 0 );
- }
- .r_block h2, .r_block h3 {
- right: expression( this.parentNode.offsetWidth % 2 ? -1 : 0 );
- }
- </style>
- <![endif]-->
Вот, в общем-то, и всё. Выглядит в результате это так:
Исходники: