Równe kolumny layoutu CSS
07 marca 2007
Roger Johansson powiedział kiedyś tak:
Web professionals who refuse to update their skills and insist on using outdated methods can no longer be called web professionals.
(Profesjonaliści, którzy odmawiają uczenia się nowych rzeczy i upierają się przy używaniu przestarzałych metod nie mogą być już dłużej nazywani profesjonalistami - tłum. wł.)
Kiedyś budowaliśmy strony za pomocą tabel, teraz nadszedł czas na podzielenie dokumentu na sekcje i stworzenie z nich layoutu za pomocą CSS. Rozszerzając wypowiedź Johannsona - wszyscy, którzy projektują dalej na zagnieżdżonych tabelach w niedługim czasie albo przestawią się na CSS albo wypadną z obiegu.
Tabelowy layout jest niedopuszczalny, ale prosty w użyciu i bardzo przewidywalny. Webdesignerzy zaczynający pisać w CSS mają całkiem poważne problemy, ponieważ nowoczesne projektowanie opiera się na pozycjonowaniu treści zawartej w blokach. Ich rozmiary nie są sztywne (i w większości sztywne być nie powinny), dlatego nie można uzyskać równych kolumn. Nie można? Zaraz się przekonamy…
Hakami piekło jest wybrukowane
Od lat projektanci są zmuszeni walczyć z tym problemem i radzą sobie całkiem nieźle. Zaawansowani w temacie na pewno słyszeli o Faux Columns, powiększaniu kolumn paddingiem albo używaniu skryptów. Tylko, że właśnie - te rozwiązania walczą z problemem, stwarzając wiele pomniejszych problemów.
Powtarzalne tło wymaga określonej szerokości kolumn. Ulepszona wersja Faux Columns operuje na zmiennych szerokościach, ale wymaga nadmiarowego kodu i długich obrazków. Padding wydaje się elegancki, ale tak naprawdę jest hakiem CSS polegającym na wymiarach i hardkorowej modyfikacji odstępów. JavaScript ma wiele mankamentów - raz, że może go wcale nie być, dwa że jest problem z czasem uruchomienia skryptu.
Tabela tabeli nierówna
Wrócmy jednak do pierwszych akapitów. Tabele są złe, ponieważ elementy <table>, <tr>, <td>, etc służą do opisania danych tabelarycznych. Działamy na szkodę oddzielenia prezentacji od zawartości. Ludzie z nich korzystają, bo prezentacja tabel jest użyteczna. I właśnie. Potrzebujemy prezentacji tabel, a nie ich samych.
W CSS możemy określić wyświetlanie tabelaryczne, a robimy to przez ustawienie display na table / table-row / table-cell. Wartości otrzymały takie nazwy, ponieważ tabele powinny być domyślnie wyświetlane przy ich pomocy. Użycie display: table nie oznacza powrotu do ery tabelek, tylko zrozumienie potrzeby oddzielenia prezentacji od zawartości. A to jest ok.
Znowu ten #$%!@ IE… ;-)
Byłoby miodzio, gdybyśmy mieli wsparcie dla display: table we wszystkich przeglądarkach. Na nieszczęście jest taka jedna, która uparcie nie chce wyrosnąć z pieluch - Internet Explorer.
Jak już wielokrotnie wspominałem, Explorer pomimo swojej ułomności został wyposażony w wiele rozszerzeń. Za pomocą jednego z nich - expressions, naprawimy wyświetlanie w IE. Czemu zdecydowałem się więc na display: table, skoro i tak w 75% przeglądarek będzie działał JavaScript? Ponieważ expressions są przeznaczone do wykonywania w czasie rzeczywistym, za każdą zmianą na stronie i można je wrzucić wygodnie do CSS. A userzy IE nie wyłączają JS.
Standardy
Główny HTML się nie zmienia, jest taki sam jak w pierwszym niedziałającym przykładzie:
<div id="wrapper"><div id="content"></div><div id="sidebar"></div></div>
Należy teraz przypisać CSS:
#wrapper {overflow: hidden; /* clearance */width: 770px;background-color: #e4f1bb;display: table;}#content, #sidebar {display: table-cell;vertical-align: top;}#content {width: 520px;}#sidebar {width: 250px;background-color: #d7ee7d;}
Za kolor kolumny z główną treścią odpowiada tło całego wrappera. Aby było go widać, należy zaaplikować mu clear - ja to robię przy pomocy overflow. Trzy linijki CSS i koniec zmartwień, wszystko działa jak należy, czy w Firefoksie czy w Operze. Sprawdźcie.
Expressions
W Internet Explorerze 6 i 7 display: table nie odnosi żadnego skutku, więc musimy skorzystać z floatów. A następnie dopasować minimalną wysokość sidebara na podstawie wysokości wrappera. Potrzebne są dwa rozwiązania, bo IE6 ma zabugowany height działający jak min-height - w odróżnieniu od IE7.
Kod dla IE6: <!--[if lte IE 6]><![endif]-->
#sidebar {-iexp: expression(this.parse ? 0 : (this.style.height = this.offsetHeight + 'px',this.parse = 1),helper = (this.style.height < this.parentNode.offsetHeight) ? 0 : (this.style.height = this.previousSibling.offsetHeight));}
Ustawiam na początku wysokość (tak naprawdę min-height) kolumny na podstawie tego jak wysoka jest wyrenderowana w przeglądarce. Następnie sprawdzam czy wysokość sidebara jest mniejsza niż wysokość całego wrappera, jeśli tak nie jest to ustawiam height (znowu, min-height) na wysokość drugiej kolumny.
Kod dla IE7: <!--[if IE 7]><![endif]-->
#sidebar {-iexp: expression(this.parse ? 0 : (this.style.minHeight = this.offsetHeight + 'px',this.parse = 1),helper = (this.offsetHeight < this.previousSibling.offsetHeight) ? (this.style.minHeight = this.parentNode.offsetHeight) : (this.style.minHeight = this.previousSibling.offsetHeight));}
Tutaj po ustawieniu min-height sprawdzam czy wysokość jest mniejsza od wysokości drugiej kolumny, jeśli tak to min-height ustawiam na wysokość wrappera, jeśli nie to na wysokość drugiej kolumny.
I to by było na tyle - działający przykład.
Mały apel - używajmy standardów tam gdzie można, a popsute przeglądarki albo zostawiajmy na pastwę losu albo znajdujmy dedykowane i nieinwazyjne rozwiązania. Kod expressions na pewno można jeszcze ulepszyć, aby uniezależnić się od ilości kolumn, ale na początek wystarczy.
PS: Oczywiście nie mówię teraz, aby każdą nawet najmniejszą implementację Faux Columns zamieniać na wyświetlanie tabelaryczne, nie w tym rzecz - ważne jest też dopasowanie metody do skali efektu końcowego.
Dla poprawnego wyświetlania w Safari należało dodać vertical-align: top, podziękowania dla Wojtka Zająca za komentarz.


