Ссылка с возможностями блока

Автор: Евгений Рыжков Дата публикации: 15.02.2010

Задача

Сделать ссылку для вот такого блока

пример ссылки-блока

При чем кликабильной должна быть вся область блока.

На что стоит обратить внимание:

  • ссылка должна иметь четко заданную ширину (width)
  • ссылка должна иметь четко заданную высоту (height)
  • ссылка должна иметь внутренние отступы (padding)

Для облегчения задачи упустим тот факт, что такой блок в реальных условиях может быть еще и резиновым.

ссылка-блок имеет четкие размеры и внутренние отступы

Когда я первый раз столкнулся такой задачей, первое, что пришло мне в голову — сделать все предельно просто:

<a href="#">Информация о Германии</a>
a {
	width: 71px;
	height: 33px;
	background: (path-to/about-germany.png);
	padding: 20px 30px 20px 83px;
}

Попробовав так сделать и посмотрев на результат, вспомнил, что размеры и padding-top / padding-bottom работают только для элементов уровня блок. А ссылка у нас — это строчный элемент. Какие проблемы? Сейчас сделаю блок!

<a href="#"><div>Информация о Германии</div></a>
a div {
	width: 71px;
	height: 33px;
	background: (path-to/about-germany.png);
	padding: 20px 30px 20px 83px;
}

Это сработало. Но радовался я не долго. Проверка на соотвествие стандартам меня несколько огорчила:

нельзя вкладывать тег div в a

Оказалось, что элементы уровня блок нельзя вкладывать в элементы уровня inline (строчные элементы). Еще подумав, пришел к выводу, что без помощи javascript тут не обойтись:

<div onclick="location.href='#'">Информация о Германии</div>

Это решение соответствовало дизайну и проходило валидацию. В таком виде я сдал работу, в которой впервые встретилась подобного рода ссылка. Неудивительно, что этот заказчик больше никогда и ничего у меня не заказывал. Ведь я сделал из простой задачи большую проблему, и решить ее смог только с помощью javascript. А достаточно знать немного лучше CSS и тогда решение становится простым и изящным:

<a href="#">Информация о Германии</a>
a {
	display: block; /* меняем способ отображения элемента на блочный */
	width: 71px;
	height: 33px;
	background: (path-to/about-germany.png);
	padding: 20px 30px 20px 83px;
}

Посмотреть результат.

Более сложный вариант

Чтобы лучше усвоить урок, усложним задачу:

более сложная ссылка

Такая задача — обычное дело при верстке каталогов товаров, интернет магазинов. Чтобы было понятней в чем сложность, приведу обычные требования к такому блоку:

  • картинка должна быть вставлена тегом <img>
  • картинка должна скругляться версткой (чтобы редакторы не тратили время на скругление в фотошопе каждой картинки)
  • размеры блока с фото и самого фото жестко фиксированы (чтобы все картинки в каталоге были одинакового размера)
  • фото и текст должны быть кликабильны, при чем в коде должен быть всего один тег <a>

Набросаем себе алгоритм реализации:

  • если нужен только один тег <a>, значит он должен быть основным контейнером
  • т.к. размер фото фиксирован, достаточно будет одного элемента для рамки, которая будет округлять углы фото
  • картинку и рамку разместим с помощью абсолютного позиционирования, причем рамка должна быть поверх фото, чтобы закруглить углы
  • текст разместим в нужном месте за счет внутренних отступов (padding)
текст позиционируем внутренними отступами ссылки

Подготовим материалы:

фото прямоугольной формы фото, нормальной прямоугольной формы
уголки для скругления рамки с прозрачной центральной частью, и скругленными углами по углам
<a href="#" class="photo">
	<img src="path-to/photo.jpg" width="214" height="160" alt="" />
	<span></span>
	Экстерьер и интерьер
</a>
.photo a {
	display: block;
	width: 181px;
	padding: 176px 20px 0 15px; /* позиционируем текст внутренними отступами */
	text-transform: uppercase;
	font-size: 11px;
	color: #298db2;
	position: relative; /* чтобы дочерние элементы позиционировались относительно границ ссылки-контейнера */
}
.photo a:hover {
	color: #FF0000;
}
.photo a img {
	position: absolute; /* фото и скругленние углов позиционируется абсолютно, чтобы не влиять на положение текста */
	top: 0;
	left: 0;
	z-index: 1; /* у фото должен быть z-index меньше, чем у скругленных углов чтобы рамка с углами была на фото */
}
.photo a span { /* в ссылку вкладываем span: нейтральный элемент и код будет валидным */
	display: block; /* отображение span меняем на блок */
	width: 215px;
	height: 160px;
	background: url(path-to/photo-corners.png); /* рамка с прозрачным содержимым и скругленными углами */
	position: absolute;
	top: 0;
	left: 0;
	z-index: 2; /* рамка должна быть над фото */
	cursor: pointer; /* чтобы IE вложенным элементам при наведении тоже показал правильный указатель */
}

Посмотреть результат.

Заметка

В данной ситуации можно было не указвать явно z-index, т.к. элемент идущий по коду ниже, будет расположен выше по z-оси.

Проверено в:

Такой техникой можно смело верстать более сложные конструкции с большим количеством вложенных элементов и при этом код будет оставаться валидным.