Дивные дивы

Дивные дивы

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

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

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

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

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

  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

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

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
Мне понравилось:) Буду использовать:)

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

как выглядит какой тег
жирный текст <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>
разрешенные теги или посмотреть как будет выглядеть
counter strike mt2 silkroad pvp metin2 metin2 pvp knight pvp gm olarak başlayan pvpler pvp silkroad pvp serverler counter strike serverler msn show cam show görüntülü sohbet oyunlar suskunlar gazete oku