Konkurs CSS – epilog

Zadanie CSS wzbudziło kilka kontrowersji, dlatego uzgodniliśmy z autorem zwycięskiego rozwiązania, że przygotuje on artykuł wyjaśniający, co i jak działa. Dodatkowo chciałem wyróżnić kod autorstwa Bartka Ziółkowskiego, któremu również – już od siebie – przyznaję nagrodę w postaci książki o HTML5.

Otóż Bartek użył i wskazał prawidłowo pewien błąd nieścisłość w działaniu box-model, a mianowicie proporcje 1:2 różniły się o około 100px w wyniku takiego, a nie innego algorytmu zastosowanego przy obliczaniu wolnej przestrzeni. W swoim rozwiązaniu – mimo że wyrzuciłbym z niego kilka linijek kodu, by były o wiele za ciężkie, umieścił prawidłowy przepis na ominięcie tego problemu, o czym wspomina też szczegółowo artykuł poniżej, autorstwa Krzyśka Urbasa. Zapraszam do lektury!

CSS jest fajny (!) czyli wyjaśnienie rozwiązania konkursu CSS’owego

Witam wszystkich czytelników ferrante.pl. W tym gościnnym wpisie omówię pokrótce zwycięskie rozwiązanie konkursu CSS’owego oraz wyjaśnię pewne wątpliwości. Treść zadania znajdziecie we wcześniejszym wpisie.

Zacznijmy od HTML’a. Tu nie ma co wyjaśniać, prościej się już raczej nie dało :). #wrapper jest potrzebny, aby spełnić warunek, że łączna szerokość kolumn nie będzie większa niż 1600px i jest według mnie ładniejszym rozwiązaniem niż użycie do tego znacznika <body>.

<div id="wrapper">
	<div>kolumna A</div>
	<div>kolumna B</div>
	<div>kolumna C</div>
</div>

Teraz przejdźmy do części głównej rozwiązania. Dla przejrzystości kodu usunąłem „prefixy producentów przeglądarek”. Nadajemy #wrapper właściwość display: box oraz box-orient: horizontal i już mamy układ 3-kolumnowy. O szczegółach działania tzw. Flexible Box Model można poczytać po angielsku lub po polsku. Dodatkowo ustawiam maksymalną szerokość kontenera zawierającego kolumny i jego marginesy, aby w razie czego znalazł się na środku ekranu (niestety działa to według założeń tylko pod Webkitem).

#wrapper {
	width: 100%;
	max-width: 1600px; /* one of task's additional criteria */
	margin: 0 auto;
	display: box;
	box-orient: horizontal;
}

Nadajemy każdej z kolumn właściwości zgodnie z treścią zadania. Kolumna A dostaje stałą szerokość i jest to jedyne miejsce jej edycji (kolejne założenie zadania spełnione). Kolumny B i C dostają zdefiniowaną elastyczność.

#wrapper > div:nth-child(1) { //kolumna A
	width: 200px; /* only one place of editing column A width */
}
#wrapper > div:nth-child(2){ //kolumna B
	box-flex: 1;
}
#wrapper > div:nth-child(3){ //kolumna C
	box-flex: 2;
}

Wiem, że w rozwiązaniu pojawił się problem z zachowaniem szerokości kolumn w ustalonych proporcjach po wypełnieniu ich większą ilością tekstu. Rozwiązaniem problemu jest ustawienie ‚preferowanej’ szerokości każdej z nich, mimo właściwości box-flex. Czyli powinienem dodać jeszcze, mimo wszystko, szerokość każdej z kolumn, jednak w proporcjach. I tak, jeżeli kolumna B dostanie szerokość 200px, to kolumna C, aby zachować proporcje 1:2, musi mieć szerokość preferowaną 400px. Algorytm znalazłem tu. A tutaj poprawione rozwiązanie z „wypchanymi” kolumnami. (link do pliku w zalaczniku maila)

#wrapper > div:nth-child(2){ //kolumna B
	box-flex: 1;
	width: 200px;
}
#wrapper > div:nth-child(3){ //kolumna C
	box-flex: 2;
	width: 400px;
}

