Po krótkiej weekendowej przerwie, wracam do przygotowań do egzaminu. Od zeszłego tygodnia jestem już zapisany na konkretny termin (21 marca), a więc czas przejść do decydującego odliczania ;) Do omówienia zostały mi już tylko cztery tematy więc myślę, że się wyrobię… Zgodnie z tematem posta, dziś zajmiemy się interfejsem użytkownika w HTML5. Dowiemy się zatem, co to jest model CSS3 flexbox oraz jak stworzyć layout wielokolumnowy. Do zagadnień należących do tego obszaru należą też nowe możliwości CSS3 dotyczącymi definiowania opływania tekstem elementów blokowych, wyrównywanie do siatki (ang grid alignment)oraz regiony - aby jednak nie zajmować zbyt wiele miejsca, tymi zagadnieniami zajmę się w kolejnym wpisie. Przejdźmy więc do rzeczy!

CSS3 flexbox

“Elastyczne pudełko” to nowy model pozycjonowania elementów blokowych pozwalający nam ustawianie kolejności i pozycji “pudełek” w pionie i poziomie, dodatkowo umożliwiając łatwe decydowanie co zrobić z pozostałym wolnym miejscem. Model ten szczególnie nadaje się do pozycjonowania przycisków, formularzy czy bloków zawartości. Oczywiście równocześnie z nimi można też stosować znane już wcześniej “pływanie” (ang. floating) i inne sposoby pozycjonowania elementów blokowych.

Uwaga! Specyfikacja modelu “flexbox”, zmieniała się kilka razy w czasie! W związku z tym w sieci można znaleźć opisy do kilku różnych jej odmian. Jako, że ja przygotowuje się do egzaminu Microsoftu, w niniejszym poście opisuję wersję, która obsługiwana jest w IE10 (różne przeglądarki obsługują różne implementacje tego modelu, a dla każdej z nich stosować należy przedrostki ‘-webkit-‘, ‘-ms-‘ itp.)!! Zachęcam też do zapoznania się z artykułem na css-tricks.com (data opublikowania to luty 2013, tak że powinno opisywać najlepsze dostępne rozwiązanie w momencie pisania tego posta), zawierającym sposób na takie skonfigurowanie styli aby były one wyświetlane odpowiednio przez wszystkie popularne przeglądarki. Pełny opis modelu “flexbox” dostępny w przeglądarce IE10 dostępny jest na stronach Microsoft’u.

Przykład

Tyle tytułem wstępu, czas na wyjaśnienie jak to działa, no i oczywiście przykłady. Zacznijmy może od zdefiniowania przykładowego kodu HTML, na którym będziemy pracować:

<div id="container">
    <div class="box">jeden</div>
    <div class="box">dwa</div>
    <div class="box">trzy</div>
</div>

Przykład nie będzie odpowiednio przemawiać do wyobraźni bez odpowiedniego ostylowania elementów:

div#container {
    height: 500px;
    width: 500px;
    padding: 1em;
    background-color: gray;
}

div.box {
    width: 100px;
    height: 100px;
    background-color: blue;

    text-align: center;
}

Tak zdefiniowany HTML i CSS spowoduje wyświetlenie szarego prostokąta, a w jego wnętrzu trzy niebieskie prostokąty jeden pod drugim. Mamy już przygotowane “środowisko” testowe, wykorzystajmy zatem “flexbox” do wyświetlenia zdefiniowanych powyżej trzech niebieskich kwadratów poziomo, jeden obok drugiego:

div#container {
    height: 500px;
    width: 500px;
    padding: 1em;
    background-color: gray;

    display: -ms-flexbox;
}

Widzimy powyżej, że odpowiednią wartość właściwości ‘display’ ustawiamy w kontekście kontenera zawierającego elementy, którymi sterować. Zamiast ‘-ms-flexbox’ możemy też użyć ‘-ms-inline-flexbox’ jeśli chcielibyśmy aby nasz kontener traktowany był jako element “inline” a nie “block”.

Od tego momentu, elementy <div> będące wewnątrz kontenera, wyświetlane są biorąc pod uwagę model “flexbox” (domyślnie od lewej, jeden obok drugiego, poziomo). Należy zwrócić uwagę, że jeśli jeden z tych elementów byłby dodatkowo pozycjonowany bezwzględnie (na przykład, poprzez nadanie właściwości “position: absolute”), wówczas wypadłby “spod kurateli” opisywanego zachowania.

Przejdźmy więc do kolejnego przykładu:

div#container {
    height: 500px;
    width: 500px;
    padding: 1em;
    background-color: gray;

    display: -ms-flexbox;
    -ms-flex-flow: row-reverse;
}

W linii ósmej dodaliśmy ustawienie właściwości “-ms-flex-flow” na wartość “row-reverse” - spowoduje to, że nasze elementy zostaną wyświetlone odwrotnie: znajdą się po prawej stronie naszego kontenera w odwrotnej kolejności! I to tylko za pomocą jednej właściwości CSS! ;)

Opcje parametru flex-flow

W przypadku tej właściwości mamy następujące możliwości jeśli chodzi wartości:

  • row - wartość domyślna; elementy wyświetlane od lewej w kolejności takiej jak podana w pliku HTML
  • row-reverse - elementy wyrównane do prawej i w odwrotnej kolejności
  • column - elementy wyświetlane od góry do doły, w podanej w HTML kolejności
  • column-reverse - elementy wyrównane do dołu, w odwrotnej kolejności
  • wrap - jeśli brak miejsca, nie mieszczące się w linii elementy przenoszone są kolejnej linii
  • nowrap - w tym przypadku nie ma przenoszenia do nowej linii
  • wrap-reverse - przenoszenie do nowej linii, a do tego odwrócona kolejność

Do tego mała uwaga: pierwsze cztery wartości można stosować łącznie z trzema ostatnimi - to dlatego, że właściwość “-ms-flex-flow” jest skrótem właściwości “-ms-flex-direction” oraz “-ms-flex-wrap”. Na przykład tak:

-ms-flex-flow: row wrap-reverse;

Myślę, że warto sobie te opcje przetestować, żeby dobrze zrozumieć jak działają poszczególne opcje sterowania przepływem elementów w modelu “flexbox” (na końcu paragrafu podam link do klikalnego przykładu na jsfiddle).

Sterowanie kolejnością

Możemy teraz przejść do ustawiania kolejności elementów. Na potrzeby przykładu, zmodyfikujmy kod HTML drugiego z naszych wewnętrznych “div’ów”:

<div class="box" style="-ms-flex-order: 1;">dwa</div>

Po takiej modyfikacji elementy zmienią kolejność na następującą (zauważyć można też, że do zmiany kolejności służy właściwość “-ms-flex-order”):

"jeden" "trzy" "dwa"

W sumie trochę zaskakujące prawda? Oto dlaczego tak jest: poszczególne elementy w modelu “flexbox” znajdują się w posortowanych grupach. Jeśli żaden z elementów nie ma ustawionej właściwości “-ms-flex-order”, wówczas wszystkie znajdują się w grupie o indeksie 0. Z kolei jeżeli, tak jak w powyższym przykładzie, ustawimy drugiemu elementowi tę właściwość na wartość 1, element ten wędruje do drugiej grupy, o indeksie właśnie 1. Dlatego element “jeden” oraz “trzy” są na początku, a element “dwa” na końcu. Moim zdaniem proste ;)

Rozciąganie wewnątrz kontenera

Następna ciekawa możliwość modelu “flexbox” to zdolność do odpowiedniego rozciągania się elementów wewnątrz “elastycznego” kontenera. Służy do tego właściwość “-ms-flex”. Spójrzmy na poniższy przykład:

div.box {
    width: 100px;
    height: 100px;
    margin: 2px;
    background-color: blue;

    text-align: center;

    -ms-flex: 1 0 100px;
}

