Start arrow Programowanie arrow Szablon arrow Kolumny w dopełnieniach
Kolumny w dopełnieniach Drukuj Wyślij znajomemu
Wielu projektantów poszukuje idealnego 3-kolumnowego układu z wyrównywaną wysokością kolumn, ze stopką utrzymującą się przy ich krawędzi, a przy tym zgodnego ze standardami. Symbolem idei jest legendarny kielich Holly Grail - Święty Graal. Matthew Levine - w poszukiwaniu Świętego Graila [In Search of the Holy Grail], podobnie jak Paul O’Brien, sięgnął do właściwości modelu blokowego.

Tajemnice modelu blokowego

Model blokowy okazuje się wdzięcznym polem eksperymentów. W rozwiązaniu Paula O’Briena mieliśmy okazję poznać wykorzystanie właściwości marginesów. Matthew Levine sięgnął po  dopełnienia.

Krok 1. Ramka

Paul O’Brien umieścił boczne kolumny na marginesach, Matthew Levine umieścił je w obszarze lewego i prawego dopełnienia kolumny centralnej.

Prześledzimy ten udany eksperyment, tworząc opartą na jego założeniach podstawę szablonu dla Joomla! i Mambo.

Dla porządku rozpocznijmy od wypunktowania, czy raczej przypomnienia ogólnych założeń.

Założenia projektu

Chcemy uzyskać układ z nagłówkiem i stopką o następujących właściwościach:

  • semantyczna struktura i układ treści, główna treść na początku dokumentu HTML,
  • płynna szerokość kolumny centralnej i ustalona szerokość kolumn bocznych,
  • zmienna wysokość kolumn, dostosowująca się do najdłuższej,
  • minimum nadmiarowego kodu,
  • prosty CSS z minimalną ilością łatek.

Szablon nazwiemy 07_liquid_M_Levin.

Prześledzimy kolejne etapy tworzenia projektu.

Przygotowanie katalogu i plików szablonu

Załóż w katalogu /templates folder 07_liquid_M_Levin i przekopiuj do niego zawartość katalogu 00_podstawa

W pliku templateDetails.xml zmień nazwę szablonu i jego opis:

........
  <name>07_liquid_M_Levin</name>
........
  <description>
    3-kolumnowy, płynny układ ze stałą szerokością bocznych kolumn,
    na podstawie: Matthew Levine: In Search of the Holy Grail
    (www.alistapart.com/articles/holygrail)
  </description>
........

Z pliku index.php usuń zawartość sekcji body, będziemy ją uzupełniać w trakcie tworzenia szablonu; ewentualnie zmień opis w nagłówku pliku:

<?php
/** 3-kolumnowy, płynny układ, stała szer. kol,  
     na podstawie: Matthew Levine: In Search of the Holy Grail  
     www.alistapart.com/articles/holygrail */
......
<body>
 
<!-- stąd usuń zawartość -->
 
</body>

Pierwszy krok: Tworzymy nagłówek, obszar zawartości i stopkę

Rozpoczynamy od utworzenia trzech elementów.

<div id="header"></div>
<div id="content"></div>
<div id="footer"></div>

W arkuszu stylów ustalamy dla elementu #content dopełnienia szerokości planowanych kolumn:

#content {
  padding-left: 200px;   /* szerokość #nav_bar */
  padding-right: 150px;  /* szerokość #misc_bar */
}

Ilustracja powyżej przedstawia efekt: mamy nagłówek, treść i stopkę

Krok 2: Dodajemy kolumny

W obszarze treści tworzymy kolumny:

<div id="header"></div>
<div id="content">
  <div id="content_main" class="column"></div>
  <div id="nav_bar" class="column"></div>
  <div id="misc_bar" class="column"></div>
</div>
<div id="footer"></div>

W arkuszu stylów ustalamy szerokości kolumn, #content przekształcamy w element pływający dosunięty do lewego brzegu:

