Из ВК

30 декабря 2009

Колонки без бордюров из блоков одной высоты



Проблема заезженная, скорее всего велосипед я опять не изобрёл. Если уже знаете - не читайте. В общем пишу чтоб было, ну и может кто найдёт здесь - будет подспорье.

В общем проблема блочной вёрстки (спорить на эту тему не собираюсь, просто я сам перешёл на неё и Вам рекомендую - поддержка упрощается в разы) в выравнивании по высоте соседних блоков. Есть ещё одна проблема, которую я очень не люблю - свойство clear:laft|right|both которое срабатывает на плавающие блоки на которые не хотелось бы чтоб срабатывало. Ну как картинка имеющая float:right; clear:right спускается не под такуюже картинку, а под километровый сайдбар с меню который тоже имеет свойство float:right;. Собственно я больше особых недостатков в блочной вёрстке и не знаю. Ну ещё надо с CSS по колдовать чтоб во всяких IE6 выглядело как везде, тем не менее я с этим морочусь из-за перевешивающих все эти недостатки последующей простотой поддержки этих страниц. Конечно если вы знаете, что больше никогда к этому сайту не прикоснётесь - можно накидать всё за 5 минут в таблицах и всё. Они будут одинаковыми везде. Но когда приходится поддерживать сайт, как в моём случае, произведённый такими умельцами - можно проклясть всё на свете.

Теперь к делу. Способ основан на этом принципе, но менее заморочен, т.к. не позволяет использовать бордюры. Если нужны бордюры - воспользуйтесь вышеприведённой ссылкой. Ноя не разобрался как её применить к вёрстке с садбарами фиксированной ширины... В обсуждаемом варианте можно вкладывать в "Контент" такие же блоки равной высоты (инкапсулировать). Можно делать больше сайдбаров в с разных сторон сразу. В общем довольно гибкая система. Создавалась для блока контент плавающей ("резиновой" вёрстки) или фиксированной ширины и сайдбаров известной ширины.

Принцип действия, собственно, описан в источнике, но я передам его своими словами. Наша цель поставить рядом два (и больше, но начнём с двух) блока. И заставить их при изменении количества содержимого быть одинаковой высоты. т.к. блоки взаимно не связаны - это практически не возможно. Т.к. блоки созданы не для этого, для этого созданы таблицы. Блоки и должны быть по высоте равны содержимому внутри себя, а не внутри соседа. По этому логичным выводом будет создать под интересующим блоками необходимый фон высотой с самый высокий блок, что будет создавать иллюзию одинаковой высоты.


Однако, если сайдбар станет длиннее содержимого, под содержимым вылезет фон сайдбара...

Одно из наиболее простых решений:
  1. Сайдбар создаётся внутри блока контента и делается плавающим в нужную сторону.
  2. Со стороны где будет сайдбар задаётся бордюр для блока контента шириной в сайдбар и цветом фона сайдбара.
  3. Сайдбару задётся с нужой стороны отрицательный внешний отступ margin шириной в сайдбар.
В результате блок сайдбара как-бы проваливается на бордюр. При этом он по прежнему остаётся в потоке внутри контентного блока и если тот имеет свойство overflow:hidden или после блока сайдбара не плавающий блок со свойством clear:<стороная в которую "сплывает" сайдбар>|both то при увеличении высоты сайдбара - он будет растягивать и родительский блок с контентом.

Код:
<html>
<head>
  <title>Тест колонок одинаковой высоты</title>
  <style type="text/css">
    #content{
      border-right:150px red;
      background:green;
    }
    #sidebar{
      width:150px;
      background:red;
      margin-right:-150px;
    }
    * html #sidebar{ /* хак для IE 6 а то он удваивает величину внешнего отступа у блочных элементов */
      display:inline;
    }
    .clear{
      clear:both;
    }
  </style>
</head>
<body>
  <div id="content">
    <div id="sidebar">
      Сайдбар
    </div>
    Контент
    <div class="clear"></clear>
  </div>
</body>
</html>
Очевидный недостаток - количество сайдбаров ограничено по одному с каждой стороны (хотя такие потребности возникают очень редко). Также очевиден и способ обхода - добавить ещё одну обёртку снаружи и у дополнительных садбаров внешний отступ будет равен -(<своя ширина>+<сумма ширин сайдбаров лежащих между ним и блоком контента>).

Честно говоря, я вот смотрю на это решение и даже не знаю, зачем нужен мой метод? А ни зачем он получается не нужен, казалось бы... Хотя есть случаи когда у сайдбара не цвет фоновый, а картинка или текстура. Вооот, а то уж думал зря я его сочинял этот способ...

Способ очень похож на предыдущий. Только добавляется ещё один обёрточный блок (самый внешний), который будет содержать необходимый фон. А у блока контента делается внешний отступ с нужной стороны шириной в сайдбар. Тогда с этой стороны будет из-под блока контента выглядывать нужный фон сайдбара, а сам сайдбар будет "сваливаться" не на бордюр блока контента, а в пустоту на головную обёртку с нужным фоном. При этом он будет растягивать блок контента если станет выше его, а блок контента будет растягивать основную обёртку с фоном сайдбара, если станет выше сайдбара.

Код:
<html>
<head>
  <title>Тест колонок одинаковой высоты</title>
  <style type="text/css">
    #sideBarBack{
      background:red;
    }
    #content{
      margin-right:150px;
      background:green;
    }
    #sidebar{
      width:150px;
      background:red;
      margin-right:-150px;
    }
    * html #content{ /* хак для IE 6 а то он может заливать фоном родительского элемента дочерний */
      position:relative;
      display:inline; /* хак для IE 6 а то он удваивает величину внешнего отступа у блочных элементов */

    }
    * html #sidebar{ /* хак для IE 6 а то он удваивает величину внешнего отступа у блочных элементов */
      display:inline;

    }
    .clear{
      clear:both;
    }
  </style>
</head>
<body>
  <div id="sideBarBack">
    <div id="content">
      <div id="sidebar">
        Сайдбар
      </div>
      Контент
      <div class="clear"></clear>
    </div>
  </div>
</body>
</html>
На заметку: в коде использована пара хаков для IE 6, в IE 7 вроде бы проблем вообще не заметил, IE 8 конформный CSS2 браузер хотя проверять рекомендую, иногда есть расхождение в реализации этой конформности. Например CSS свойство селектор :active не "всплывает" на родительский элемент, как во всех остальных браузерах. Так вот чтобы не городить огород с условными операторами в HTML для загрузки CSS файлов с нужными хаками и прочей лабудой для конкретной версии браузера - рекомендую пользоваться следующими CSS селекторами:

* html <обычный селектор нужного Вам элемента> - такие селекторы отрабатываются только в IE версии 6, меньше версии - не знаю как реагируют, 7-й IE уже не отрабатывает его.
*:first-child+html <обычный селектор нужного Вам элемента> -такие селекторы не воспринимаются никакими браузерами, кроме IE 7.