HTML5 & CSS3Webdesign & UX

„Przesuwane tabelki” – czyli sposób na responsywność tabel na stronie internetowej

Responsywne tabele na stronach internetowychZapewnienie użytkownikom urządzeń mobilnych wygodnego i szybkiego przeglądania stron internetowych to dzisiaj już standardowy wymóg. Responsive Web Design to jeden z fundamentów współczesnej sieci, a rosnąca ilość użytkowników tabletów i smartphone’ów zmusza nas do tego by nie zapominać o użytkownikach tychże urządzeń. O ile technologia poszła na tyle do przodu, że RWD stało się możliwe i w podstawach nawet relatywnie łatwe do implementacji to jednak pozostał jeden element HTML, który jakby nie zauważał tych zmian… tabelki. To najczęściej one powodują problemy na stronach mobilnych, ale i na to jest sposób!

„Ukrywamy” tabelkę

Sposobem sprawiającym, iż tabelki wyświetlą się na urządzeniu mobilnym w sposób ergonomiczny i nie psujący layout’u strony jest użycie prostej sztuczki sprowadzającej się do owinięcia naszego delikwenta (czyt. tabelki) div’em z właściwością overflow-x:scroll.

Jak to wygląda w praktyce?

<div class="rwd-table">

 <table>
  <!-- wnętrze tabelki -->
 </table>

</div>

Zamysł jest banalny – musimy owinąć tabelkę w div, który przy odpowiednim stylowaniu zasłoni treść wychodzącą poza niego. Domyślnie każdy div rozciąga się na całą dostępną przestrzeń. W ten sposób jeśli trafi do wnętrza elementu dostosowującego się do szerokości okna przeglądarki widoczna część tabelki nigdy nie „rozwali” nam układu strony, gdyż zostanie ukryta.

Jeśli użytkownik będzie chciał zobaczyć resztę danych w tabelce wystarczy że przesunie suwak (czy w wypadku telefonów i tabletów przesunie treść palcem).

CSS potrzebny dla naszego owijającego div‚a jest następujący:

.rwd-table {
 overflow-x:scroll;
}

Raczej nie chcemy aby na ekranach komputerów pojawiał się bezużyteczny scrollbar, więc możemy użyć mediaqueries aby zastosować powyższy CSS tylko wtedy gdy będzie potrzebny. ‚Roboczo’ założymy, że jeśli ekran ma mniej niż 960px szerokości mamy do czynienia z urządzeniem mobilnym.

@media screen and (max-width:960px) {
	.rwd-table {
		overflow-x:scroll;
	}	
}

Oczywiście nadal może się tak zdarzyć, że przy większych szerokościach ekranu niż 960px tabelka ‚wyleje się’ poza owijającego ją div‚a ze względu na ilość treści, która się w niej znajduje. Aby temu przeciwdziałać możemy przyjąć większy niż 960px breakpoint albo znowu pomajstrować przy CSS.

@media screen and (min-width:960px) {
	table {
		width:100%;
		table-layout: fixed;
	}
}

Powyższy kod zapewni, że tabelka nie przekroczy szerokości owijającego ją div‚a, lecz jest to już tylko uwaga na marginesie bo nie ma to znaczenia z punktu widzenia naszego rozwiązania. Ważne jest tylko aby te style nie były aplikowane dla elementów HTML poniżej pewnej rozdzielczości, gdyż sprawiłyby one, że tabelka wyglądała by po prostu źle, a nasze rozwiązanie nie działało by w zamierzony sposób. Dlatego własnie użyliśmy mediaqueries.

W tym momencie pełny kod CSS powinien wyglądać tak:

@media screen and (max-width:960px) {
	.rwd-table {
		overflow-x:scroll;
	}	
}

table {
	border:1px solid #e1e1e1;
	border-collapse:collapse;
}

@media screen and (min-width:960px) {
	table {
		width:100%;
		table-layout: fixed;
	}
}

That’s all folks… No prawie wszystko… Jest kilka rzeczy, które pomogą nam ulepszyć to rozwiązanie.

Automatyzacja

W tym momencie nasze rozwiązanie działa, ale niestety nie jest zbyt poręczne jeśli chcemy je stosować wielokrotnie na stronie internetowej. W końcu musielibyśmy ręcznie owijać każdą tabelkę w div co jest czasochłonne i mało efektywne.

Z pomocą przychodzi nam JavaScript. Przy pomocy prostego skryptu możemy zautomatyzować czynność przydzielania div‚a z odpowiednią klasą do tabelki i dzięki temu nie będziemy tracić czasu na żmudną pracę. Dla uproszczenia zakładamy, że w projekcie używamy już jQuery:

<script>
	$('table').wrap("<div class='rwd-table'></div>");
</script>

Teraz każda tabelka zostanie owinięta div’em o klasie .rwd-table

Kiedy należy używać?

Jak już wspomniałem to rozwiązanie warto używać jedynie dla urządzeń mobilnych, gdyż nie ma sensu pokazywać użytkownikowi scrollbar’a, dla którego nie ma żadnego zastosowania a tak własnie będzie w przypadku urządzeń desktopowych.

Pierwsze zaproponowane rozwiązanie tego problemu to użycie mediaqueries.

@media screen and (max-width:960px) {
	.rwd-table {
		overflow-x:scroll;
	}	
}

Jego mankament jest jednak taki, że tak na prawdę stosujemy tutaj uproszczenie zakładając, że kiedy okno przeglądarki ma mniejszą szerokość niż 960px mamy do czynienia z urządzeniem mobilnym. Jak znalazł wydaje się aby użyć w tej sytuacji media type ‚handheld’, ale niestety istnieją problemy z kompatybilnością (właściwie jej brakiem) – dla ciekawych więcej informacji na ten temat.

Dlatego jeśli zastanowić się dobrze to rozwiązanie przedstawione na początku wcale nie jest złe… Przecież wiele osób używających komputerów nie używa przeglądarek rozciągniętych na pełną szerokość monitora, co jest już dość powszechnie znanym faktem, a po drugie nawet jeśli używają to przecież mogą chcieć zmniejszyć wielkość okna przeglądarki, prawda? Wydaje się, więc że nasze ‚robocze’ założenia mogą śmiało zachować swoją ważność.

Alternatywnie jeśli zależy komuś na tym by jednak skupić się tylko i wyłącznie na urządzeniach mobilnych to należy sięgnąć po techniki rozpoznawania urządzenia i serwować odpowiedni kod CSS w zależności od tego z jakim urządzeniem mamy do czynienia. Osobiście jednak uważam, że byłby to w tym wypadku przerost formy nad treścią.

Problem z Mac OS

Niestety rozwiązanie problemu responsywności tabelek w postaci ‚przesuwanej tabelki’ ma pewien mankament związany z systemem operacyjnym Mac OS. Od czasu Mac OS X Lion scrollbar’y na stronach są domyślnie ukryte. Może to rodzić pewne kłopoty ponieważ nasza ukryta, przesuwana tabelka może po prostu wyglądać jak kawałek urwanej treści a nie jak tabelka…

Nie mam do końca pewności jakie (i czy w ogóle jakieś) problemy związane z użytecznością pojawiają się w związku z takim zachowaniem, ale wiem, że niektórzy zwracają uwagę na tę kwestię dlatego postanowiłem od razu zaserwować rozwiązanie.

::-webkit-scrollbar {
    -webkit-appearance: none;
    width: 7px;
}
::-webkit-scrollbar-thumb {
    border-radius: 4px;
    background-color: rgba(0,0,0,.5);
    box-shadow: 0 0 1px rgba(255,255,255,.5);
}

Źródło rozwiązania

Powyższy kod zapewnia nam kontrolę nad suwakami w przeglądarkach z silnikiem webkit, ale niesety problem pozostaje aktualny w przypadku przeglądarki Firefox… Jeśli dla was lub waszego klienta jest to baaardzo duży problem to możecie też pokuśić się o rozwiązanie oparte o tzw. custom scrollbar. Dobrym przykladem jest jScrollPane. Sama idea działania będzie podobna, ale implementacja takiego rozwiązanie wymagać będzie większej ilości kroków związanych z odpaleniem dodatkowych skryptów – zainteresowanych zapraszam do dokumentacji pluginu :)

Jeszcze jednym rozwiązanem tej sytuacji jest umieszczenie jakiegoś wizualnego wskaźnika umożliwiającego zrozumienie, iż tabelkę można przesunąć. Jest to właściwie sztuczka mająca na celu zasugerowanie odwiedzającemu możliwość zobaczenia dalszje ukrytej treści. Rozwiązanie mogłoby wyglądać tak:

rwd-table

Naszą wskazówkę musimy umieścić na górze żeby odwiedzający od razu mógł się zorientować, że tabelka nie jest po prostu uciętą treścią i że na dole będzie mógł znaleźć suwak. Taki efekt możemy osiągnąć w bardzo prosty sposób:

.scroll-this {
	position:absolute;
	top:0;
	right:5px;
	z-index:999;
	font-size: 25px;
	padding:5px;
	background:#e1e1e1;
	display: none;
}

@media screen and (max-width:960px) {
	.scroll-this {
		display: block;
	}
}

Natomiast w HTML naszej strony musimy jeszcze dodać:

<div class="scroll-this">Scroll &raquo;</div>

Aby pozycjonować absolutnie div o klasie scroll-this jedynie we wnętrzu div‚a o klasie rwd-table temu ostatniemu należy nadać następujący styl:

.rwd-table {
	position: relative;
}

Natomiast dla uzyskania przestrzeni nad tabelką musimy dodać ten kod:

@media screen and (max-width:960px) {
	.rwd-table {
		padding-top:45px;
	}	
}

Jest to szybki i prosty sposób na uwolnienie się od potencjalnego problemu braku zrozumienia naszych intencji przez użytkowników. Oczywiście w prawdziwych projektach zachęcam do wymyślenia ciekawszej szaty graficznej :)

Webdesign & UX

Przyznam, że dość często stosuję ‚przewijane tabelki’, gdyż uważam że sprawdzają się bardzo dobrze w przypadku małych i średnich (kryterium podziału raczej intuicyjne) tabelek a zarazem są proste w implementacji i łatwe do zrozumienia i używania dla użytkowników.

Najważniejsze jest, że tabelka nie traci swojego charakteru i układu co sprawia, że zestawione dane stają się łatwiejsze do czytania. Z drugiej zaś strony html’owe przewijane tabele nie psują układu naszych mobilnych stron www dzięki czemu nie oszpecają starannie przygotowanych layout’ów.

Nie jest to jednak rozwiązanie, które można zastosować w przypadku dużych, tabelarycznych zestawień. W takich wypadkach trzeba szukać bardziej rozbudowanych rozwiązań.

A jakie Wy macie sposoby na responsywność tabelek?

Sprawdź Demo »

Całość kodu użytego w tym artykule:

<!DOCTYPE html>
<html lang="pl" dir="ltr">
<head>
<title>Tabelka RWD - DEMO - Webroad.pl</title>

<meta charset='utf-8'> 

<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<style>
	.container {
		width:70%;
		margin:20px auto;
	}

	.rwd-table {
		position: relative;
	}

	@media screen and (max-width:960px) {
		.rwd-table {
			overflow-x:scroll;
			padding-top:45px;
		}	
	}

	table {
		border:1px solid #e1e1e1;
		border-collapse:collapse;
	}

	@media screen and (min-width:960px) {
		table {
			width:100%;
			table-layout: fixed;
		}
	}

	td {
		padding:20px;
		border:1px solid #e1e1e1;
	}

	::-webkit-scrollbar {
	    -webkit-appearance: none;
	    width: 7px;
	}
	::-webkit-scrollbar-thumb {
	    border-radius: 4px;
	    background-color: rgba(0,0,0,.5);
	    box-shadow: 0 0 1px rgba(255,255,255,.5);
	}

	.scroll-this {
		position:absolute;
		top:0;
		right:5px;
		z-index:999;
		font-size: 25px;
		padding:5px;
		background:#e1e1e1;
		display: none;
	}

	@media screen and (max-width:960px) {
		.scroll-this {
			display: block;
		}
	}


</style>

</head>
<body>

<div class="container">
	
	<div class="rwd-table">
	
		<table>
			<thead>
				<tr>
					<th>Lorem</th>
					<th>ipsum</th>
					<th>dolor</th>
					<th>amet</th>
					<th>consectetur</th>
					<th>adipiscing</th>
				</tr>
			</thead>
			<tbody>
				<tr>
					<td>Morbi dapibus erat sapien. Duis egestas convallis auctor. Cras vel fermentum orci.</td>
					<td>Ut feugiat vitae eros non fermentum.</td>
					<td>Phasellus id elementum purus, eu lobortis dui.</td>
					<td>Nam convallis metus quis venenatis pulvinar.</td>
					<td>Aenean sollicitudin semper sem vel condimentum.</td>
					<td>Maecenas odio lorem, suscipit id mi eget, ullamcorper ornare quam.</td>
				</tr>
				<tr>
					<td>Maecenas odio lorem, suscipit id mi eget, ullamcorper ornare quam.</td>
					<td>Morbi dapibus erat sapien. Duis egestas convallis auctor. Cras vel fermentum orci.</td>
					<td>Phasellus id elementum purus, eu lobortis dui.</td>
					<td>Ut feugiat vitae eros non fermentum.</td>
					<td>Nam convallis metus quis venenatis pulvinar.</td>
					<td>Aenean sollicitudin semper sem vel condimentum.</td>
				</tr>
				<tr>
					<td>Nam convallis metus quis venenatis pulvinar.</td>
					<td>Aenean sollicitudin semper sem vel condimentum.</td>
					<td>Maecenas odio lorem, suscipit id mi eget, ullamcorper ornare quam.</td>
					<td>Morbi dapibus erat sapien. Duis egestas convallis auctor. Cras vel fermentum orci.</td>
					<td>Ut feugiat vitae eros non fermentum.</td>
					<td>Phasellus id elementum purus, eu lobortis dui.</td>
				</tr>
			</tbody>
		
		<div class="scroll-this">Scroll &raquo;</div>

	</div>

