Век живи — век учись (и дураком помрешь)... В учебниковой статье про float'ы я описывал два варианта "резиновости" колонок: когда их ширины заданы процентным соотношением, и растягиваются все вместе, и когда растягивается только одна основная колонка, а остальные имеют фиксированную ширину.
И вот с этим вторым вариантом (который, кстати, мне нравится больше) я отметил одну проблему: его не получается сделать, если блок с основным содержимым идет в HTML раньше дополнительных.
А сегодня наткнулся на статью Меттью Левина на "A List Apart", где описывается, как это можно сделать. Читать ее надо обязательно, а я постараюсь кратко изложить принцип по-русски.
Принцип я покажу на двух колонках (на ALA рассматривают на трех).
<div id="container">
<div id="main">...</div>
<div id="sidebar">...</div>
</div>
Суть нужной резиновной раскладки в том, что одна из колонок должна иметь ширину "весь контейнер минус константа". Поскольку прямого способа это сделать в CSS нет, я предлагал оставить основную колонку в потоке с автоматической шириной и дать ей боковой фиксированный padding, который будет откладываться внтурь. Это и дает нужный эффект. Но как раз то, что блок остается в потоке, не дает поставить его в HTML первым перед боковушками, потому что тогда они будут начинаться ниже основной колонки (у меня в статье есть картинка).
#main {
background:red;
padding-left:200px;
}
#sidebar {
background:blue;
float:left;
width:200px;
}
Левин делает по-другому.
Во-первых, основной блок таки float'ится, и ему ставится ширина 100%. А вот место под боковые колонки делается с помощью padding'ов в контейнере. Ширина содержимого контейнера при этом уменьшается, и именно в нее укладывается этот основной float.
Но боковые колонки все еще идут ниже основной, потому что та занимает 100% доступной ширины. Вот тут идет гениальная штука. Если боковушке дать отрицательный боковой margin равный или больше ее ширине, то она перестает занимать место по горизонтали вообще. И значит "умещается" сбоку основной колонки. И тем самым поднимается вверх.
#container {
padding-left:200px;
}
#main {
float:left; width:100%;
}
#sidebar {
float:left; width:200px;
margin-left:-200px;
}
Дальше осталось пододвинуть боковушку на свое место налево. Сейчас относительно своего начального положения (правый край) она сдвинута налево на 200 пикселов, и надо к ним добавить еще все ширину основной колонки — 100%. В CSS есть обходной способ, когда надо сложить несколько смещений в разных единицах: одно сделать через margin, а другое — через смещение при position:relative.
#sidebar {
float:left; width:200px;
margin-left:-200px;
position:relative; left:-100%;
}
Вот теперь все практически на месте. Единственная проблема — баг в IE, который двигает колонку слишком далеко налево. Автор статьи это обходит неким шаманством, расставляя по-другому 200px и 100%, и применяя right вместе с left примерно так:
#sidebar {
float:left; width:200px;
margin-left:-100%;
position:relative; right:200px;
}
* html #sidebar {
left:0; /* тут ширина правой колонки, если есть */
}
Честь ему и слава, что он до этого дохачил :-). Однако, это все равно работает, только если ширина контейнера занимает все окно. Если меньше, IE куда-то девает левую колонку, и у меня так и не вышло ее найти :-(.
Комментарии: 12
containe{padding:0 0 0 200px;border-color:#000;}
sidebar{float:left;width:200px;margin-right:-200px;position:relative;left:-200px;}
main{float:right;width:100%;padding:0 0 0 200px;padd\ing:0;}
аа, забыл бордеры убрать....
Это, сдается мне, только с двумя колонками будет работать. Если колонки 3, то в любом случае придется одну тащить через центральную, что вправо, что влево. Хотя, может быть так, что вправо такой глюк и не проявится... Надо посмотреть.
да, 3ю придётся выносить за контейнер =/
У меня тоже левая убегает когда я ей в качестве фона пытаюсь картинку назначить... геморой одним словом!
Внушаеть! Но при всём уважении к проделанной Меттью работе, ИМХО, это всё-таки тот случай когда проще плюнуть на принципы и переставить блоки в коде:)
Приведенный у вас код, тем не менее, не работает у меня в IE 6.0 :( как и код, приведенный в статье Меттью Левина, даже с "заплатками". А так уже хочется без проблем делать резиновую раскладку в 3 колонки :(
А чем не нравится идея такая:
left
{
position: absolute;
left: 0;
top: 0;
width: 10em;
}
main
{
margin-left: 10em;
margin-right: 11em;
}
right
{
position: absolute;
right: 0;
top: 0;
width: 11em;
}
Какой html, думаю, понятно... Ну и добавляются правила нужные + хаки.
Абсолютно позиционированная колонка не сможет раздвигать вниз контейнер. И если она длиннее main'а, то будет напозать на футер или просто некраисво торчать снизу. Собственно, это основная проблема, из-за которой колонки делаются как правило float'ами: те можно оставить в потоке.
Прошу прощения за флуд, но мне показалось, что было нужно решение с контейнером не на всю ширину.
Решение с отступами в процентах привожу:
Возможно тут есть лишние контейнеры - просто у меня на все раскладки стандартный шаблон. К примеру, здесь футер клеится к нижнему краю окна, если содержимое меньше прокрутки, и к нижнему краю содержимого - если больше.
Да уж :-)
Сергей, если честно, то Ваш код иллюстрирует как раз то, от чего CSS призван избавить. Такое количество элементов в HTML, служащих только презентационным целям, ничем не отличается от верстки таблицами, кроме названия тега.
CSS — не идеальный инструмент. Поэтому если его возможностей для целей дизайнера серьезно не хватает, мне кажется есть всего два выхода:
Но пытаться пользоваться неподходящим инструментом просто незачем, мне кажется.
к тому же последний вариант у меня ужасно глючит в ФайрФоксе и Опере ... лечно у меня на работе (не еще не работа, я туда устраиваюсь и должен тестовое задание ваполнить) требуют (даже настоятельно рекомендуют) что бы в большенстче браузеров работало хорошо! да что там начальство, я сам от себя этого требую ))) правда не получается пока, но рано или поздно думаю добью