Spójrzmy na linię dziewiątą, gdzie ustawiamy opisywaną właściwość dla wszystkich elementów znajdujących się wewnątrz naszego przykładowego kontenera. W zależności od wartości “-ms-flex-direction” (‘row’ albo ‘column’), właściwość “-ms-flex” wpływa na rozciąganie elementów w poziomie lub w pionie. Pierwsza wartość określa proporcje rozciągania względem innych rozciąganych elementów - jeśli w kontenerze istnieje jakaś wolna przestrzeń, element z ustawioną wartością 2 zabierze na swoje rozciągnięcie dwa razy więcej miejsca niż element z ustawioną wartością 1. Druga wartość to “elastyczność negatywna” oznacza to samo co pierwsza z tym, że dotyczy przypadku gdy elementy muszą zostać zwężone a nie rozszerzone. Trzecia wartość jaką podajemy to preferowana szerokość/wysokość (tutaj w pikselach). To również warto przetestować samodzielnie ;)

Elastyczne wyrównywanie elementów

Przejdźmy dalej, kolejna opcja to “elastyczne” wyrównanie elementów. Spójrzmy na poniższy przykład:

div#container {
    height: 500px;
    width: 250px;
    padding: 1em;
    background-color: gray;

    display: -ms-flexbox;
    -ms-flex-flow: row nowrap;
    -ms-flex-align: center;
}

W linii dziewiątej widzimy definicję wyrównania za pomocą właściwości “-ms-flex-align”. W tym przypadku przypisana wartość to ‘center’; poniżej lista wszystkich dostępnych opcji wraz z opisem (wartości te działają inaczej w zależności czy “-ms-flex-flow” ustawione jest na wartość “row” czy “column” lub ich wariacje):

  • start - wyrównanie do początku (do góry dla “row”; do lewej dla “column”)
  • end - wyrównanie do końca (do dołu dla “row”; do prawej dla “column”)
  • center - wyrównanie do środka kontenera (względem góry i dołu dla “row”; względem lewej i prawej dla “column”)
  • stretch - rozciągnięcie (od góry do dołu dla “row”; od lewej do prawej dla “column”)
  • baseline - wyrównanie elementów względem siebie; element który zajmuje najwięcej miejsca podąża za zasadą “start”, reszta równa do niego

Wykorzystywanie pustego miejsca

Ostatnia sprawa to właściwość “-ms-flex-pack”, która służy do definiowania w jaki sposób elementy mają wykorzystywać puste miejsce (bez rozciągania). Dostępne właściwości to:

  • start - pierwszy element ustawiony jest na początku rodzica, a kolejne są do niego przyklejone krawędź w krawędź
  • end - ostatni element ustawiony jest na końcu rodzica, a kolejne są do niego przyklejone krawędź w krawędź
  • center - środkowy element (lub elementy) umiejscowiony jest na środku, a pozostałe przyklejone do niego z obu stron
  • justify - skrajne elementy przyklejone są do skrajnych krawędzi rodzica a pozostałe są rozmieszczone pomiędzy nimi równomiernie

To w zasadzie wszystko na temat modelu “flexbox”. Tak jak obiecałem, zapraszam do przetestowania powyższych przykładów w jsfiddle.net.

Interfejs wielokolumnowy

CSS3 daje nam możliwość łatwego definiowania “pudełek” zawierających tekst sformatowany w postaci kolumn. Do tego celu służą dwie główne właściwości (oraz kilka pomocniczych). Zacznijmy od razu od przykładu, na początek kod HTML:

<div id="container">
    ... dłuuuuuugi tekst ...
</div>

Spójrzmy teraz, jak sformatować zawartość elementu o indeksie “container” jako dwie kolumny (oczywiście zakładamy, że w miejsce “… dłuuuuugi tekst …” rzeczywiście znajdzie się jakiś odpowiednio długi tekst). Oto definicja styli CSS:

#container {
    width: 350px;

    background: lightgray;

    column-width: 150px;
    column-count: 2;
}