</div>
<!--przed odkomentowaniem najlepiej usunąć div .rwd-table z html ;)
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
	$('table').wrap("<div class='rwd-table'></div>");
</script>
-->
</body>
</html>

Image courtesy of Stuart Miles / FreeDigitalPhotos.net

Tagi:CSS3HTMLpromowanyResponsive Web Design

komentarzy 7

  • Awatar
    Comandeer

    16 lipca 2014 11:37

    Bardzo podstawowa wersja metody, niemniej sprawdza się dobrze. Chociaż osobiście uważam, że tabelka wystająca poza szerokość ekranu działa dokładnie tak samo, bo… też musimy scrollować ;) To jest po prostu estetyczniejsze.

    Co do JS – a od kiedy JS jest od generowania niezbędnego HTML-a? Skoro to jest podstawowa funkcjonalność strony to a) powinna działać bez JS b) nie wszystkie tabelki z tym chcę c) mam większą kontrolę robiąc to ręcznie d) nie zaciągam całego jQ i nie lecę po całym DOM, co dla mobilnych ma znaczenie szczególne

    Odpowiedz
    • Awatar
      Mr.Mr

      16 lipca 2014 15:48

      Demo jest minimalistyczne jeśli chodzi o design. Można by się się pokusić o więcej wizualnych wskazuwej np. cień na prawej krawędzi padający na treść tabelki.

      Co do JS – selektor skonstruowałem na podstawie elementu ale na potrzeby przykładu. W rzeczywistości pewnie wygodniejsza była by klasa. Chociaż z drugiej strony nie da się wykluczyć, że można chcieć owijac tak wszystkie tabelki.

      Dlaczego jQuery i dlaczego owijanie divem przez js – otóż o ile nie mamy do czynienia z małą stroną to robienie tego ręcznie jest raczej problematyczne. W przypadku dużych portali nie wyobrażam sobie jak by to mogło działać bo 1. redaktorzy nie muszą znać html 2 ilość tabelek może być znaczna i teraz co – ktoś będzie siedział jak ten świstak i zawijał tabelki w divy? :D
      Nie jestem aż takim purystą, więc chociaż uznaję, że js nie powinno być od dodawania html to jednak jestem w stanie iść na ustępstwa.
      A jquery to przy założeniu, że pewnie i tak już masz gdzieś w projekcie bo to raczej standard – wiem że to uproszczenie.

      Odpowiedz
      • Awatar
        Comandeer

        16 lipca 2014 15:51

        >otóż o ile nie mamy do czynienia z małą stroną to robienie tego ręcznie jest raczej problematyczne. W przypadku dużych portali nie wyobrażam sobie jak by to mogło działać bo 1. redaktorzy nie muszą znać html 2 ilość tabelek może być znaczna i teraz co – ktoś będzie siedział jak ten świstak i zawijał tabelki w divy? :D

        W obu przypadkach jest proste rozwiązanie: build tools ;) Tym samym nikt się w tym nie grzebie, kod sam się generuje i klient nie jest tym obciążany. Win – win

        Tak, uważam, że jeśli coś się da przepuścić przez jakiegoś typu preprocesor, to należy to zrobić ;)

        Odpowiedz
      • Awatar
        Mr.Mr

        16 lipca 2014 18:18

        Build toolsy jakieś to chyba jedyna alternatywa w tym układzie ;)

        Odpowiedz
      • Awatar
        Comandeer

        16 lipca 2014 18:19

        I w sumie na upartego można to zrobić Twoim kodem JS. patrz: renderowanie w phantom.js i zrzucanie wyniku

        Odpowiedz
  • Awatar
    xyx

    14 lutego 2016 11:05

    Co do pierwszej opcji, to zamiast bawić się z @media nie łatwiej po prostu do kontenera tabeli dodać overflow: auto; albo overflow-x: auto;? Jeśli tabela będzie wykraczać, to doda scrolla, jeśli nie, to nie doda.

    Odpowiedz

Zostaw odpowiedź