Oczywiście z tego, co zbadałem, różne przeglądarki różnie interpretują Flexmodel. Chrome np. dolicza do szerokości kolumny A padding (200px + 2*10px na padding), co wydaje się normalne zgodnie z modelem pudełkowym, jednak Firefox 4 oblicza szerokość kolumny A jako 180px zostawiając miejsce na 10px padding z każdej strony.. W specyfikacji planowane są jeszcze zmiany nazw właściwości, więc myślę, że i tak jeszcze trochę poczekamy zanim naprawdę będziemy mogli korzystać z tej trochę skomplikowanej, ale efektownej ‚technologii’.

Na zakończenie jeszcze krótkie wyjaśnienie części ‚mobilnej’ mojego rozwiązania. Po pierwsze używam tzw. Media Queries, czyli ustawiam specjalne style dla urządzeń spełniających zadane warunki, w tym przypadku gdy strona będzie wyświetlana na ekranie o maksymalnej rozdzielczości 640px (kolejny punkt zadania). Korzystam nadal z Flexbox’a tylko zmieniam układ z horyzontalnego na wertykalny, oraz resetuję szerokość i elastyczność div’ow. Kolumny zamieniają się w sekcje poukładane pod sobą. Zawartość strony jest czytelna także na małych rozdzielczościach. Aby to przetestować nie potrzeba nawet emulatora Opery Mini. Wystarczy zmniejszyć okno przeglądarki. Przy okazji tematu stron w wersji mobilnej polecam bardzo ciekawy artykuł Responsive Web Design.

@media screen and (max-width: 640px) {
	#wrapper {
		box-orient: vertical;
	}
	#wrapper > div {
		width: 100%;
		box-flex: 1;
	}
}

Jeżeli po przeczytaniu tego artykułu (oraz przytoczonych źródeł) nadal coś pozostało niejasne, napiszcie o tym w komentarzach, a postaram się pomóc.

autor:
Krzysztof Urbas, @krzysu

Źródła oraz linki wspomniane w tekście:

  1. http://www.html5rocks.com/tutorials/flexbox/quick
  2. http://dev.w3.org/csswg/css3-flexbox/
  3. http://kamilpelka.com/2010/12/03/css3-flexbox-koniec-z-floatami-kiedys/ (po polsku)
  4. https://developer.mozilla.org/en/CSS/-moz-box-flex
  5. http://www.smashingmagazine.com/2011/01/12/guidelines-for-responsive-web-design/

Komentarze

1

Eh te paddingi ;-)

2

Miło być docenionym ;) Problem z (nie)prawidłowym obliczaniem proporcji między elementami pokazuje, że w kwestii CSS3 jeszcze wiele jest do zrobienia ;)

Bartek Ziółkowski
3

Ogólnie, to też miałem ten problem, tylko że nie pomyślałem o nadaniu szerokości, tylko władowałem jakieś niepotrzebne wrapery i w ostateczności się pogubiłem :) Muszę to jeszcze raz przetestować .
Do zmniejszania okna przeglądarki polecam dodatek do chrome: Resize Google Chrome Window.

4

Czy użycie (w tym konkretnym przypadku) #wrapper > div... jest potrzebne? Można zrobić #wrapper div... i efekt będzie ten sam. Chyba, że jest coś czego nie wiem :)

5

Jeżeli zostawisz boxy puste to nie bo przecież niżej w hierarchii nic już nie masz, ale semantycznie powinno tak być, bo odnosimy się konkretnie do tych potomków a nie wszystkich div-ów wewnątrz :)

6

@shpyo: Wydajność jest lepsza :P To oczywiście żart, ale gdybyśmy mówili o większej stronie, to warto pamiętać. Mało osób wie, ale selektory są czytane od końca. Więc jeśli zaczynamy od diva, to aby przyspieszyć wyszukiwanie po drzewie w górę warto dodać selektor bezpośredniego potomka.

Dodaj komentarz

Dozwolone tagi: <blockquote>, <code>, <strong>