#content .column {
  float: left;
}
#content_main {
  width: 100%;
}
#nav_bar {
  width: 200px;  /* szerokość #nav_bar */
}
#misc_bar {
  width: 150px;  /* szerokość #misc_bar */
}
#footer {
  clear: both;
}

Dla kolumny #content_main ustalamy 100% szerokości. Kolumna ta wypełni zatem całą szerokość bloku #content z wyjątkiem dopełnień. Zobaczymy te 100% szerokości, gdy cały układ będzie gotowy.

Kolumny boczne są w tej samej linii co kolumna centralna. Ale ponieważ kolumna centralna ma 100% szerokości ramki, więc kolumny boczne są spychane poniżej w wolny obszar. Miejsce na stopkę zostało oczyszczone przez właściwość clear: both.

Ilustracja przedstawia efekt tych ustawień.

Image

Krok 3: Przeniesienie lewej kolumny

Trzeba teraz przenieść na swoje miejsce boczne kolumny - umieścić je w obszarze stworzonym przez dopełnienie bloku #content.

Image

Kolumna centralna znajduje się w miejscu, w którym powinna być. Skoncentrujmy się więc najpierw na lewej kolumnie.

Wystarczą dwa zabiegi.

Po pierwsze, przemieścimy tę kolumnę w lewo za pomocą ujemnego marginesu: margin-left: -100%. Pamiętamy, że 100% to szerokość ramki, wypełniona aktualnie w całości kolumną centralną.

#nav_bar {
  width: 200px;        /* szerokość #nav_bar */
  margin-left: -100%;  
}

Teraz lewa kolumna zachodzi na kolumnę centralną, przylegając do jej lewego brzegu. Prawa kolumna przemieściła się w lewo i nadal zachodzi na kolumnę centralną.

Image

Aby przesunąć blok #nav_bar na pożądane miejsce, skorzystamy z właściwości pozycjonowania względnego. W arkuszu stylów tworzymy klasę .column, przypisaną (zobacz wyżej) do wszystkich trzech kolumn. Właściwością float: left wyrównujemy wszystkie trzy kolumny do lewej krawędzi.

W deklaracji stylu lewej kolumny dodajemy right: 200px;, by przesunąć ją do prawej krawędzi kolumny środkowej. Zauważ dokonujemy przemieszczenia w prawo dokładnie o szerokość lewej kolumny. W efekcie lewa kolumna przylega do kolumny centralnej, co widać na ilustracji.

#content .column {
  float: left;
  position: relative;
}
#nav_bar {
  width: 200px;        /* szerokość #nav_bar */
  margin-left: -100%;  
  right: 200px;        /* szerokość #nav_bar */
}

Krok 4: Umieszczenie prawej kolumny

Pozostało nam przeniesienie na swoje miejsce prawej kolumny. Musimy umieścić ją w ramce #content (aktualnie znajduje się poza), a następnie przesunąć tak, aby znalazła się w obszarze dopełnienia ramki.

Korzystamy, podobnie jak w przypadku lewej kolumny, z metody ujemnego marginesu.

Image

Spójrz na ilustrację. Wszystkie kolumny znalazły się na swoim miejscu.

Mamy pożądany elastyczny układ.

#misc_bar {
  width: 150px;          /* szerokość #misc_bar */
  margin-right: -150px;  /* szerokość #misc_bar */
}

Krok 5: Udoskonalenie rozmieszczenia

Gdy okno przeglądarki zostanie zmniejszone tak, że środkowa kolumna będzie węższa niż lewa, układ rozsypie się. Ale to nie jest problem. Aby utrzymać kolumny na swoim miejscu, wystarczy ustalić minimalną szerokość elementowi <body>. W IE6 nie mamy do czynienia z takim kłopotem, nie musimy więc stosować żadnych łatek. Nie ma zatem problemu z przeglądarkami niewspierającymi właściwości min-width.

