Центрирование резинового блока по горизонтали

Автор: Татьяна Шкабко, Александр Головко Дата публикации: 30.07.2010

Представь типичный фрагмент сайта: фотография, а под ней ссылка с выравниванием по-центру:

фотография с кнопкой, выровненной по центру

Тут все просто. Самое долгое в верстке этого блока — вырезать фотографию. Давай немного усложним задачу: ссылка должна выглядеть как кнопочка (т.е. иметь фон). Например, такой:

фотография с кнопкой, выровненной по центру

Тоже легко? Контейнеру text-align: center, ссылке display: block, margin: 0 auto, фон и ширину… Стоп! А если ссылка-кнопка резиновая? Ширину-то задавать и нельзя! А без нее блочный элемент разъедется на все доступное пространство. Как же его подогнать под размер содержимого?

Как вариант задать float, например, left. Элемент останется блочным, а значит фоновый рисунок не пострадает, и сожмется до размеров содержимого. Решения найдено? Как бы не так! Теперь margin: 0 auto не работает и кнопка преспокойненько прилипла к левому краю!

Ну и дела! Похоже придется задавать margin-left в зависимости от ширины надписи…

Пробуем включить мозг. Итак:

  1. Чтобы присвоить фоновую картинку ссылке, ее нужно сделать блочной.
  2. Чтобы спозиционировать блочный элемент по центру экрана нужно задать ему ширину, иначе он растянется на всю ширину родительского элемента.
  3. Чтобы элемент не растягивался на всю ширину родителя для него обычно прописывают float: left, но тогда он будет выровнен по левому краю и ему нужно задать отступ слева. Но я не знаю, какой будет отступ слева, потому, что он зависит от ширины кнопки!

То есть я не могу сделать ссылку строчной, потому что у нее есть высокая фоновая картинка, и не могу выровнять резиновую блочную ссылку по центру. Ни display: inline, ни display: block в этом случае не подходят. Вот если бы было так, чтобы одновременно и по центру как display: inline и с картинкой, как display: block…

А ведь именно так и можно сделать! В спецификации CSS2 у свойства display специально на этот случай есть значение inline-block, которое превращает элемент в строчный блок.

Таким образом, решением данной задачи будет следующий код:

	<div class="parent">
		<div class="forImg">
			<img src="path-to/img-inline-block.png" width="200px" height="150px" alt="Аватарка с улиткой" />
		</div>
		<a class="button" href="#">Комментировать<span></span></a>
	</div>
.parent{
	text-align: center;
}
.button{
	display: inline-block;
	color: #fff;
	position: relative; 
	margin: 0 auto;
	line-height: 32px;
	padding: 0px 6px 0 10px;
	font-size: 12px;
	background: url(path-to/inline-block-button.png) no-repeat;
	text-decoration: none;
	cursor: pointer;
}
.button span{
	position: absolute;
	width: 5px;
	height: 32px;
	right: -4px;
	top: 0;
	background: url(path-to/inline-block-button-cup.png) no-repeat;
}
		

Демонстрационный пример

Проверено в:

Такой вариант подойдет для выравнивания любого строчного элемента. Для блочных это тоже работало бы, если бы не одно мелкомягкое НО. Да, ты конечно понял, какое. Я даже не удивился — display: inline-block неправильно работает с блоками в IE6 и даже IE7.

Тем не мение, как всегда, имеется способ побороть разработки Microsoft, к тому же их же оружием. А именно, используя Microsoft свойство hasLayout!

Для того, чтобы все заработало, придется сделать элемент строчным принудительно, задав display: inline, а уже потом присвоить ему layout. В данной ситуации сделать это можно, прописав zoom: 1.

Решение нашей задачи с блочным элементом в главной роли:

	<div class="parent">
		<div class="forImg">
			<img src="path-to/img-inline-block.png" width="200px" height="150px" alt="Аватарка с улиткой" />
		</div>
		<div class="button">Комментировать<span></span></div>
	</div>
.parent{
	text-align: center;
}
.button{
	position: relative;
	margin: 0 auto;
	line-height: 32px;
	padding: 0px 6px 0 10px;
	font-size: 12px;
	background: url(path-to/inline-block-button.png) no-repeat;
	text-decoration: none;
	cursor: pointer;
	display: inline-block;
	//display: inline;
	zoom: 1;
}
.button span{
	position: absolute;
	width: 5px;
	height: 32px;
	right: -4px;
	top: 0;
	background: url(path-to/inline-block-button-cup.png) no-repeat;
}
		

Демонстрационный пример

Проверено в:

  • IE 6-8
  • Firefox 3.0
  • Opera 9.5-10.5
  • Safari 4
  • Chrome 5

Не забудь, что свойство zoom невалидно. Поэтому в боевых условиях выноси его и хак для IE в отдельный CSS, подключаемый с помощью условных комментариев.

Заметка

Также display: inline-block не работает в Firefox 2 и его эмулируют используя вендорное значение display: -moz-inline-stack. Эта информация носит скорее ознакомительный характер, потому что процент пользователей Firefox 2 падает с каждым днем и, думаю, с ним не стоит заморачиваться.

Выводы

Резиновый строчный элемент с фоном можно выровнять по центру родителя просто присвоив родителю text-align: center, а элементу display: inline-block, который превратит элемент в строчный блок.

Резиновый блочный элемент для всех нормальных браузеров выравнивается точно так же. Для IE6-7 алгоритм такой:

  1. В правилах для IE6-7 сделать элемент строчным (display: inline).
  2. Установить этому элементу layout.