Najważniejsze oczywiście z naszego punktu widzenia są linie szósta oraz siódma - najpierw określamy preferowaną szerokość kolumny (powinna być o ponad połowę mniejsza od szerokości całego kontenera). Wartość właściwości ‘column-width’ może być ustawiona na konkretną wartość, lub na wartość ‘auto’ - wówczas szerokość dostosowywana jest w zależności od ustawienia ilości kolumn i szerokości kontenera. Następnie określamy ilość kolumn - w tym przypadku dwie (właściwość ‘column-count’). Możecie sobie to przetestować na jsfiddle.net.

Właściwość-skrót

Jak często bywa w przypadku właściwości CSS, mamy też możliwość użycia właściwości-skrótu. Za pomocą właściwości “columns” możliwe jest jednoczesne ustawienie szerokości kolumny i ilości kolumn. Ustawienia z poprzedniego przykładu za pomocą właściwości skrótowej:

columns: 150px 2;

W przypadku właściwości ‘columns’, nie ma znaczenia kolejność podawania parametrów - silnik przeglądarki potrafi rozpoznać, która wartość podana została jako pierwsza, a która jako druga.

Sterowanie odstępami

To tyle jeśli chodzi o najważniejsze właściwości dotyczące interfejsu wielokolumnowego. Wspomniałem jednak, że dostępny jest także szereg właściwości pomocniczych. Na początek weźmy możliwość ustawiania odstępów między kolumnami (ang. gaps) oraz definiowania wyglądu linii rozdzielającej kolumny. Poniżej wykaż właściwości, służących do sterowania powyższymi zasadami:

  • column-gap - definiuje odstęp pomiędzy kolumnami tekstu; możliwe wartości to “normal” będąca wartością domyślną i równą “1em” lub konkretna wartość zdefiniowana za pomocą standardowych jednostek CSS
  • column-rule-color - pozwala ustalić kolor linii rozdzielającej kolumny tekstu; możliwe jest przypisanie tej właściwości koloru za pomocą wszystkich dostępnych w CSS3 sposobów ustawiania koloru
  • column-rule-width - szerokość linii rozdzielającej kolumny; akceptowane są wszystkie wartości jakie można przypisać do właściwości ‘border-width’
  • column-rule-style - styl linii rozdzielającej kolumny; można przypisać każda wartość jaka akceptowana jest przez właściwość ‘border-style’ (“solid”, “dotted” itp.)
  • column-rule - skrót dla trzech powyższych wartości; wartości podaje się w następującej kolejności: <column-rule-width> <column-rule-style> <column-rule-color>

Wypełnianie wolnego miejsca

Oprócz tego, możliwe jest też określenie sposobu wypełniania dostępnego w pionie miejsca w kolumnie przez tekst. Służy do tego właściwość ‘column-fill’. Przyjmuje ona dwie wartości “balanace”, która powoduje, że tekst będzie wypełniał wszystkie kolumny do mniej więcej tej samej wysokości. Druga opcja to wartość ‘auto’, powodująca że kolumny są wypełniane po kolei maksymalnie jak się da, a ostatnia kolumna wypełniona jest do takiej wysokości do jakiej starczy tekstu.

Przerywanie przepływu wielokolumnowego

Następna ciekawa właściwość to ‘column-span’. Można ją ustawić na przykład dla nagłówków w tekście na wartość ‘all’ co spowoduje, że każde wystąpienie nagłówka spowoduje, że “przerwie” on przepływ wielokolumnowy, i dopiero tekst pod nim znów sformatowany zostanie na wiele kolumn. Drugą możliwą wartością jest “1”, czyli brak przerwania wielokolumnowości (jest to wartość domyślna).

Zachęcam do przetestowania działania interfejsów wielokolumnowych na stronie Microsoftu.

Podsumowanie

To tyle na dziś. Tak jak wspomniałem we wstępie, była to pierwsza część opisu większego zagadnienia dotyczącego “elastycznych interfejsów”. Mam nadzieję, że temat CSS3 flexbox oraz interfejs wielokolumnowy nie jest już dla Ciebie tajemnicą! Zapraszam więc od razu na część drugą!