Начало · Справочники · Курсы · Разговоры

leechy.ru · Сайт почти придуман

Как сверстать уголки для блока

Доброе утро.

Эта статья об одном из способов сверстать блок с углами отличными от прямоугольных. В 99% случаев «уголки отличные от прямоугольных» — это просто части окружности (если это ваш случай, посмотрите статью «Закругленные уголки»), но на самом деле это просто способ засунуть по углам блока любую картинку и даже любой элемент, и поэтому я буду использовать совсем не окружность.

В данном примере (рис. 1) есть блок, в углах которого должен быть расположен некий орнамент. Загвоздка здесь еще в том, что внутренние отступы в блоке (от рамки до текста) равны 10 пикселей, а размеры орнамента — 25×25px. Еще условие — известен цвет фона блока (и орнамента), но неизвестен цвет фона, который может быть какой угодно. Ширина и высота блока тоже плавающие — ширина, скажем в процентах от ширины родительского блока, а высота — в зависимости от текста.

Самое простое, что можно придумать в этой ситуации — вытрести из дизайнера какой все-таки будет фон, сделать четыре картинки и распихать их в абсолютно расположеных элементах по углам. Попутно сделав какой-нибудь фикс для эксплореровского глюка с нечетными значениями для right и bottom.

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

Каркас

Итак, для начала определимся с каркасом. Нам нужно закрасить однородным цветом область показанная на рис. 2. Каркас сделаем из трех элементов (плюс один обрамляющий все). Верхний и нижний с фиксированой высоты и с внешними отступами слева и справа — в зависимости от размеров картинки, располагаемую в углах, в нашем случае — по 25px. А тот, который посередине — просто блок, который закрашен цветом фона.

Стили и HTML представлю отдельно, скорее всего у вас будет также. У контейнера будет класс fancy-corners, остальные стили будут плясать от него. Класс у верхнего блока будет t (от слова top), у нижнего — b (bottom), а посередине — c (content).

Пример 1: основные элементы каркаса
Закрашеный блок, по углам которого расположен просто идиотский орнамент вызывающий тошноту
CSS
.fancy-corners .t, .fancy-corners .b { 
   height: 25px;
   margin: 0 25px;
} 
.fancy-corners .t, .fancy-corners .b, .fancy-corners .c { 
   background-color: #345488;
} 
.fancy-corners .c { 
   color: white;
} 
01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
HTML
<div class="fancy-corners"> 
	<div class="t">
	<div class="c">Закрашеный блок, по углам которого расположен просто идиотский орнамент вызывающий тошноту</div>
	<div class="b">
</div> 
01 
02 
03 
04 
05 

Контент

Сделать каркас совсем несложно. Но как видно из примера, есть одна проблема, которая должна быть решена — содержимое блока находится только в центральном блоке, не имеет отступов, и даже если поставить ему padding: 10px, все-равно отступ от верхнего края будет никак не меньше 25px, а нужен — 10px!

Поэтому мы воспользуемся еще одним элементом, который будет расположен внутри блока <div class="c"/> и у которого будут отрицательные внешние отступы сверху и снизу. Это должно привести к тому, что содержимое контентного блока будет большим по высоте, чем контейнер, т. е. начинаться выше и заканчиваться ниже. Отступы будут такие же, как высота уголков — минус 25 пикселей. Для этого элемента дадим класс f (fix). Здесь добавим и правильный внутренний отступ в 10 пикселей.

Пример 2: растягиваем контент по высоте
Закрашеный блок, по углам которого расположен просто идиотский орнамент вызывающий тошноту
CSS (добавлено)
.fancy-corners .f {
   margin: -25px 0;
   padding: 10px;
} 
01 
02 
03 
04 
HTML
<div class="fancy-corners"> 
   <div class="t">
   <div class="c">
      <div class="f">Закрашеный блок, по углам которого расположен просто идиотский орнамент вызывающий тошноту</div>
   </div>
   <div class="b">