To niemal pewne, że żadna technika rozmieszczania nie będzie kompletna bez jakiejś sztuczki koniecznej dla Internet Explorer. Ujemny margines powoduje w IE zbyt dalekie przesunięcie lewej kolumny. Niezbędne jest więc przesunięcie jej o szerokość równą szerokości prawej kolumny. Korzystamy z selektora gwiazdki, by ukryć tę regułę przed innymi przeglądarkami:

* html #nav_bar {
  left: 150px;  /*  szerokość #misc_bar  */
}

Objaśnienie, dlaczego dokonujemy przesunięcia o szerokość prawej kolumny, wymagałoby nieco algebry. To szczegółowa kwestia. Możesz poeksperymentować, rozważając różne przypadłości IE.

Więcej światła!

Oczywiście, uzyskany efekt daleki jest jeszcze od doskonałości. Przede wszystkim tekst będzie przylegać do krawędzi kolumn. Niezbędne są odstępy.

Jedną z wad elastycznego układu kolumn One True Layout jest korzystanie z procentów. To podstępna technika. Procentowo określane dopełnienie przynosi nienajlepsze efekty przy zmieniającej się szerokości okna przeglądarki. A stałe dopełnienie można uzyskać jedynie za pomocą dodatkowych znaczników <div> w każdej kolumnie.

W tej technice dodanie dopełnienia nie stwarza takiego problemu. Można je dodać wprost do lewej i prawej kolumny. Szerokość można ustalić dowolnie, np. 10px. Wymaga to nieznacznej modyfikacji arkusza CSS:

#nav_bar {
  width: 180px;        /* pełna szerokość #nav_bar minus padding */
  padding: 0 10px;
  right: 200px;        /* pełna szerokość #nav_bar */
  margin-left: -100%;
}

Dopełnienie plus 100% szerokości ramki powodują, że środkowa kolumna będzie wychodzić poza blok #content, który nie posiada dopełnienia. Aby uniknąć tego problemu, konieczne jest powiększenie prawego marginesu o szerokość dopełnienia. To zapewni, że środkowa kolumna będzie tak szeroka, jak oczekujemy.

Zmiana ta spowoduje jednak poszerzenie kolumny centralnej. Dlatego korekty wymaga odległość lewej kolumny. Zmniejszymy przesunięcie za pomocą prostej sztuczki.

Na przykład, dodając 10px dopełnienia do bocznych kolumn (w sumie 20px), dodamy 20 px do obu stron kolumny centralnej (w sumie 40px). Zmodyfikowany arkusz CSS wygląda następująco:

body {
  min-width: 630px;   /* 2x (pełna szerokość #nav_bar +
                         dopełnienie #content_main) + pełna szerokość #misc_bar */
}
#content {
  padding-left: 200px;   /* pełna szerokość #nav_bar */
  padding-right: 190px;  /* pełna szerokość #misc_bar + dopełnienie #content_main */
}
#content .column {
  position: relative;
  float: left;
}
#content_main {
  padding: 10px 20px;    /* dopełnienie #content_main */
  width: 100%;
}
#nav_bar {
  width: 180px;          /* szerokość #nav_bar */
  padding: 0 10px;       /* dopełnienie #nav_bar */
  right: 240px;          /* pełna  szerokość #nav_bar + dopełnienie #content_main */
  margin-left: -100%;
}
#misc_bar {
  width: 130px;          /* szerokość #misc_bar */
  padding: 0 10px;       /* dopełnienie #misc_bar */
  margin-right: -190px;  /* pełna szerokość #misc_bar + dopełnienie #content_main */
}
#footer {
  clear: both;
}
 
/*** Łatka dla IE  ***/
* html #nav_bar {
  left: 150px;           /* pełna szerokość #misc_bar */
}

Oczywiście, dopełnienia w nagłówku i w stopce mogą być dodawane bez jakichkolwiek problemów.

