Выравнивание навигации из блоков по центру
Задача
Есть навигация (список ul). Каждый элемент списка (li) — блочный. Количество элементов навигации заранее не известно. Список в виде строки (li имеют свойство float: left/right), для того чтоб навигация была в одну строку. Нужно выровнять эту навигацию по середине родителя
Имеем следующий HTML:
<div class="parent">
<ul>
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li>3</li>
<li><a href="#">4</a></li>
</ul>
</div>
и CSS:
.parent {
width: 100%;
text-align: center; /*пытаемся выровнять содержимое по центру */
padding: 20px 0;
background: #6699FF; /* для наглядности обозначаем родителя */
float: left; /* чтоб высота родителя была с учетом плавающих потомков */
}
ul {
list-style: none;
font-size: 12px;
margin: 0 auto;
padding: 0;
}
li {
float: left; /* выстраиваем блочные элементы в ряд */
margin-right: 4px;
width: 23px;
height: 19px;
overflow: hidden;
text-align: center;
color: #fff;
font-weight: bold;
position: relative; /* для удобного размещения ссылки внутри */
background:url(images/testFonNeactiv.png); /* фоновая картинка текущей страницы*/
cursor: default;
padding-top: 3px;
}
li a {
color: #fff;
text-decoration: none;
position: absolute;
top: 0;
left: 0;
display: block;
background:url(images/testFonActiv.png);
text-align: center;
width: 23px;
height: 22px;
padding-top: 3px;
}
Как видно на примере обычное выравнивание блока по центру относительно родителя в этом случае не срабатывает, т.к. нет четко заданной ширины блока навигации.
Решение
Для решения этой проблемы используем конструкцию:
<div class="parent">
<span><!--или любой другой элемент уровня inline (строчный)-->
<ul>
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
</ul>
</span>
</div>
CSS:
.parent {
width: 100%; /* ширина нужна, только если блок плавающий (float) */
text-align: center; /* обязательно делаем выравнивание по центру */
float: left; /* в данном примере float нужен чтобы высота блока была с учетом плавающего содержимого */
padding: 20px 0;
background: #6699FF;
}
ul {
display: table; /* элемент типа таблицы имеет ширину, зависящую от содержимого */
width: auto; /* для уверенности что ширина будет зависеть от содержимого*/
margin: 0 auto; /* устанавливаем отступ слева и справа в auto */
list-style: none;
font-size: 12px;
padding: 0;
}
* html .parent span {/*хак для IE6, который не понимает display: table*/
display: inline-block;
}
*:first-child+html .parent span {/*хак для IE7, который не понимает display: table */
display: inline-block;
}
li {
float: left;
margin-right: 4px;
width: 23px;
height: 19px;
overflow: hidden;
text-align: center;
color: #fff;
font-weight: bold;
position: relative;
background:url(images/testFonNeactiv.png);
cursor: default;
padding-top: 3px;
}
* html li {
height: 22px;
}
li a {
color: #fff;
text-decoration: none;
position: absolute;
top: 0;
left: 0;
display: block;
background:url(images/testFonActiv.png);
text-align: center;
width: 23px;
height: 22px;
padding-top: 3px;
}
Результат. Проверено в:
В боевых условиях лучше использовать условные комментарии вместо хаков.
HTML код не пройдет проверку корректности (валидацию), т.к. элементы уровня inline (строчные) не могут содержать элементы уровня блок (блочные). Заменить в этом коде <span> на блочный элемент (например <div>) не получится — в IE навигация останется прижата влево.
Альтернативное решение (валидный код)
Если отказаться от использования списка, можно сделать и по стандартам:
HTML:
<div class="parent">
<span>
<a href="#">1</a>
<a href="#">2</a>
<b>3</b>
<a href="#">4</a>
</span>
</div
CSS:
.parent {
width: 100%;
text-align: center;
padding: 20px 0;
background: #6699FF;
}
span {
font-size: 12px;
margin: 0 auto;
padding: 0;
width: auto;
display: table;
}
* html .parent span {
display: inline-block;
}
*:first-child+html .parent span {
display: inline-block;
}
a, b {
float: left;
margin-right: 4px;
width: 23px;
height: 19px;
overflow: hidden;
text-align: center;
color: #fff;
font-weight: bold;
background:url(images/testFonActiv.png);
padding-top: 3px;
display: inline;
}
* html a, * html b {
height: 22px;
}
b {
background:url(images/testFonNeactiv.png);
cursor: default;
}
Результат. Проверено в:
Заметка
Для более точного центрирования нужно убрать у последнего элемента отступ справа. Или же, если отступы для элементов навигации заданы слева, нужно убрать отступ у первого.
Решение без дополнительных элементов с валидным HTML
update: by Александр Головко.
Это решение не требует дополнительных элементов, является семантичным и оставляет программистам чистый, валидный HTML код. Решение построено на использовании CSS свойства display:inline-block. Навигация реализована списком:
<div class="parent"> <ul> <li><a href="#">1</a></li> <li><a href="#">2</a></li> <li><a href="#">3</a></li> <li>4</li> <li><a href="#">5</a></li> <li><a href="#">6</a></li> </ul> </div>
.parent { text-align: center;/*все строчные элементы будут выравниваться по центру*/ } ul { display: inline-block; /*превращаем элемент в строчный блок*/ //display: inline; /*для IE6-7 превращаем элемент в строчный*/ zoom: 1; /*присваиваем ему layout*/ font-size: 12px;/*устанавливаем размер шрифта*/ } li { float: left;/*делаем блок плавающим*/ display: inline;/*убираем двойные отступы у плавающих блоков в IE6*/ margin-right: 4px; width: 23px; height: 22px; overflow: hidden; text-align: center;/*для того, чтобы центрировать надписи в элементах списка по горизонтали*/ color: #fff; font-weight: bold; background: url(/path-to/nvigatsiya-def.gif) no-repeat; cursor: default;/*для активной страницы*/ line-height: 22px;/*для того, чтобы центрировать надписи в элементах списка по вертикали*/ } li a { color: #fff; text-decoration: none; display: block; width: 23px; height: 22px; background: url(/path-to/nvigatsiya-href.gif) no-repeat; }
Как обычно, невалидный zoom и хак для IE прячем с помощью условных комментариев.
Проверено в: