wtorek, 9 czerwca 2015

Responsywne tabele

Jako, że RWD stało się już standardem w projektowaniu stron, a budowanie stron na tabelkach jest już mocno nieprofesjonalne, to do prezentowania danych należy używać jednak tabel. Jak zatem zbudować tabelę aby była prawidłowo wyświetlana np. na telefonie?

Rozwiązanie są co najmniej dwa, a istniejącej tabeli zasadniczo nie trzeba przebudowywać. Poniżej zaprezentuje dwa rozwiązania dla poniższej tabeli:

Struktura tabeli:
<table>
    <tr>
        <th>Nagłówek 1</th>
        <th>Nagłówek 2</th>
        <th>Nagłówek 3</th>
    </tr>
    <tr>
        <td>Rząd 1 Kolumna 1</td>
        <td>Rząd 1 Kolumna 2</td>
        <td>Rząd 1 Kolumna 3</td>
    </tr>
    <tr>
        <td>Rząd 2 Kolumna 1</td>
        <td>Rząd 2 Kolumna 2</td>
        <td>Rząd 2 Kolumna 3</td>
    </tr>
    <tr>
        <td>Rząd 3 Kolumna 1</td>
        <td>Rząd 3 Kolumna 2</td>
        <td>Rząd 3 Kolumna 3</td>
    </tr>
</table>
Minimalne style:
table {
    width: 100%;
    border-spacing: 0px;
}

th,
td {
    border: 1px solid grey;
}

th + th,
td + td {
    border-left: 0px;
}

tr > td {
    border-top: 0px;
}
Powyższy kod można przetestować na http://jsfiddle.net/m6q90ncd

Załóżmy, że chcemy aby nasza tabela dopiero dostosowywała się przy rozdzielczości ekranu równej i mniejszej niż 420px. Do tego musimy wykorzystać media queries z CSS3, które są dostępne już w większości przeglądarek.

Media queries:
@media screen and (max-width:420px) {
    /* ... */
}

Na cele przykładu zastosowałem wymuszenie nie łamania tekstu w komórkach poprzez dodanie wartości white-space: nowrap;

Rozwiązanie minimalne

W tym rozwiązaniu potrzebujemy otoczyć naszą tabelę dodatkowym blokiem (o klasie .rwd) i dodanie wartości overflow: scroll;, celem przesuwania tabeli przy zachowaniu jej wyglądu. Takie rozwiązanie świetnie sprawdza się gdy chcemy dać użytkownikowi możliwość przesuwania treści tabel używając palca. Rozwiązanie to można także zastosować gdy np. nie chcemy z jakichś powodów skalować obrazu lub innych elementów.

Przykład ten można obejrzeć na http://jsfiddle.net/m6q90ncd/1
Aby przetestować wystarczy zmniejszyć okno.

Rozwiązanie profesjonalne

Tutaj wykorzystamy zalety CSS3 oraz tzw. pseudoklasy. Kod HTML pozostaje bez zmian, jednak nasz kod CSS trochę rozbudujemy:
table {
    width: 100%;
    border-spacing: 0px;
    white-space: nowrap;
}

th,
td {
    border: 1px solid grey;
}

th + th,
td + td {
    border-left: 0px;
}

tr > td {
    border-top: 0px;
}

@media screen and (max-width:420px) {
    table {
       border-top: 1px solid grey;
       border-left: 1px solid grey;
    }
    
    tr:first-of-type {
        display: none;
    }
    
    td {
        display: block;
        width: 100%;
        border-left: 0px;
    }
    
    td:nth-of-type(n):before {
        display: block;        
        float: left;
        width: 25%;
        border-left: 0px;
        border-right: 1px solid grey;
    }
    
    td:nth-of-type(1):before {
        content: 'Nagłówek 1';
    }
    
    td:nth-of-type(2):before {
        content: 'Nagłówek 2';
    }
    
    td:nth-of-type(3):before {
        content: 'Nagłówek 3';
    }
}
O ile kwestie wartości border możemy sobie pominąć - pozwalają tylko na zachowanie wyglądu tabel, to muszę tutaj wspomnieć o zawartości progu 420px.
Na początku ukrywamy cały wiersz z nagłówkami, następnie dla każdej pierwszej komórki w każdym wierszu używamy pseudoklasy :before do zbudowania nagłówka, by później dla każdej kolumny wstawić treść naszej kolumny.

Przykład zaprezentowano na http://jsfiddle.net/m6q90ncd/2.

Czy przechowywanie tekstu w pliku CSS jest prawidłowe? Co jeśli nagłówki w tabeli są tłumaczone, jak to rozwiązać w CSS'ie? Na pomoc przychodzą nam dynamiczne własności z CSS3. Ale najpierw musimy dodać data-atrybuty do naszej tabeli:
<table>
    <tr>
        <th>Nagłówek 1</th>
        <th>Nagłówek 2</th>
        <th>Nagłówek 3</th>
    </tr>
    <tr>
        <td data-title="Nagłówek 1">Rząd 1 Kolumna 1</td>
        <td data-title="Nagłówek 2">Rząd 1 Kolumna 2</td>
        <td data-title="Nagłówek 3">Rząd 1 Kolumna 3</td>
    </tr>
    <tr>
        <td data-title="Nagłówek 1">Rząd 2 Kolumna 1</td>
        <td data-title="Nagłówek 2">Rząd 2 Kolumna 2</td>
        <td data-title="Nagłówek 3">Rząd 2 Kolumna 3</td>
    </tr>
    <tr>
        <td data-title="Nagłówek 1">Rząd 3 Kolumna 1</td>
        <td data-title="Nagłówek 2">Rząd 3 Kolumna 2</td>
        <td data-title="Nagłówek 3">Rząd 3 Kolumna 3</td>
    </tr>
</table>
by następnie skrócić nieco nasz kod CSS:
/* ... */

@media screen and (max-width:420px) {
    table {
       border-top: 1px solid grey;
       border-left: 1px solid grey;
    }
    
    tr:first-of-type {
        display: none;
    }
    
    td {
        display: block;
        width: 100%;
        border-left: 0px;
    }
    
    td:nth-of-type(n):before {
        content: attr(data-title);
        display: block;        
        float: left;
        width: 25%;
        border-left: 0px;
        border-right: 1px solid grey;
    }
}

Sprawę pobierania nagłówków z HTML'a załatwia nam wartość attr(data-title).

Całość do obejrzenia na http://jsfiddle.net/m6q90ncd/3.

1 komentarz: