UWAGA: Strona zawiera materiały archiwalne. Większość artykułów dotyczy Joomla! 1.0
Start arrow Szablony arrow Szablon arrow Kolumny na marginesach
Kolumny na marginesach Drukuj Email
Objaśnienie technik projektowania 3-kolumnowych układów z nagłówkiem i stopką Paula O’Briena może posłużyć do stworzenia różnych typów szablonów. W kolejnym przykładzie rozpatrzymy tworzenie układu płynnego z nagłówkiem i stopką.

Zestawienie wymagań

Projektowany szablon będzie się charakteryzować się następującymi właściwościami:

  • układ płynny, 3-kolumnowy,
  • stała szerokość bocznych kolumn,
  • wysokości kolumn dostosowane do najdłuższej,
  • nagłówek powyżej górnej krawędzi kolumn,
  • stopka poniżej dolnej krawędzi kolumn,
  • semantyczna struktura i układ treści.

Nim przystąpimy do przygotowania plików szablonu, rozważmy, na czym polega trudność i jak ją rozwiązać.

Główne problemy

W projektach układów 3-kolumnowych z nagłówkiem i stopką, trzeba rozwiązać dwa zasadnicze problemy:

  • problem umieszczenia stopki przy dolnej krawędzi wszystkich trzech kolumn,
  • problem dostosowania wysokości wszystkich kolumn do najdłuższej.

Paul O’Brien wykorzystał w swej koncepcji jedno z założeń modelu blokowego - możliwość ustanawiania ujemnych marginesów. Przypomnijmy pokrótce właściwości elementów blokowych.

Model pudełka - nieco teorii

Każdy element generuje jeden lub więcej prostokątnych obszarów zwanych pudełkami elementu. Wewnętrzna część pudełka zawierająca treść to pole elementu. Jego granice wyznaczają wewnętrzne brzegi - górny, prawy, dolny i lewy.

Model pudełkowy

Pole elementu może być otoczone dopełnieniem [padding], czyli odstępem, ramką [border] złożoną z czterech krawędzi - górnej, prawej, dolnej i lewej oraz marginesami [margin] - górnym, prawym, dolnym i lewym. Całe pudełko znajduje się w obszarze ograniczonym brzegiem zewnętrznym.

Model pudełkowy - brzegi

Marginesy, ramki i dopełnienia (odstępy) są opcjonalne. Jeśli wartość wszystkich zostanie ustawiona na 0, to zewnętrzne brzegi pudełka elementu pokrywają się z brzegami wewnętrznymi.

Marginesy pudełka (i tylko maginesy) mogą przyjmować nie tylko wartości dodatnie, ale także ujemne! W rezultacie element potomny, a więc umieszczony, wewnątrz (sic!), w polu elementu, może być szerszy i dłuższy niż obejmujący go element nadrzędny. Może wystawać poza pudełko rodzica, w tym poza okno przeglądarki. Może też zachodzić na inne elementy.

Wszystkie wymiary - szerokości i wysokości - sumują się. Gdy ustalona jest np. szerokość obszaru elementu, szerokość dopełnienia, szerokość marginesu i szerokość obramowania, to obszar zajmowany przez cały element ma szerokość równą sumie wymienionych. Nie dotyczy to jednak przeglądarek Win 5/5.5. W tych przeglądarkach szerokość i wysokość ustalona dla elementu obejmuje nie tylko jego pole, ale także wartości ustalone dla dopełnienia i obramowania. Szerokość i wysokość całego obszaru są zatem w ich przypadku sumą dwóch wartości - ustalonej dla elementu i dla marginesów.

Koncepcja rozwiązania problemu

Istotą pomysłu Paula O’Briena jest osadzenie wszystkich trzech kolumn planowanego układu w jednym elemencie - kolumny środkowej w polu elementu, a kolumn bocznych w obszarze jego marginesów. Takie rozwiązanie zapewnia, że wysokość kolumn zawsze będzie dostosowywać się do wysokości najdłuższej, bo najdłuższa będzie wydłużać obszar całego elementu.

Jeśli jednak stworzymy teraz pudełka dla bocznych kolumn i osadzimy je wewnątrz nadrzędnego elementu, to pudełko z lewą kolumną przylegać będzie do lewej krawędzi wewnętrznego brzegu elementu nadrzędnego, a prawe do prawej wewnętrznej krawędzi. Musimy przysunąć je do brzegów zewnętrznych.

Zgodnie z modelem elementów blokowych marginesy mogą przyjmować wartości ujemne, a tym samym element wewnętrzny może być szerszy, niż jego rodzic. Można więc pudełkom bocznych kolumn dodać odpowiednio szerokie ujemne marginesy, a następnie całą ich zawartość przenieść w obszar tych marginesów. To ustawienie rozwiązuje problem, choć nie w pełni, do czego wrócimy.

Pozostaje stopka. Ale skoro nie ma już problemu kolumn i ich wyrównania do najdłuższej, to umieszczenie stopki u ich dolnej krawędzi wydaje się łatwe. Zostanie osadzona pod elementem obejmującym kolumny.

Struktura elementów treści strony - plik index.php

Zgodnie z tymi założeniami ustalamy zawartość zawartość sekcji body w pliku index.php.

Poza już znanymi z poprzednich projektów elementami: #header, #content_main, #nav_bar (lewa kolumna), #misc_bar (prawa kolumna) i footer potrzebujemy jeszcze elementu obejmującego wszystkie treści strony z wyjątkiem stopki. Nazwiemy go #content.

W pliku index.php - w odpowiednich miejscach - umieszczamy następujące kod:

<?php
/** 05_liquid_P_O_Brien. Płynny 3-kolumnowy układ wg P. O&#8217;Briena 
    oparty na: Three Column Layout with Equalizing Header and Footer 
    (http://www.pmob.co.uk/)
*/
 
<body>
  <div id="content">
     <div id="header">
        <h1><?php echo $GLOBALS['mosConfig_sitename']; ?></h1>
     </div>
     <div id="nav_bar">
        <?php mosLoadModules( 'left' ); ?>
     </div>
     <div id="misc_bar">
        <?php mosLoadModules( 'right' ); ?>
     </div>
     <div id="content_main">
        <?php mosMainBody(); ?>
     </div>
  </div>   
  <div id="footer">
     <?php include_once($GLOBALS['mosConfig_absolute_path'] 
      . '/includes/footer.php'); ?>
  </div>
</body>

Właściwości elementów

Rozważmy teraz, jakie właściwości musimy ustalić dla każdego elementu, aby osiągnąć planowany efekt.

Wysokość obszaru obejmującego i kolumn

Projekt rozmieszczeniaWysokość obszaru obejmującego to wysokość najdłuższej kolumny. Ale wysokości kolumn nie znamy i nie jesteśmy w stanie ustalić, ponieważ zależy ona od zawartości. A w Joomla! i Mambo zawartość jest generowana dynamicznie, a więc nieprzewidywalna. Musimy więc posłużyć się wymiarem względnym - w stosunku do elementu nadrzędnego, którym jest element body.

Problem leży w tym, że nie znając wysokości najdłuższej kolumny, nie możemy przyjąć, że jakąś część strony, np. 90% przeznaczymy na element obejmujący treść, a pozostałe 10% na stopkę. Możemy założyć tylko jedno sensowne ustawienie, przyjąć, że element #content będzie wypełniać 100% wysokości strony. Minimum 100% i równocześnie maksymalnie 100%.

Miejsce dla stopki

Jeśli jednak ustalimy, że element #content będzie wypełniał 100% wysokości strony, to braknie miejsca na stopkę. Rozpatrując tę kwestię, P. O’Brien znowu sięgnął do założeń elementu blokowego: elementowi #content ustalił dolny ujemny margines, wysokości planowanej stopki.

Arkusz stylów - pierwsze podejście

Spróbujmy na tej podstawie zdefiniować style dla planowanych elementów. Umyślnie nie rozważamy w tym momencie wszystkich aspektów omawianego rozwiązania. Oglądając efekty wstępnych ustawień i widząc ich interpretację w różnych przeglądarkach, latwiej będzie zrozumieć szczegóły projektu.

Plik template_css.css

Oto kod arkusza stylów zawierający właściwości zdefiniowane na podstawie omówionych powyżej założeń. Przekopiuj go pliku template_css.css:

/* 05_liquid_P_O_Brien. 
   3 kolumny, płynny, nagłówek, stopka, wyrównana długość kolumn
   oparty na P. O&#8217;Brien: Three Column Layout with Equalizing Header and Footer 
   (http://www.pmob.co.uk/)
*/
body {
   height             : 100%;
   font               : 76.1% Verdana,Arial,Helvetica,sans-serif; 
   } 
#content {
   height             : 100%;
   min-height         : 100%;    
   margin-left        : 190px;
   margin-right       : 190px;
   margin-bottom      : -50px;
}
#header {
   margin             : 0 -144px;
}
#nav_bar {
   width              : 190px;    /* taka sama jak lewy margines w #content*/
   float              : left;        /* wstawia kolumnę w jej pozycję */
   margin-left        : -190px;   
}
#misc_bar {
   width              : 190px;    /* taka sama jak prawy margines w #content*/
   float              : right;      /* wstawia kolumnę w jej pozycję */
   margin-right       : -190px;
}
#footer {
   width              : 100%;
   height             : 50px;
}
   
/* ========== TYLKO DLA PODGLąDU =================== */
body {
   background-color   : #F8F8F8;    /* kolor całej strony */
   }
#content{
   background-color   : #FFF;
   border-left        : 1px solid #000;
   border-right       : 1px solid #000;
}
#header{
   background-color   : #EAF0FE;
   border-top         : 1px solid #000;
   border-bottom      : 1px solid #000;
}
#nav_bar,#misc_bar {
   background-color   : #F2F2F2;   
}
#footer {
   background-color   : #EAF0FE;
   border-top         : 1px solid #000;
   border-bottom      : 1px solid #000;
}

Podgląd efektów - modyfikacja

Sprawdzamy efekt w kilku podstawowych przeglądarkach. Najpierw w jednej z najbardziej zgodnych ze standardami - w Firefox. Mamy w zasadzie to, czego oczekiwaliśmy: trzy odpowiednio rozmieszczone kolumny, nad górną krawędzią kolumn nagłówek z nazwą serwisu, pod dolną krawędzią kolumn stopkę. W Operze i Netscape podobnie. Problem stopki rozwiązany został jednak tylko czściowo. Jest na swoim miejscu, ale w jej obszarze znalazła się część materiału z obszaru głównej treści.

Sprawdźmy jeszcze w IE 6.0… Nie ma lewej i prawej kolumny, widzimy obszar nagłówka, ale tylko część nazwy serwisu. Takiego efektu można się jednak było spodziewać. To znana przypadłość IE. Bloki #header, #nav_bar i #misc_bar są elementami pływającymi - ustaliliśmy dla nich styl float. Dla innych przeglądarek jest oczywiste, że mają do czynienia z pozycjonowaniem względnym. Dla IE, niestety, nie! Trzeba to zadeklarować jawnie. Uzupełnijmy zatem arkusz stylów:

#header{
   margin             : 0 -190px;
   position           : relative; /* dodana linia */
}
#nav_bar {
   position           : relative; /* dodana linia */
   width              : 190px; 
   float              : left;  
   margin-left        : -144px; 
}
#misc_bar {
   position           : relative; /* dodana linia */
   width              : 190px; 
   float              : right; 
   margin-right       : -190px;
}

Sprawdzamy. Kolumny wskoczyły w IE na swoje miejsce. Ale nagłówek nadal jest widoczny jedynie nad kolumną centralną, a tytułu serwisu nie widać. Ten błąd rozwiąże  - ciekawostka - określenie wysokość elementu header.

#header{
   position           : relative;
   margin             : 0 -190px 0 -190px;
   height             : 70px; /* dodana linia */
}

Problem jest rozwiązany, ale zauważmy, że określenia wysokości nagłówka wymagał tylko IE. Zamiast więc dodawać styl height w głównej części arkusza, dodajmy poprawkę dla IE/Win. IE dla Mac nie wymaga określania wysokości. Usuńmy zatem dodaną przed chwilą linię, a w sekcji /* == ŁATKI== */ arkusza stylów dodajmy:

/* Ukryj przed Mac/IE  Commented Backslash hack v2 \*/
* html #header{
   height:72px;   
   height:70px;
}
/* Koniec ukrywania dla Mac/IE */

Łatki, sztuczki i kruczki

Obsługa CSS przez urządzenia odczytujące jest coraz lepsza. Z czasem niektóe przynajmniej sztuczki na kruczki przestaną być potrzebne, stąd warto wszystkie niestandardowe rozwiązania wydzielić w odrębną sekcję arkusza stylów.

Tutaj zastosowaliśmy trzy sztuczki:

  • Commented Backslash hack v2 - ukrywający reguły przed IE/Mac,
  • Star Hack - ukrywajacy reguły przed innymi niż IE przeglądarkami,
  • Tan Hack rozwiązujący problem interpretacji modelu blokowego przez IE.

Efekt będzie następujący: IE/Mac nie zobaczy żadnej reguły, IE 6.0 zobaczy obie, ale zastosuje się do drugiej, natomiast IE/Win 5.x drugą ze względu na ukośnik w nazwie pominie.

Jak pamiętamy, IE 5.x w wysokości elementu uwzględnia także wartości ustalone dla dopełnienia i obramowania. Zgodnie z tym nie doda już do wysokości #header grubości górnej i dolnej ramki. Stąd w regule 72px ustalone dla IE 5.x. Natomiast dla IE 6.0 ustalonych zostało 70px, do których dojdą jeszcze 2 piksele obramowania.

Z objaśnieniami tych i innych sztuczek możesz zapoznać się w sekcji Kruczki i sztuczki.

Oczyszczanie elementów pływających

Upewniamy się teraz, że obie kolumny, nagłówek i stopka we wszystkich przeglądarkach znajdują się na właściwym miejscu.

Sprawdźmy, co się dzieje, gdy długość centralnej kolumny jest krótsza niż którejś z bocznych. Wybieramy z menu głównego pozycję Aktualności, i…

W Firefoksie, w Operze i w Netscape stopka wskoczyła bezpośrednio pod znacznie krótszą kolumnę centralną. W IE pozostała na swoim miejscu. Zatem jeszcze jeden problem - wcześniej już widzieliśmy, że do obszaru stopki dostał się fragment treści głównej.

Gdy korzystamy z elementów pływających, musimy zadbać o ich poprawne oczyszczenie, czego jeszcze nie uczniliśmy.

Stopkę (#footer) umieściliśmy na zewnątrz elementu content, zakładając, że wskoczy w obszar stworzony ujemnym marginesem elementu #content.

Oczyśćmy zatem obszar dla stopki. Musimy w tym celu wprowadzić w części body szablonu dodatkowy element - clear_footer i określić dla niego właściwości w arkuszu stylów

Musimy też zapobiec opływaniu stopki przez elementy #nav_bar i #misc_bar. Dodajmy zatem styl float z wartością both, uniemożliwiającą pojawienie się pływających elementów po obu stronach stopki. Pamiętamy też, aby ze względu na IE wyraźnie zadeklarować, że #footer jest pozycjonowany względnie:

Modyfikacja index.php

Najpierw w pliku index.php przed znacznikiem </div> kończącym element content umieszczamy pusty element:

<div id="clear_footer"></div>

Modyfikacje w arkuszu stylów

W arkuszu stylów dodajemy deklarację dla #clear_footer oraz modyfikujemy style stopki:

#clear_footer{/* czyści obszar dla stopki */
   clear              : both;
   height             : 50px;
}  
#footer {
   width              : 100%;
   height             : 50px;
   float              : both; /* dodana linia */ 
   position           : relative; /* dodana linia */ 
   }

Sprawdzamy. Wszystkie elementy są na swoich miejscach. Stopka dobrze się trzyma dolnej krawędzi. Teraz należałoby zadbać jeszcze o odstępy między kolumnami, co uczynimy później.

Udoskonalanie

Moglibyśmy już zakończyć pracę nad przykładowym projektem, ale kilka kolejnych drobnych poprawek uczyni go doskonalszym.

Obramowanie

We właściwościach elementu #content zadeklarowaliśmy prawe i lewe obramowanie grubości 1 piksela. Aktualnie jest niewidoczne. Ukrywa się pod tłem elementów nav_bar i misc_bar. Łatwo to sprawdzić, usuwając z nich tło. Aby obramowanie było widoczne, wystarczy drobne przesunięcie obu elementów o ten 1px w lewo. Skorzystamy z właściwości left. W przypadku elementu nav_bar musimy posłużyć się wartością ujemną.

#header{
   margin             : 0 -191px; /* zmiana, było 144px */
   }
#nav_bar {
   margin-left        : -189px;   /* zmiana, o 1px mniej */
   left               : -1px;     /* dodana linia*/     
   }
#misc_bar {
   margin-right       : -189px;   /* zmiana, o 1px mniej */
   left               : -1px;     /* dodana linia*/

Magiczny piksel

Wprawdzie nasz układ zachowuje się zgodnie z założeniami, ale warto zaufać jego twórcy. P. O’Brien sugeruje mianowicie, że jeżeli elementom nav_barmisc_bar ustalimy ujemne marginesy o 1px węższe od ich szerokości, a następnie przesuniemy te elementy w lewo i w prawo za pomocą właściwości left, to będą one - zachodząc tym jednym magicznym pikselem na kolumnę centralną - wymuszać jej wydłużenie, a także zepchną stopkę poniżej wszystkich trzech kolumn.

Zmodyfikujmy więc style dla #header, #left i #right następująco:

#header{
   position           : relative; 
   margin             : 0 -191px; /* zmiana, było 144px */
   }
#nav_bar {
   position           : relative; 
   width              : 190px;    
   float              : left; 
   margin-left        : -189px;   /* o 1px mniej niż szer., by zepchnąć stopkę */
   left               : -2px;     /* wyrównuje brakujący 1 px z marginesu */   
   }
#misc_bar {
   position           : relative; 
   width              : 190px; 
   float              : right; 
   margin-right       : -189px;   /* o 1px mniej niż szer., by zepchnąć stopkę */
   left               : 2px;      /* wyrównuje brakujący 1 px z marginesu */   
   }

Wyzerowanie marginesów i dopełnień

Ponieważ przeglądarki w różny sposób dodają do elementów marginesy i dopełnienia, trzeba koniecznie zapanować nad tymi właściwościami. Nawet jeden piksel może zburzyć cały układ. Stąd w stylach dla html, body wyzerujemy wszystkie dopełnienia i marginesy.

100% wysokości

Ustaliliśmy elementowi body wysokość 100%. Niektórym przeglądarkom to nie wystarczy - w Mozilli o wysokości elementu body decyduje element html. Ten fragment arkusza musimy więc nieco zmodyfikować, określając wysokość zarówno dla html, jak i body. Efekt podejrzeć będzie można np. w Netscape. Dopiero po tym zabiegu strona wypełni całe okno przeglądarki, nawet wówczas, gdy zawartość we wszystkich trzech kolumnach będzie skromna.

Dokonajmy w arkuszu stylów deklarację dla html,body {} i usuńmy z body definicję wysokości:

/* Ukryj przed Mac/IE  commented backslash hack v2 \*/ 
html, body{
   height:100%;
         /* Koniec ukrywania dla Mac/IE */
   padding:0;
   margin:0;  
   } 
body {
   /* usunęliśmy stąd styl height, przeniesiony wyżej */ 
   font             : 76.1% Verdana, Arial, Helvetica, sans-serif; 
}

100% wysokości - wysokość minimalna i maksymalna

Elementowi #content ustaliliśmy wysokość 100%. To wystarczy dla IE, ale w innych przeglądarkach można się spodziewać przepełnienia - wypłynięcia zawartości na zewnątrz, gdy będzie większa. Aby temu zapobiec, dodaliśmy styl min-height: 100%. IE tę właściwość ignoruje, więc nie ma problemu. Jednakże ustawienie height-min: 100% w takich przeglądarkach, jak Mozilla spowoduje, że będzie to nie tylko minimalna, ale i maksymalna wysokość. Aby zapobiec takiej sytuacji, nakażemy innym przeglądarkom dostosować wysokość automatycznie za pomocą stylu: height:auto. Przed IE ukryjemy tę regułę za pomocą selektora potomka (>), którego IE nie interpretuje. W sekcji /*==== Łatki ====*/ dodamy:

html > body #content{
   height:auto;  /* dla Mozilli, w IE zawsze height = min-height */
   }

Model blokowy raz jeszcze

Dla stopki ustaliliśmy wysokość równą 50px. W IE5/Win (a także w IE6/Win w trybie quirks) rozmiary obszaru zawartości elementu są powiększane o dopełnienie i ramkę [border]. Jeśli chcemy, by IE5/Win nadawało stopce oczekiwaną wysokość, konieczna jest poprawka. Zastosujemy już raz wykorzystaną sztuczkę Tanteça:

* html #footer {                     /* Style tylko dla IE */
   height           : 52px;         /* dla ie5 */
   height           : 50px;         /* dla ie6 */
}

Błąd przepełnienia

W przeglądarkach IE mamy do czynienia z błędnym przepełnieniem zawartości elementów pływających. Błąd ten naprawia poniższa łatka:

* html #nav_bar {
   margin-right:-3px; /* usuwa w IE lukę po elementach pływających */
   }
* html #content_main {
   height:1%;
   margin-bottom:12px; /* równoważy w IE przepełnienie elementów pływających */
   }

Wartość określona dla height nie ma zbyt wielkiego znaczenia - IE dostosowuje bowiem wysokość do zawartości. Wystarczy więc, jeśli określimy dla height wielkość na 1%.

Modyfikacje dla IE/Mac i Safari

Kolejne dwie poprawki przeznaczone sa dla IE/Mac i dla Safarii. Uzupełnij kod o deklaracje:

* > html #clear_footer {             /* Style dla IE/Mac */
   float             :left;
   width             :100%;
   }     
html > body  #minHeight{ /* Style dla Safari -  Tim Connor*/
   float             : left;
   width             : 0px;
   height            : 100%;
   margin-bottom     : -52px;
   }

Modyfikacja dla przeglądarki Safarii wymaga też uzupełnienia kodu w pliku index.php. Tuż po elemencie body dodaj linię:

 
<div id="minHeight"></div>

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ł »