</div> 
01 
02 
03 
04 
05 
06 
07 

Проблемы с выпрыгиванием

Ой! В примере видно, что пропали дырки, которые мы оставили специально для уголков. К сожалению, есть такой момент в HTML отвечающий за «схлопывание» внешних отступов (margins), который переносит отступы внутренного элемента на внешнем, если у него нет рамки или внутренного отступа. Поэтому поставим внутренний отступ в 1px и, соответственно, увеличим отрицательный отступ до 26px.

Пример 3: чиним выпрыгивание контента из контейнера
Закрашеный блок, по углам которого расположен просто идиотский орнамент вызывающий тошноту
CSS (добавлено и изменено)
.fancy-corners .c {
	padding: 1px 0;
} 
.fancy-corners .f {
	margin: -26px 0;
} 
01 
02 
03 
04 
05 
06 

Стоп, стоп. В эксплорере все еще что-то не так. Отступ сверху есть, а снизу все равно все плохо. К сожалению, это уже не фича HTML, а глюк браузера, который можно исправить только очень радикальным способом — приведя родительский блок в состояние hasLayout (через свойство zoom — самый безболезненный метод) и вытащив контент поверх других элементов с помощью z-index.

Осторожно!

Осторожно!

Всегда, когда используете свойство z-index или даже просто position отличный от static, следует помнить о том, как работает позиционирование элементов по координате Z и избегать возможные конфликты выставляя правильные значения.

Об этом на сайте скоро появиться отдельная статья.

Пример 4: правки для Internet Explorer
Закрашеный блок, по углам которого расположен просто идиотский орнамент вызывающий тошноту
CSS (добавлено — только для Internet Explorer)
.fancy-corners .c {
   zoom: 1;
} 
.fancy-corners .f {
   zoom: 1;
   position: relative;
   z-index: 2;
} 
01 
02 
03 
04 
05 
06 
07 
08 

Уголки

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

Каждый уголок, это плавающий элемент. Левые — влево, правые — вправо. Размеры заданы жестко — высота и ширина уголка заранее известны. Уголки, еще и относительно позиционированы и смещенны на нужное количество пикселов влево и вправо соответственно, в нашем случае — на 25 пикселей.

Пока, для наглядности, покрасим эти элементы в желтом. Классы у элементов l (left) и r (right).

Пример 5: ставим уголков на место
Закрашеный блок, по углам которого расположен просто идиотский орнамент вызывающий тошноту
CSS (добавлено)
.fancy-corners .l, .fancy-corners .r {
   width: 25px;
   height: 25px;
   position: relative;
   background-color: #ffdf3a;
} 
.fancy-corners .l {
   float: left;
   left: -25px;
} 
.fancy-corners .r {
   float: right;
   left: 25px;
} 
01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
11 
12 
13 
14 
HTML
<div class="fancy-corners"> 
   <div class="t">
      <div class="r">
      <div class="l">
   </div>
   <div class="c">
      <div class="f">Закрашеный блок, по углам которого расположен просто идиотский орнамент вызывающий тошноту</div>
   </div>
   <div class="b">
      <div class="r">
      <div class="l">
   </div>
</div> 
01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
11 
12 
13 

Нежелательное обтекание текста

К сожалению, видим, что эти элементы мешаются тексту в Firefox и Opera. Да и на самом деле текст должен обтекать плавающие элементы (хоть и из-за отрицательного отступа), так что поведение Safari можно считать ошибкой (в Internet Explorer, это блоки hasLayout и они уже не влияются внешними блоками). Недолго думая, в каких элементов текст не попадает под влиянием внешних плавающих элементов, вспомнил таблицу. Так что элементу, который чинит нам отступы — <div class="f"/> скажем, что он на самом деле таблица.

Пример 6: убираем обтекание
Закрашеный блок, по углам которого расположен просто идиотский орнамент вызывающий тошноту
CSS (добавлено)
.fancy-corners .f {
	display: table;
}
01 
02 
03 

Картинки