Technika ta sprawdza się również wówczas, gdy zamiast pikseli zastosujesz emy. Nie można jednak mieszać jednostek miar.

Wyrównanie wysokości kolumn

Dotychczas nadane właściwości przyniosą satysfakcjonujący efekt, gdy mamy kolumny równiej wysokości. Gdy jednak wysokość kolumn jest zmienna i trudno ją przewidzieć - jak w przypadku Joomla konieczny jest kod rozwiązujący problem zachodzenia stopki na kolumny z zawartością. Autor zaadoptował metodę zastosowaną w One True Layout. Elementowi #content ustawił właściwość overflow: hidden, aby zapobiec ograniczeniu wysokości ramki. Następnie dodał we właściwościach ramki duże dopełnienie u dołu powiększone o 10px odstępu, jaki chciał uzyskać między zawartością a stopką, a następnie podniósł dolną krawędź ramki za pomocą techniki ujemnego marginesu.

#content {
  overflow: hidden;
}
#content .column {
  padding-bottom: 20010px;  /* X + padding minus bottom */
  margin-bottom: -20000px;  /* X */
}
#footer {
  position: relative;
}

To rozwiązanie wystarczyłoby, gdyby nie… IE. Gdy strona jest krótsza niż okno przeglądarki, IE przycina tło ramki. Aby zrównoważyć ten błąd, konieczny jest dodatkowy znacznika <div>:

<div id="footer-box">
  <div id="footer"></div>
</div>

Teraz wystarczy skorzystać z tej samej sztuczki co powyżej, by spowodować, że stopka będzie przemieszczona do dołu okna przeglądarki.

* html body {
  overflow: hidden;
}
* html #footer-box {
  float: left;
  position: relative;
  width: 100%;
  padding-bottom: 10010px;
  margin-bottom: -10000px;
  background: #fff;         /* taki sam, jak tło body */
}

To rozwiązuje problem i przynosi oczekiwany rezultat przy minimum sztuczek.

Można by się zastanawiać, czy nie ma innego rozwiązania. Jakby nie było, dodany jest ponadmiarowy, niesemantyczny znacznik. Najprawdopodobniej jednak niemożliwe jest uzyskanie idealnego efektu, bez żadnych dodatkowych niesemantycznych znaczników.

Rozwiązanie nie jest idealne. Ale zbliża do ideału. Nie będzie ono działać dobrze na przykład w przypadku znacznie zmniejszonego okna przeglądarki.

Uwagi końcowe

Inspiracja dla próby podjętej przez Matthewa Levine’a były opracowania:

Rozwiązanie Alexa Robinsona wymaga jednak dodatkowych, nadmiarowych znaczników <div> - dwóch ramek obejmujących kolumny i dodatkowych bloków wewnątrz kolumn, umożliwiających ustalenie odstępów między kolumnami za pomocą właściwości padding.

Istotą rozwiązania Erica Meyera jest z kolei wykorzystanie różnych jednostki miar: pikseli, emów i procentów. Niewątpliwie efekt jest bardzo dobry, ale zależny od szerokości okna przegladarki.

Matthew Levine zaproponował rozwiązanie znacznie bliższe ideałowi.

Mamy bardzo elastyczny, choć nie idealny układ. Ilość niesemantycznych znaczników jest minimalna. W większości przeglądarek uzyskamy w pełni satysfakcjonujące efekty.

Oczywiście, zaprezentowany tutaj kod wymaga jeszcze rozwinięcia. Konieczne jest rozszerzenie kodu pliku index.php o funkcje ukrywające prawą kolumnę, gdy nie będzie z jakichś względów potrzebna. Ale tę kwestię rozważymy w kolejnym przykładzie.

Plik instalacyjny

Skopiuj następujący kod do pliku templateDetails.xml:

