Дивные дивы

Дивные дивы

Сперва, всем привет!

Это моя первая статья, так что посмотрим каким вкусным этот блин будет.

Так как я больше серверный программист, чем клиентщик, очень часто бывает ситуация, когда надо быстро сверстать страницу, и вот тут начинаются проблемы. Вроде все помнишь, но мысли разбредаются и в итоге тратишь много времени на воспоминания и вычитывание статей.

Как правило, все всегда есть и поиски завершаются успехом, но есть одно но. В основном вся информация на английском. И даже если знаешь язык нормально, все равно приходится напрягаться. Даже из-за таких простых вещей. Но, все в наших руках!

Сегодня мы рассмотрим две темы:

  1. Как расположить несколько div’ов горизонтально так, чтобы они никуда не уплывали.
  2. Как сделать два горизонтально расположенных div’а одинаковой высоты.

Ничего нового я не скажу, это всего лишь перевод этой и вот этой статей с woorkup.com. Приступим.

Сразу скажу, что Антонио Лупетти делает в общем правильное дело — борется с IE6. Так что оба совета не для старого ослика. С другой стороны, даже столь неповоротливая организация-заказчик, на которую я работаю, и то инициализировала переход. Правда, пока только инициализировала...

Так же добавлю от себя, что обе эти проблемы можно решить с использованием списков <UL>, но это не совсем элегантно. Каждый инструмент лучше использовать по его непосредственному назначению.

Как расположить несколько div'ов в горизонтальной плоскости

Основная идея этого совета — использовать div-обертку (wrapper) и селектор CSS :first-child.

Итак, дано: сделать на странице несколько блоков, равномерно распределенных по горизонтали:

Исходный код такой разметки предельно прост:

<div id="wrapper">
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
</div>

Для того, чтобы горизонтально расположить блоки в оболочке, нам потребуется всего несколько строк CSS кода. Первое, что приходит в голову: объявить класс .section со свойствами width и margin-right, с нужными нам значениями. Но при этом правый отступ крайнего правого элемента будет выступать за границы оболочки:

Так как правый отступ крайнего правого элемента превышает ширину оболочки, по правилам разметки крайний правый блок «уйдет» вниз:

Возникает вопрос: как убрать «лишний» отступ у крайнего правого блока без специального CSS класса, у которого свойство margin-right будет задано 0?

Именно здесь и стоит вспомнить о селекторе :first-child, и инвертировать правые отступы на левые. Таким образом, чтобы у первого блока отступ слева был нулевым. Напрашивается вопрос: зачем инвертировать? Все дело в том, что в IE7|8 поддержка :first-child добавлена, а :last-child нет. Экономят?

Итак, давайте посмотрим на CSS код решения. Сперва определим оболочку:

#wrapper {
width:320px;
height:60px;
background:#EFEFEF;
}

Теперь объявим класс  содержимого оболочки .section:

.section {
border:solid 1px #999;
float:left;
height:58px;
margin-left:10px;
width:98px;
}

В примере используются фиксированные значения свойств width и margin-left. Вы на свое усмотрение можете использовать и процентные отношения.

Теперь нам надо убрать отступ слева у первого блока, делается это так:

#wrapper div:first-child {
margin-left:0px;
}

Как уже было сказано выше, единственный недостаток этого подхода то, что IE6 не поддерживает селектор  :first-child. В этом случае придется использовать условные комментарии для того, чтобы объявить-таки отдельный класс (например, .section-first). Свойства этого класса будут с теми же значениями, что в классе .section, только свойство margin-left = 0.

Как сделать несколько div'ов одинаковой высоты

В этом туториале Антонио предлагает реализацию фиктивных колонок, равных по высоте, с использованием CSS свойств position: absolute и border.

Представим, что у нас задача: надо реализовать разметку на две колонки так, чтобы высота боковой колонки была равна высоте основной. Иллюстрация такой задачи ниже:

Сначала опишем такую разметку:

<div id="wrapper">
<div id="maincontent">...</div>
<div id="sidebar">...</div>
</div>

Как и в предыдущем примере, у нас есть div-оболочка, в которой содержатся «подопытные» блоки.