Теперь осталось всего-лишь в уже подготовленных для уголков элементов поставить картинки. Это можно сделать самыми разными способами: поставить четыре разных картинки в фоне каждого элемента; использовать одну картинку и позиционировать фон; если нужен PNG с полупрозрачностью и интересуют Internet Explorer 5.5 и 6.0 — использовать в каждом уголке еще абсолютно расположенный элемент, которого двигать с помощью CSS-свойств left и top. У всех свои преимущества и недостатки, которые тысячу раз описаны. В данном примере я использую одну картинку в фоне, который позиционирую по разному в каждом из уголков, но в вашем конкретном случае — выбор за вами.

Пример 7: добавляем картинки
Закрашеный блок, по углам которого расположен просто идиотский орнамент вызывающий тошноту
CSS (добавлено)
.fancy-corners .t .l {
   background: url('./fancy-corners.png') no-repeat;
} 
.fancy-corners .t .r {
   background: url('./fancy-corners.png') no-repeat right top;
} 
.fancy-corners .b .l {
   background: url('./fancy-corners.png') no-repeat left bottom;
} 
.fancy-corners .b .r {
   background: url('./fancy-corners.png') no-repeat right bottom;
} 
01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
11 
12 

Весь код и пример для скачивания

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

CSS для всех браузеров

.fancy-corners {
   width: 20%; /* ширина блока, если он уже в нужной колонке можно не указывать */
} 
.fancy-corners .t, .fancy-corners .b {
   height: 25px; /* высота уголков, если у верхних и нижних уголков она разная - нужно указать отдельно */
   margin: 0 25px; /* ширина уголков, если у разных уголков она разная - можно указать значения отступов слева и справа отдельно */
   position: relative;
} 
.fancy-corners .t, .fancy-corners .b, .fancy-corners .c {
   background-color: #345488; /* цвет фона блока */
} 
.fancy-corners .c {
   color: white; /* цвет текста в блоке */
   padding: 1px 0;
} 
.fancy-corners .f {
   margin: -26px 0; /* отрицательное значение высоты уголков минус один пиксель, для верхних и нижних уголков можно укзать разные значения, если необходимо */
   padding: 10px; /* внутренние отступы от краев блока до его содержимого */
   display: table;
} 
.fancy-corners .l, .fancy-corners .r {
   width: 25px; /* ширина уголков, для верхних/нижних/левых/правых можно указать разные селекторы с необходимыми размерами */
   height: 25px; /* высота уголков - также можно указать нужные размеры в разных селекторах */
   position: relative;
} 
.fancy-corners .l {
   float: left;
   left: -25px; /* отрицательное значение ширины левых уголков */
} 
.fancy-corners .r {
   float: right;
   left: 25px; /* ширина правых уголков */
} 
/* картинки */
.fancy-corners .t .l {
   background: url('./fancy-corners.png') no-repeat; /* фон для верхнего левого уголка */
} 
.fancy-corners .t .r {
   background: url('./fancy-corners.png') no-repeat right top; /* фон для верхнего правого уголка */
} 
.fancy-corners .b .l {
   background: url('./fancy-corners.png') no-repeat left bottom; /* фон для нижнего левого уголка */
} 
.fancy-corners .b .r {
   background: url('./fancy-corners.png') no-repeat right bottom; /* фон для нижнего правого уголка */
} 
01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 

CSS для Internet Explorer

.fancy-corners .c {
   zoom: 1;
} 
.fancy-corners .f {
   zoom: 1;
   position: relative;
   z-index: 2;
} 
01 
02 
03 
04 
05 
06 
07 
08 

HTML-код

<div class="fancy-corners"> 
   <div class="t"><div class="l"><div class="r"></div>
   <div class="c">
      <div class="f">Закрашеный блок, по углам которого расположен просто идиотский орнамент нызывающий тошноту</div>
   </div>
   <div class="b"><div class="r"><div class="l"></div>
</div> 
01 
02 
03 
04 
05 
06 
07