<?xml version="1.0" encoding="iso-8859-1"?>
<mosinstall type="template" version="1.0.0">
  <name>07_liquid_M_Levin</name>
  <creationDate>2006.08.06</creationDate>
  <author>test</author>
  <copyright>GNU/GPL</copyright>
  <authore-mail>
 Ten adres email jest ukrywany przed spamerami, włącz obsługę JavaScript w przeglądarce, by go zobaczyć
 </authore-mail>
  <authorUrl>http://www.joomla.pl</authorUrl>
  <version>0.9</version>
  <description>
    3-kolumnowy, płynny układ ze stałą szerokością bocznych kolumn,
    na podstawie: Matthew Levine: In Search of the Holy Grail
    (www.alistapart.com/articles/holygrail)
  </description>
  <files>
     <filename>index.php</filename>
  </files>
  <css>
     <filename>css/template_css.css</filename>
  </css>
</mosinstall>

Plik index.php

Skopiuj następujący kod do pliku index.php:

<?php
/** 3-kolumnowy, płynny układ, stała szer. kol,  
     na podstawie: Matthew Levine: In Search of the Holy Grail  
     www.alistapart.com/articles/holygrail */
defined( '_VALID_MOS' ) or die( 'Zasób zastrzeżony.' );
$iso = explode( '=', _ISO );
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="pl" xml:lang="pl">
 <head>
  <meta http-equiv="Content-Type" content="text/html; <?php echo _ISO;  ?> " />
  <?php mosShowHead(); ?>
  <?php if ($my->id) {initEditor(); } ?>
  <script type="text/javascript"></script>
  <link rel="stylesheet" type="text/css" title="Standardowy"
    href="<?php echo $GLOBALS['mosConfig_live_site'];    
    ?>/templates/<?php echo $cur_template; ?>/css/template_css.css" media="screen" />
</head>
<body>
  <div id="header">
     <h1><?php echo $GLOBALS['mosConfig_sitename']; ?></h1>   
  </div>
  <div id="content">
    <div id="content_main" class="column">
       <?php mosMainBody(); ?>
    </div>
    <div id="nav_bar" class="column">
       <?php mosLoadModules( 'left' ); ?>
    </div>
    <div id="misc_bar" class="column">
       <?php mosLoadModules( 'right' ); ?>
    </div>
  </div>
  <div id="footer">
    <?php include_once($GLOBALS['mosConfig_absolute_path'] 
        . '/includes/footer.php'); ?> 
  </div>
</body>

Arkusz stylów CSS

Skopiuj następujący kod do pliku template_css.css.php:

/* 07_liquid_M_Levin
   3-kolumnowy, płynny układ, stała szer. kol,  
   na podstawie: Matthew Levine: In Search of the Holy Grail  
   www.alistapart.com/articles/holygrail */
body {
  min-width: 550px;      /* 2x szerokość #nav_bar + szerokość #misc_bar */
}
#content {
  padding-left: 200px;   /* szerokość #nav_bar */
  padding-right: 150px;  /* szerokość #misc_bar */
}
#content .column {
  position: relative;
  float: left;
}
#content_main {
  width: 100%;
}
#nav_bar {
  width: 200px;          /* szerokość #nav_bar */
  right: 200px;          /* szerokość #nav_bar */
  margin-left: -100%;
}
#misc_bar {
  width: 150px;          /* szerokość #misc_bar */
  margin-right: -150px;  /* szerokość #misc_bar */
}
#footer {
  clear: both;
}
/*** IE6 Fix ***/
* html #nav_bar {
  left: 150px;           /* szerokość #misc_bar */
}

Uwagi, źródła

Jeżeli masz sugestie odnośnie treści lub chcesz zgłosić poprawki do tego rozdziału, skomentuj go albo umieść wiadomość na forum: Dokumentacja - Propozycje, zmiany, poprawki

Dziękujemy!

Stefan Wajda, Zespół Dokumentacji PCJ

 
« poprzedni artykuł   następny artykuł »