CSS-код оболочки выглядит вот так:

#wrapper {
margin:0 auto;
width:600px; }

Рассмотрим теперь по-отдельности каждую из колонок.

Главная колонка

Главная колонка представлена id #maincontent. Она будет содержать основное содержимое страницы (например, посты). Иллюстрация показывает основную фишку этого туториала:

У колонки правая граница задана очень большой (border 200px). Эта граница и будет представлять собой место для вспомогательной колонки (#sidebar). Для этого задана фиктивная заливка фона #sidebar, которая будет иметь ту же высоту, что и основная. Описание стиля главной колонки ниже:

#maincontent {
border-right:solid 200px #DFDFDF;
position:absolute;
width:400px;
}
Вспомогательная колонка

Все, что нам осталось, описать #sidebar:

#sidebar {
background:#DFDFDF;
margin-left:400px;
position:absolute;
width:200px;
}

Ширина вспомогательной колонки должна быть такой же, как ширина границы основной колонки (200px), а левый отступ margin-left должен быть равен ширине содержимого #maincontent.

Вот что получается в результате:

Недостатки этого способа

Везде и во всем есть недостатки, этот способ верстки не исключение. Во-первых, ширина колонок должна быть фиксированной. Во-вторых, фон у них должен быть одинаковый. И в-третьих, вспомогательная колонка всегда должна быть по высоте меньше, чем основная.

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

#wrapper{
overflow: hidden;
margin:0 auto;
width:600px;
}
#maincontent, #sidebar{
float: left;
padding-bottom: 9999px;
margin-bottom: -9999px;
}
#maincontent{
background:#ccc;
width:400px;
}
#sidebar{
background:#DFDFDF;
width:200px;
}

Ну и, в качестве последней приманки (или десерта): приз!

Расскажите друзьям

Оцените статью:
  • 1
  • 2
  • 3
  • 4
  • 5

Комментарии — 26

switch
Спасибо. Замечательная статья!
#
switch
Vadim
Браво! :)
FisheR
Супер! Спасибо!
FisheR
А за приз отдельное спасибо!!! ;-)
spike
Спасибо за отзывы!
Статья переводная, так что все труды ушли на приз. =)
#
spike
akatadke
По-моему, не самые удачные решения для поставленных задач. Для первого случая существует кроссбраузерное решение, в котором используется дополнительная обертка, и лишний отступ справа убирается с помощью oveflow:hidden. Во втором случае вообще-же написано черезчур узкое решение, так как применяется абсолютное позиционирование и колонки вырываются из общего потока. К тому же, это всего лишь симуляция одинаковой высоты
#
akatadke
spike
akatadke,
если не сложно, дай мне ссылку на это решение. Или (что будет еще лучше), напиши его в комментарии. Хотя бы просто скинь css.

Насчет второго так и есть -- симуляция. Есть много других способов, так что это один из. В оригинальной статье множество комментариев по этому поводу, но все способы так или иначе вырывают блоки из контекста и/или используют горы костылей.
Плюс, конечно, для этих целей можно использовать js. И в jquery, и в mootools есть решения.
#
spike
RagnarR
Статья очень хорошая. Спасибо за работу.
#
RagnarR  
ujifgc
Вот это решение 2 задачи даёт реальную высоту правой колонке. Для ие6 не подходит (он не растягивает #slave куда надо).

<style>
#container {
 position: relative;
 width: 50%;
}
#master {
 width: 70%;
 background: #ccc;
}
#slave {
 position: absolute;
 top: 0;
 bottom: 0;
 left: 71%;
 right: 0;
 background: #aaa;
}
</style>
<div id=container>
  <div id=master> foo<br>foobar<br>bar </div>
  <div id=slave> bar </div>
</div>
#
ujifgc  
akatadke
spike,
Например, для фотогалерей я обычно использую следующую разметку:
<div>
	<ul>
		<li><img src="1.jpg" alt=""></li>
		<li><img src="2.jpg" alt=""></li>
		<li><img src="3.jpg" alt=""></li>
		<li><img src="4.jpg" alt=""></li>
		<li><img src="5.jpg" alt=""></li>
		<li><img src="6.jpg" alt=""></li>
	</ul>
</div>

С такими вот, например, стилями
div {
	width: 340px;
	overflow: hidden;
	margin:0;
	padding:0;
}
ul {
	list-style:none;
	width: 360px;
	background: #ccc;
	overflow: hidden;
	margin:0 -20px -20px 0;
	padding:0;
}
li {
	display:block;
	float:left;
	padding:0 20px 20px 0;
}
img {
	display:block;
	height:100px;
	width:100px;
}
#
akatadke
spike
akatadke,
спасибо! Я это и имел в виду, когда писал, что расположить горизонтально можно с помощью списка. Это подходит для атомарных элементов (картинок, пунктов меню). Но верстать, например, меню (целиком) и блок с постами в блоге с помощью списков... не то.

ujifgc,
спасибо! Больше мнений, хороших и разных! =)
#
spike
Nail
По поводу задачи с двумя колонками. Предложенное решение (даже два решения) обладают следующими существенными недостатками:
1) sidebar должен быть строго меньше по высоте, чем maincontent
2) невозможность задать для sidebar фон, отличный от сплошной заливки (например, фоновая картинка). Сюда же относим все остальные проблемы, связанные с тем, что sidebar реально имеет не ту же саму высоту, как maincontent: потребность в своем бордере, наличие блоков, которые могут позиционироваться относительно sidebar и т.п.

Самое лучшее решение, которое существует, предложил Чикуенок:
http://chikuyonok.ru/2009/06/float-columns/
Хотя и у него есть ограничения, например, фиксированная ширина колонок.
#
Nail
Alexander
Спасибо за статью.
Но было бы еще лучше ссылки на реальные примеры того, что вы проделали.
... "вот что у нас получилось _ссылка_".
#
Alexander
spike
Alexander,
спасибо, я это учту в будущем. Здесь сделал, как было в оригинале.
#
spike
dgl
Для расположения дивов в горизонтальной плоскости сущесвтует свойство display: inline-block. Для того, чтобы этот способ сработал в IE7 и ниже, нужно сделать элемент инлайновым и задать ему hasLayout.
#
dgl
Автор
Спасибо автору, давно искал подобное решение...вечно уходят правая часть куда-то......
Жасулан
Статья говно
#
Жасулан
duncan
одно "но", псевдостиль "ферст-чайлд" не понимает долбанный шестой ишак.
Makito
Первый способ я реализую следующим образом:
1. задаю отступ блокам не справа а слева
2. для того чтобы погасить отступ первых блоков в строках, блоку-обертке задаю отрицательный левый отступ равный величине отступа у блоков
#
Makito
Александр
С блэкджеком и ш... :) Да..

Есть что почерпнуть новенького. За информацию спасибо. Статья получилась.

Насчет выравнивания колонок - я обычно пускаю фон - в принципе самый кроссбраузерно оптимальный вариант.
#
Александр
skforussia
спасибо за отличный обзор
Ranerg
Мне понравилось:) Буду использовать:)
noys
Приз полный трындец, чуть не упал со стула.
#
noys
Владимир
Большое спасибо!
Получилось все отлично - http://manualov.net/Acura-manuals.php

Новый комментарий

как выглядит какой тег
жирный текст <b>жирный текст</b>
курсивный тект <i>курсивный тект</i>
зачеркнутый текст <s>зачеркнутый текст</s>
подчеркнутый текст <u>подчеркнутый текст</u>
ссылка <a href="адрес">ссылка</a>
function foo() { ... }
<pre><code>function foo() { ... } </code></pre>
разрешенные теги или посмотреть как будет выглядеть
как выглядит какой тег
жирный текст <b>жирный текст</b>
курсивный тект <i>курсивный тект</i>
зачеркнутый текст <s>зачеркнутый текст</s>
подчеркнутый текст <u>подчеркнутый текст</u>
ссылка <a href="адрес">ссылка</a>
function foo() { ... }
<pre><code>function foo() { ... } </code></pre>
разрешенные теги или посмотреть как будет выглядеть

metin2 pvp metin2 pvp serverler pvp serverler