Semantyczny blog w HTML5 Bezpośredni link do sekcji

Ten tutorial przeznaczony jest dla tych, którzy już mają jakiekolwiek pojęcie o HTML. Dobrym miejscem na zdobycie podstaw wiedzy jest Kurs HTML czy też książka Ferrante Moja pierwsza strona internetowa w HTML5 i CSS3.

Witam wszystkich! Przeszukałem kilka for webmasterskich i nie znalazłem ani jednego tutoriala na temat HTML5. Trza to naprawić!

Od razu uprzedzam, że słowa semantyczny i HTML5 z tematu są rozdzielne i część porad można zastosować w starym dobrym HTML4. A na upartego słowa blog w ogóle można się pozbyć.

Punkt wyjścia Bezpośredni link do sekcji

Dobra, do rzeczy. Wyobraźmy sobie, że mamy sobie przykładowy blog:

Kod:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
	<html lang="pl" dir="ltr">
		<head>
			<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
			<meta name="description" content="Super hiper wpis na temat czegokolwiek">
			<meta name="keywords" content="Bardzo ważne słowa kluczowe">
			<script type="text/javascript" src="http://bardzo-zajety-serwer.google.com/jquery.js"></script>
			<script type="text/javascript" src="http://mniej-zajety-serwer.blog.pl/scripty.js"></script>
			<link rel="alternate" type="application/rss+xml" title="Wpisy na RSS" href="http://example.net/feed">
			<link rel="index" title="Strona główna" href="http://example.net">
			<link rel="prev" title="Jakiś hiper poprzedni wpis" href="http://example.net/Jakis-hiper-poprzedni-wpis">
			<link rel="next" title="Jakiś super następny wpis" href="http://example.net/Jakis-super-nastepny-wpis">
			<link rel="canonical" href="http://example.net/Super-hiper-wazny-wpis">
			<link rel="pingback" href="http://example.net/xmlrpc.php">
			<link rel="stylesheet" type="text/css" href="http://example.net/css/style.css">
			<title>Super hiper ważny wpis | Example.net - fajowy blog, na którym bloguję</title>
		</head>
		<body>
			<div id="header">
				<h1><a href="http://example.net">Example.net - fajowy blog, na którym bloguję</a></h1>
				<p>Motto</p>
				<ul id="menu">
					<li><a href="whatever.html">Whatever</a></li>
					<li><a href="whereever.html">Wherever</a></li>
					<li><a href="whenever.html">Whenever</a></li>
				</ul>
				<form action="search.php" method="post">
				<p><input type="text" name="q"><button type="submit" name="submit" value="1">Szukaj</button></p>
				</form>
			</div>
			<div id="main">
				<div class="post" id="Super-hiper-wazny-wpis">
					<h2><a href="http://example.net/Super-hiper-wazny-wpis" rel="bookmark" title="Permalink do Super hiper ważny wpis">Super hiper ważny wpis</a></h2>
					<p class="post info">Opublikowano 07.01.2011 przez <a href="http://example.net/author">Comandeer</a></p>
					<img src="obrazek-do-artykulu.png" alt="Ważny obrazek">
					<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin eu justo enim, ac faucibus massa. Vestibulum in elit aliquam purus sollicitudin adipiscing ac et sapien. Curabitur eleifend justo diam, et viverra nisi. Quisque a ipsum vehicula nunc vestibulum posuere. Suspendisse potenti. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vestibulum porttitor, neque eu congue fermentum, velit ante pellentesque arcu, a posuere risus tortor vel ante. Donec et neque at odio hendrerit mattis sed eu tellus. Nullam accumsan leo ut felis suscipit vehicula posuere erat eleifend. Donec semper lorem eu nibh tincidunt varius.</p>
					<p>Vivamus leo arcu, convallis id iaculis sit amet, fringilla et nunc. Donec aliquam, justo at mollis porta, enim lorem tempor eros, id iaculis arcu elit ac sem. In et erat eu metus ornare vestibulum non at arcu. Integer in nisi massa. Etiam nulla felis, rhoncus non pharetra sed, vehicula eu risus. Vestibulum sodales nunc nisi, vitae gravida nisl. Quisque lacus ipsum, commodo ac hendrerit vitae, porta dapibus tortor. Mauris sed risus diam. Morbi lacus elit, euismod dapibus interdum id, fermentum et mi. Nam at neque orci. Sed ac hendrerit augue. Vestibulum pharetra mattis mattis. Sed porta turpis dolor, condimentum blandit libero. Aliquam non nisi mi. Nulla nec sem elit. Duis blandit viverra lacus, in convallis mauris dictum et. Ut eget risus enim. Suspendisse potenti. Aenean leo odio, luctus quis eleifend quis, consectetur sit amet ipsum. Curabitur commodo leo ac risus dignissim at porttitor turpis fringilla.</p>
					<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ullamcorper neque a magna sodales sodales. Nulla id enim sem, sit amet ultrices dolor. Vestibulum sollicitudin dolor quis quam vehicula egestas. Ut urna erat, gravida a tristique non, congue nec elit. Aenean tincidunt purus sed nisl semper sagittis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus in orci sit amet ligula posuere mollis a in diam. Nam enim tortor, ultrices quis laoreet nec, egestas non leo. Nam non fringilla turpis. Quisque vitae pellentesque nibh. Etiam dictum tincidunt ultricies. Cras sit amet aliquam odio. Morbi quis urna a nulla egestas placerat sed in lacus. Morbi id urna lacinia nunc bibendum ultricies. In pretium leo non odio feugiat porttitor. Donec aliquet purus in purus pretium aliquam. Etiam aliquet nibh ut nibh semper egestas. Cras in purus quam, nec posuere diam. Aliquam erat volutpat.</p>
					<p>Morbi porta blandit nisi at fermentum. Praesent vel sagittis urna. Pellentesque ipsum eros, vestibulum id gravida vitae, dictum vel sapien. Nam placerat lacus non lacus facilisis vitae hendrerit nibh adipiscing. Sed aliquet nisi ligula, eu viverra turpis. Curabitur tincidunt arcu in enim tempus sit amet auctor nunc luctus. Praesent dui turpis, lobortis in euismod quis, fringilla at felis. Nullam ligula purus, mattis nec tristique non, aliquam vitae sem. Quisque sit amet magna magna, eget aliquam orci. Aliquam placerat diam sit amet erat gravida fermentum. Maecenas malesuada nibh quis lorem pellentesque laoreet. Vestibulum pulvinar tincidunt fringilla. Nullam pellentesque felis ac nisi dictum egestas. Nunc metus mi, euismod non convallis nec, varius et felis. Pellentesque vel lacus turpis. In hac habitasse platea dictumst. Morbi sodales mauris a nisi feugiat pulvinar.</p>
					<p>Vivamus vitae lectus ut dui luctus iaculis. Pellentesque quis lectus id ipsum venenatis bibendum. Pellentesque non magna nec purus mollis suscipit. Nulla vestibulum interdum ante, vestibulum ullamcorper est vulputate vitae. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Quisque aliquet mollis rhoncus. Phasellus imperdiet posuere bibendum. Quisque consequat imperdiet nibh vitae pretium. Suspendisse quis eros libero, non luctus mauris. Nulla laoreet nibh at eros scelerisque condimentum. Cras aliquam velit at orci luctus et tincidunt arcu scelerisque. Donec at quam magna. Integer leo leo, ultrices facilisis bibendum vel, feugiat interdum neque. Fusce vitae nibh sapien, sit amet consequat velit. Fusce adipiscing tortor id nibh fringilla sollicitudin. Donec sodales sapien in sapien rutrum rutrum. Nam quis enim nec nibh varius mattis nec in ante. Morbi non est eu diam elementum interdum. Morbi at odio non libero tempus eleifend nec quis ligula. Cras pellentesque mauris sit amet felis vestibulum tincidunt.</p>
				</div>
				<div class="tags">
					<h3>Tagi</h3>
					<ol>
						<li><a href="http://example.net/tag/Tag1">Tag1</a></li>
						<li><a href="http://example.net/tag/Tag2">Tag2</a></li>
					</ol>
				</div>
				<h3>Komentarze</h3>
				<ol class="comments">
					<li class="alt" id="comment-25">
						<small><a href="#comment-25" title="">30.12.08, 21:19</a> </small>
						<cite><a href="http://example.net/"><img alt="Avatar użytkownika Comandeer" src="http://avatary.gdziekolwiek.com/Comandeer" height="48" width="48">Comandeer</a></cite>
						<div><p>Ale komentarz!</p></div>
					</li>
				</ol>
				<h3>Dodaj komentarz</h3>
				<form action="http://example.net/comment.php" method="post" id="add_comment">
					<fieldset>
						<legend>Napisz komentarz</legend>
						<dl>
							<dt><label for="comment_author">Nick</label></dt>
								<dd><input type="text" name="author" id="comment_author" tabindex="1"></dd>
							<dt><label for="comment_email">E-mail</label></dt>
								<dd><input type="text" name="email" id="comment_email" tabindex="2"></dd>
							<dt><label for="comment_url">Strona</label></dt>
								<dd><input type="text" name="url" id="comment_url" tabindex="3"></dd>
							<dt><label for="comment_comment">Komentarz</label></dt>
								<dd><textarea name="comment" id="comment_comment" cols="48" rows="7" tabindex="5" ></textarea></dd>
							<dd><button name="submit" type="submit" id="comment_submit" tabindex="5">Wyślij</button></dd>
						</dl>
						<input type="hidden" name="comment_post_ID" value="88">
					</fieldset>
				</form>
			</div>
			<div id="aside">
				<div class="author">
					<h3>O autorze blogaska</h3>
					<p>Nazywam się Comandeer, mieszkam w uroczym miasteczku Świętochłowice i interesuję się webmasterką.</p>
				</div>
				<div class="tags cloud">
					<h3>Tagi</h3>
					<ul>
						<li><a href="http://example.net/tag/Tag1">Tag1</a></li>
						<li><a href="http://example.net/tag/Tag2">Tag2</a></li>
						<li><a href="http://example.net/tag/Tag3">Tag3</a></li>
						<li><a href="http://example.net/tag/Tag2">Tag4</a></li>
					</ul>
				</div>
				<div class="archive">
					<h3>Archiwum</h3>
					<ol>
						<li><a href="http://example.net/archiwum/2011/01">Styczeń 2011</a></li>
						<li><a href="http://example.net/archiwum/2010/12">Grudzień 2010</a></li>
					</ol>
				</div>
			</div>
			<div id="footer">Copyright © 2011 by <a href="http://example.net/author">Comandeer</a></div>
		</body>
	</html>

Nic nadzwyczajnego – blog jakich dużo w Internecie. Przyznam się bez bicia, że ten przykładzik to połączenie blogu Lea Verou i naszego kochanego Roberto. Kodu nie będę wyjaśniał, bo mam wrażenie, że powinien być jasny. Ot, zwyczajny wpis na zwyczajnym blogu, poniżej komentarze, formularz do komentowania i jakieś tam dodatkowe info w bocznym panelu. Specjalnie nie dorzucam CSS, bo jestem z tych purystów, co to twierdzą, że strona to treść i kod, a wygląd jest jedynie dodatkiem.

Nasz cel Bezpośredni link do sekcji

Chcemy być cool i porzucamy zgrzybiałego HTML4 na rzecz jego potomka! Poza tym spróbujemy nadać większe znaczenie naszej treści, przede wszystkim dla użytkownika, pamiętając, że co dobre dla użytkownika, jest także (najczęściej) dobre dla Google. Do tego celu wykorzystamy m.in. mikroformaty i nowe znaczniki z HTML5.

Nowy DOCTYPE Bezpośredni link do sekcji

Okey, to zaczynamy. Najpierw omówię przejście na HTML5, bo tego jest najwięcej, a później doszlifujemy resztę. Pierwsze, co należy zmienić, to ten cały rozwlekły DOCTYPE. W HTML5 mamy króciutki i ładniutki:

Kod:

<!DOCTYPE html>

I już – po bólu. Twój blog właśnie stał się cool. Jeśli nie jesteś odważny, migrację na HTML5 możesz zakończyć w tym miejscu. Jeśli chcesz jednak poznać jaką zmianę w semantyce przynosi, pójdź za mną, a pokażę Ci piękno…

Ustawienie kodowania Bezpośredni link do sekcji

Kolejnym wrogiem jest ustawienie kodowania. Po nowemu zapisać je można następująco:

Kod:

<meta charset="utf-8">

To króciutkie meta obsługuje nawet IE6. Zdziwieni? A powinni, bo ta składnia powstała z… błędu. Na wielu stronach bowiem można było znaleźć potworka typu

Kod:

<meta http-equiv="Content-type" content="text/html;charset="UTF-8"">

Przeglądarki stwierdziły bowiem, że nie ma sensu parsować nieprawidłowego znacznika i po prostu znalazły inny sposób: szukały czegoś na wzór charset=["]*[a-z0-9]["]* (mam nadzieję, że to dobre wyrażenie regularne…). No i tak już zostało, a później to… ustandaryzowano w ramach HTML5. BTW ten znacznik i tak nie ma jakiegokolwiek sensu, bo kodowanie jest narzucane przez nagłówki HTTP. Można je kontrolować ręcznie, np. przez PHP:

Kod:

<?php header('Content-Type: text/html;charset=UTF-8'); ?>

Warto także zwrócić uwagę, że w specyfikacji HTML5 napisano, że nazwa kodowania jest case insensitive, co oznacza, że wielkość znaków nie ma znaczenia i UTF-8 to to samo co utf-8 czy nawet UtF-8.

Dołączanie arkusza stylów i skryptów Bezpośredni link do sekcji

Teraz słówko o arkuszu stylów: jeśli dołączamy go poprzez link, można usunąć zbędny atrybut [type] – arkusze i tak zawsze są typu text/css.

W przypadku skryptów sprawa jest nieco bardziej skomplikowana. Jeśli mówimy o "normalnym" skrypcie (np. dołączenie jQuery, slider), wówczas [type] jest całkowicie zbędne – i tak jest to zawsze [type=text/javascript]. W specyfikacji są podane jednak także inne sposoby wykorzystania script, m.in. jako systemu szablonów. Ostatnio także dodano do specyfikacji [type=module], które pozwala wczytywać moduły ES. Niemniej na razie wsparcie jest słabe (żadne…).

Obsługa starszych przeglądarek Bezpośredni link do sekcji

Niestety, z obsługą reszty znaczników nie jest już tak kolorowo i IE wymaga odpowiedniego skryptu, który trza dodać w head (IE 9 na szczęście jest już normalny):

Kod:

<!--[if lt IE 9]>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]--> 

Po więcej informacji o tym skrypciku zapraszam do oficjalnego repozytorium na GitHubie, na blog Remy'iego Sharpa i blog Paula Irisha. Jeśli natomiast w przyszłości wzbogacisz swój blog o jakieś nowinki z HTML 5 APIs (np. nagrywanie video komentarzy), to warto zapoznać się też z pojęciem feature detection (ang. wykrywanie funkcjonalności) i bibliotekami Modernizr czy has.js. Dodatkowo można też wykorzystać usługę Polyfill.io, która sama decyduje, jakie polyfille są potrzebne i je dołącza. Warto także poczytać o technice cut the mustard.

Tutaj warto też od razu zwrócić uwagę na fakt, że nieznane przeglądarce elementy są nieostylowane w żaden sensowny sposób i przez to możemy dostać np. liniowe section, co raczej jest niezbyt pożądane. Na szczęście problem ten rozwiązuje normalizacja stylów (nawet jeśli nie chcesz używać nowych znaczników, to i tak powinieneś normalizować lub resetować), przypisując najbardziej podstawowe style odpowiednim elementom.

Jeśli się zastanawiasz a co z użytkownikami IE 9-, którym nie działa JS?, odpowiem tak: jest ich na tyle mało, że nie sądzę, byś kiedykolwiek na nich trafił. Niemniej istnieją dwie alternatywy dla znaczników HTML5 (na chwilę obecną już bym ich nie polecał): używanie div[role] lub (prawie) nieużywanie znaczników HTML5. Warto się także zastanowić, czy nie porzucić całkowicie HTML5 Shiva jeśli mamy pewność, że użytkownicy naprawdę starych IE nam się nie trafią.

Warto także wspomnieć o komentarzach warunkowych dla IE – niemniej w IE 10 już nie działają, a prawdę mówiąc w dzisiejszym webdevie istnieją o wiele lepsze metody (jak wspomniane wyżej feature detection).

Nagłówek i nawigacja Bezpośredni link do sekcji

Dobra, head na razie zostawmy i przejdźmy do body. Pierwsze, co rzuca nam się w oczy, to div#header. Nic nie znaczy, prawda? Nawet [id=header] tego nie ratuje, ponieważ identyfikatory nie mają żadnego znaczenia semantycznego (pogrubienie moje):

Identifiers are opaque strings. Particular meanings should not be derived from the value of the id attribute

"http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#the-id-attribute"

HTML5 rozwiązuje ten problem, wprowadzając znacznik header. Jak sama nazwa wskazuje, służy on do oznaczania nagłówków i świetnie się nadaje do oznaczenia nagłówka strony. Zatem zamieńmy nasz div#header na header#header. Niby mała zmiana, a semantyka kodu rośnie. Ale, ale – to jeszcze nie wszystko! Spójrzmy na nagłówek: mamy tam h1 z tytułem strony i p z mottem. Fajnie by było gdyby motto też było nagłówkiem, ale co z hierarchią nagłówków? Czy przypadkiem się nie zaburzy? Na chwilę obecną musisz wiedzieć, że podtytuły, zgodnie z tym, co czytamy w specyfikacji, winny być oznaczane przy pomocy p, tudzież h* > span. Do samej hierarchii nagłówków jeszcze wrócimy.

Jeśli już zmieniamy wszystko, to pewnie pomyślicie, że menu też można zmienić. Oczywiście macie rację! W tym celu posłużymy się znacznikiem nav, który powstał specjalnie po to, aby oznaczać elementy nawigacyjne.

Co prawda w HTML5 istnieje także element menu, ale służy on tworzeniu menu dla aplikacji (menu kontekstowe czy toolbary) i nie należy go mylić z nav.

W naszym nagłówku pozostał jeszcze formularz wyszukiwania, ale do niego wrócę później i omówię go razem z formularzem dodawania komentarzy. W chwili obecnej nasz nagłówek powinien wyglądać mniej więcej tak:

Kod:

<header id="header">
	<h1><a href="http://example.net">Example.net - fajowy blog, na którym bloguję</a></h1>
	<p>Motto</p>
	<nav id="menu">
		<ul>
			<li><a href="whatever.html">Whatever</a></li>
			<li><a href="whereever.html">Wherever</a></li>
			<li><a href="whenever.html">Whenever</a></li>
		</ul>
	</nav>
	<form action="search.php" method="post">
		<p><input type="text" name="q"><button type="submit" name="submit" value="1">Szukaj</button></p>
	</form>
</header>

Artykuł Bezpośredni link do sekcji

Główne ramy Bezpośredni link do sekcji

Oki doki, teraz czas na danie główne: treść artykułu! Zapewne zauważyliście, że jest opatulona w dodatkowy div#main. Jak już wspomniałem, divy nie mają jakiegoś specjalnego znaczenia semantycznego, dlatego w HTML5 powstało mnóstwo nowych znaczników, które mogą divy zastąpić. Jednym z nich jest section, którym oznacza się pewne części dokumentu, które można wyróżnić ze względu na ich przeznaczenie. W tym wypadku użycie section jest dozwolone, gdyż wyznacza obszar artykułu wraz ze wszystkimi "dodatkami" do niego (tj. tagi i komentarze) – całość tworzy pewną całość treściową. Właśnie do takich przypadków stworzono section! Jednak to, że jest dozwolone, nie oznacza, że na pewno trzeba ten fragment oznaczyć. Za HTML5 Doctor:

But what would be the purpose of marking it [main content] up specifically, anyway? If you need to style it, use a div. An assistive technology like a screenreader can find the main content because it is the first thing inside a page that isn’t a header, nav or footer.

Niemniej potrzeba oznaczenia głównej treści strony stała się na tyle duża, że dodano do HTML5 nowy znacznik, służący wyłącznie temu – main. Warto dodać, że ten znacznik – ze względów dostępności – powinien znaleźć się na stronie wyłącznie raz, co powoduje niekończący się spór między WHATWG i W3C (tutaj warto zwrócić uwagę na to, że istnieją dwa standardy HTML – w tym tutorialu będziemy się opierać głównie na wersji W3C jako tej, która w dogłębniejszy sposób zajmuje się problemami semantyki i dostępności).

Dobra, teraz zatrzymujemy się na div.post – to też można ulepszyć. W HTML5 pojawia się article, który służy do oznaczania… artykułów (nie wpadliście na to, co?), a dokładniej semantycznej całości, która może być prezentowana samodzielnie (dość swobodna interpretacja specyfikacji). Wpis na blogu pasuje idealnie do tej definicji. No, na co czekasz – wyrzuć tego diva!

W tym miejscu pozwolę sobie na małą dygresję. Przed chwilą oznaczyliśmy główną treść strony przy pomocy main. Teraz oznaczamy artykuł przy pomocy article. Jest to całkowicie poprawne, jednakże przy stronach, na których znajduje się tylko jeden artykuł (jak w naszym przypadku), można się zastanawiać, czy aż tak dokładny podział jest konieczny. Wówczas można pomyśleć nad rozwiązaniem typu article[role=main] (o [role] napisałem ciut niżej) lub po prostu pozostawieniu samego main.

Nagłówek Bezpośredni link do sekcji

Znowu natykamy się na nagłówek, a tuż za nim na akapit z informacjami na temat daty i autora postu. Te rzeczy doskonale nadają się na nagłówek, prawda? No to otoczmy to header! Nagłówki nie są tylko i wyłącznie dla całych stron – mogą je mieć także sekcje i artykuły. To ma sens, ponieważ praktycznie każdy wpis na blogu ma swój tytuł, swojego autora itd., które wcale nie muszą być zgodne z autorem i tytułem całej strony. Ale to jeszcze nie wszystko: daty też mają swój własny znacznik w HTML5! Nie, nie jest to date wbrew pozorom, lecz time. Wraz z nim pojawia się nowy atrybut: [datetime], który przyjmuje datę w formacie ISO-8601. Ten znacznik doskonale pasuje do oznaczenia daty publikacji wpisu.

Obrazki Bezpośredni link do sekcji

Dobra, później mamy obrazek. No cóż, przynajmniej obrazka tykać nie będzie… – pomyślą ci, których przytłacza ogrom nowych możliwości. Niestety, obrazek też można ulepszyć! W tym wypadku posłużymy się znacznikiem figure. Jego zadaniem jest oznaczanie danych multimedialnych, które są istotne dla danego artykułu (sekcji), lecz mogą także być prezentowane samodzielnie. Na chłopski rozum: masz ilustrację do swojego artykułu, użyj figure!

Co rozumiem pod pojęciem "ilustracja"? Wystarczy wyobrazić sobie książkę, w której mamy obrazek (albo tabelkę, zdjęcie itp.), a pod nim podpis typu "Ryc. 1. Pusta szafa". Dzięki takiemu oznaczeniu można wyciągnąć tego typu obiekt poza pierwotny kontekst, a wciąż będzie mieć te same znaczenie (pusta szafa z podpisem to wciąż pusta szafa). Natomiast wszelkie ozdobniki graficzne, które są w artykule, żeby było ładnie, to po prostu ozdobniki. Ilustracja musi nieść ze sobą jakąś wartość semantyczną (łatwo to stwierdzić po tym, że da się wymyślić sensowny opis) i nie może zależeć od kontekstu swojego występowania (jeśli tekst traci sens po przesunięciu danego obiektu, to znak, że to nie jest kandydat na figure).

Kod:

<figure>
	<img src="http://example.net/images/obrazek-do-artykulu.png" alt="Ważny obrazek">
	<figcaption>Bardzo ważny obrazek[…],który jest bardzo ważny</figcaption>
</figure>

W figcaption można umieścić dokładny opis danego obiektu. Napisałem "obiektu", bo równie dobrze w figure można umieścić filmik (np. poprzez HTML-owy video – tak, też nowy znacznik) czy dźwięk (audio).

Mała dygresja: [alt] jest potrzebny dla obrazka z powodów dostępności. Jednakże czasami… warto pozostawić go pustym, z tych samych powodów. O co chodzi? Otóż nie ma sensu powielać opisu obrazka, jeśli jest on zawarty w otaczającej go treści (np. jeśli w figcaption jest dokładny opis tego, co na obrazku, należy zostawić [alt] pusty; często zdarza się jednak, że w takim wypadku [alt] opisuje co jest na obrazku, a figcaption dodaje do tego interpretację/wyjaśnienie; np [alt]czerwony ptak na gałęzi, figcaptionKarłowata odmiana papugi). W takich wypadkach można użyć [aria-labelledby]. W3C przygotowało kilka wskazówek (zresztą nie tylko ono). Ciekawy jest także fakt, że [alt] to nie jedyny sposób na zapewnienie dostępności.

Jeśli chodzi o sam znacznik img: jego również można ruszyć, a to za sprawą tagu picture. Przykładzik, wprost ze specki:

Kod:

<picture>
	<source media="(min-width: 45em)" srcset="large-1.jpg 1x, large-2.jpg 2x">
	<source media="(min-width: 18em)" srcset="med-1.jpg 1x, med-2.jpg 2x">
	<source srcset="small-1.jpg 1x, small-2.jpg 2x">
	<img src="small-1.jpg" alt="">
</picture>

Ci, którzy bawili się video/audio na pewno znają znaczniki source. Wskazują one źródło elementu multimedialnego (w tym wypadku obrazka). Które source ma wybrać przeglądarka? O tym decydują media queries, zawarte w atrybucie [media]. Warto zauważyć także, że często podawane są dwa obrazki, dodatkowo oznaczone "1x" i "2x". Są to wersje przystosowane do gęstości pikseli ("1x" dla normalnych monitorów, "2x" dla Retiny). Pojawia się też img. Zgodnie z najnowszą wersją picutre, img jest jego główną składową – cała otoczka służy jedynie wyborowi odpowiedniego pliku grafiki, który jest następnie ładowany do rzeczonego img. Proste i skuteczne, a zarazem dostarcza doskonałego fallbacku dla starszych przeglądarek.

Jaki sens ma stosowanie picture? Wyobraźmy sobie, że mamy zdjęcie prezydenta wygłaszającego orędzie do narodu. Owszem, można zastosować tricki w CSS, żeby obrazek nam się ładnie zeskalował na komórce, ale… No właśnie - będziemy mieli małe, rozmazane wiadomo co. Natomiast przy pomocy picture komórkom i innym mniejszym ekranom możemy zaserwować odpowiednio mniejszy (zatem i lżejszy) obrazek ze zbliżeniem na twarz prezydenta. Nie dość, że iPhone będzie musiał mniej ściągnąć, to jeszcze dostanie zdjęcie przedstawiające to, co najważniejsze. Oczywiście działa to też w drugą stronę i super wypasionym ekranom panoramicznym o przekątnej 100 cali możemy wysłać zdjęcie prezydenta + całego słuchającego go tłumu.

Warto zauważyć, że rozwojem technik związanych z responsywnością zajmuje się powołana "grupa społeczna" (która jest teraz częścią większej inicjatywy). To właśnie ona stoi za powstaniem tagu picture oraz jego mniej inwazyjnych odpowiedników: atrybutów [srcset] i [sizes] dla tagu img. Warto też nadmienić, że WHATWG odrzuciło początkowo propozycję znacznika picture, promując [srcset]. Najlepiej wyjaśnia to Ian Hickson - najbardziej wływowy człowiek w Sieci (współ)redaktor żyjącego standardu:

[…]let’s look at design. The way we usually approach ideas is that we describe the problem, then we come up with solutions to the problem and compare them, by evaluating them against the problem. This is where most concrete proposals run into a “no”; something else got the “yes” instead. <picture> is an example of this: we described the problem (that took a few months of back and forth), and then once we had a problem description, I looked at the various proposals, and synthesised a solution based on those that addressed the problems adequately while trying to avoid some common design pitfalls based on lessons we’d learnt from previous ideas. So for example with <picture>, we learnt with <video> and <source> that having multiple elements for selecting a resource is a huge design pitfall, so when designing a solution to the problem here, I avoided that (hence the srcset="" design based on CSS’s image-set() proposal).

"http://html5doctor.com/interview-with-ian-hickson-html-editor/"

Osobiście w tym względzie nie zgadzam się z Ianem i raczej widziałbym znacznik picture (+[srcset]) niż "napakowany" img. No, ale jak sam Hixie mówi:

In reality, I can’t really say either “yes” or “no”. What I say doesn’t mean anything: I don’t write any browsers. The browser vendors say “no” to me all the time, by just not implementing what I’ve specced.

"http://html5doctor.com/interview-with-ian-hickson-html-editor/"

Rzeczywistość szybko zweryfikowała poglądy Hixiego i obecnie picture już jest w kanonicznym HTML. Tym samym w cień odeszło nowe rozwiązanie – [src-n], które łączy w sobie niejako picture i [srcset] w prostsze, bardziej zrozumiałe rozwiązanie. Coraz częściej próbuje się także zrzucić odpowiedzialność za rozwiązanie problemu na serwer (co IMO jest bardzo rozsądnym rozwiązaniem). Jednak najlepszym (ale też najbardziej długotrwałym) rozwiązaniem wydaje się po prostu stworzenie nowego formatu obrazków. Zresztą nieważne tak naprawdę jak problem responsywnych obrazków zostanie rozwiązany – najważniejsze, że(by?) został rozwiązany.

Outline Bezpośredni link do sekcji

Dobra, akapitów się (jeszcze) zmienić nie da, więc treść mamy z głowy. Przyjrzyjmy się zatem hierarchii nagłówków w HTML5. Jest to o tyle ważny temat, że hierarchia nagłówków odzwierciedla całą strukturę treści na stronie (stanowi jej spis treści) i dzięki temu ułatwia nawigację dla osób korzystających z czytników ekranowych.

W HTML5 istniał ambitny plan odejścia od tradycyjnych znaczników h1h6 i przejścia na hierarchię treści opartą na nowych znacznikach sekcjonujących (section, article itd.). Niemniej nikt tego nie zaimplementował i ostatecznie postanowiono pozbyć się tej fikcji. Stąd jedynym poprawnym sposobem tworzenia hierarchii treści na stronie HTML5 jest połączenie obydwu metod (tagi sekcjonujące + różnicowanie ważności nagłówków), gdyż nowy algorytm zostanie usunięty ze specyfikacji i zastosowanie go spowoduje, że AT dostaną spłaszczoną hierarchię nagłówków (co raczej jest średnim pomysłem).

Jeśli chcesz przetestować swój outline, wystarczy zaznaczyć odpowiednią opcję (Show outline) w walidatorze.

Jako ciekawostkę można tutaj powiedzieć, że umiejętnie korzystając z atrybutu [role=heading] i [aria-level] można tworzyć hierarchię na samych h1, tak, jak zostało to opisane w specyfikacji. Metodę tę stosuje niestandardowy znacznik html5-h (przy pomocy standardu Web Components i frameworka Polymer, z którym miałem już do czynienia). Niemniej warto zauważyć, że to bardziej hack niźli eleganckie rozwiązanie problemu. Jednakowoż [aria-level] można użyć w przypadku, gdy potrzebujemy więcej niż 6 poziomów zagłębień nagłówków (do "pogłębienia" h6 – bardzo edge'owy przypadek, ale warto o tym wiedzieć).

Komentarze Bezpośredni link do sekcji

Okey, to jeszcze słówko na temat wyświetlania komentarzy: w HTML5 w końcu cite działa tak, jak nakazuje logika i nie ogranicza sie już tylko i wyłącznie do oznaczania tytułów dzieł, ale także innego rodzaju źródeł, w tym osób. Co więcej, umieścić można każdy komentarz w article, dzięki czemu stworzylibyśmy swoistą hierarchię artykułów (tzn. każdy komentarz byłby "podartykułem" wpisu). Jest to logiczne, ponieważ każdy komentarz może być wyświetlany "samodzielnie" (wszak opinia o dziele A może istnieć odrębnie od tego dzieła). Przywodzi to na myśl stare, dobre gazety, w których odpowiedzią na konkretny artykuł jest… inny artykuł.

Jeśli jednak już zgodzimy się na oznaczanie komentarzy przy pomocy artykułu, czekają nas kolejne wyzwania. Otóż regułą kciuka jest, by każdy artykuł miał odpowiedni nagłówek. Lecz jaki nagłówek powinien mieć komentarz? Wywiązała się gorąca dyskusja na ten temat, która skłoniła mnie do refleksji na temat kodu komentarzy. Na większości stron w Sieci, a także w specyfikacji, komentarze są traktowane jako wyjątek, który nie posiada nagłówka (bo są to artykuły zagnieżdżone). Niemniej na chwilę obecną uważam, że dodanie jako nagłówka nazwy użytkownika nie zaszkodzi – pozwoli to nam w łatwiejszy sposób śledzić komentarze danego użytkownika (np. naszego ulubionego hejtera!). Pomysł, by w nagłówku czy etykietce [aria-label] dodawać pierwsze słowa komentarza ostatecznie odrzuciłem – z tego samego powodu, z jakiego niekiedy warto zostawić puste [alt]: nie ma sensu dublować treści.

Nie oznacza to jednak, że np. w RSS nie warto zamieścić tego typu opisu. W przypadku jednak strony internetowej jest to zbędne.

Ostatecznie kod komentarzy wygląda tak:

Kod:

<article id="comment-25">
	<header class="comment-meta">
		<a href="#comment-25"><time datetime="2011-01-07T20:41:06+00:00"">07.01.2011, 20:41</time></a>
		<h4><b><a href="http://example.net/"><img alt="" src="http://avatary.gdziekolwiek.com/Comandeer" height="48" width="48">Comandeer</a> skomentował</b></h4>
	</header>
	<p>Ale komentarz!</p>
</article>

Nagłówki jako punkty nawigacyjne Bezpośredni link do sekcji

Jedną z praktyk poprawiających użyteczność strony internetowej jest bez wątpienia możliwość łatwego nawigowania po jej zawartości. W przypadku tradycyjnych stron internetowych można to osiągnąć dzięki kotwicom. Najlepiej je przypiąć dla każdej sekcji lub nagłówka (jeśli nie mamy sekcji). Ma to bardzo proste uzasadnienie: sekcje/nagłówki dzielą stronę na sensowne części. Gdyby porównać stronę do książki, poszczególne nagłówki oznaczałyby rozdziały. Jeśli chcemy komuś powiedzieć, żeby przeczytał sobie o skorupiakach, podajemy mu nazwę konkretnego rozdziału a nie tytuł grubej encyklopedii, prawda? Tak samo jest w przypadku stron internetowych – zamiast podać odnośnik do całej strony, często o wiele lepiej jest podać odnośnik do konkretnego fragmentu. Stąd zachęcam do dodawania [id] do każdej sekcji/nagłówka.

Choć cały kod strony najlepiej pisać w języku angielskim, [id] służące do nawigacji są wyjątkiem i powinny być w języku, w jakim jest napisana cała strona internetowa. Wystarczy sobie pomyśleć, który adres sprawia więcej sensu: strona.pl/artykul#section czy jednak strona.pl/artykul#sekcja.

Zawartość nawigacyjnego [id] najlepiej stworzyć przez stworzenie sluga nagłówka, do którego chcemy odesłać czytelnika, np. "Moje piórka" dadzą nam [id=moje-piorka].

Całość złożona do kupy Bezpośredni link do sekcji

A oto szkielet naszej treści (spokojnie, na końcu podam całość):

Kod:

<main>
	<article id="tytul">
		<header>
			<h1><a>Tytuł</a></h1>
			<p>Autor <time datetime="2011-01-07T20:40:06+00:00">07.01.2011</time></p>
		</header>
		<div>
		treść
		</div>
		<footer>
			<section>Tagi</section>
		</footer>
		<section>Komentarze
			<article></article>
			<form>Dodanie komentarza</form>
		</section>
	</article>
</main>

Warto zauwązyć, że sama treść artykułu znajduje się po prostu w div. Wiadomo, że jest to treść artykułu (jest w article i nie jest ani w nagłówku, ani w stopce), dlatego co najwyżej można umieścić ją w div w celu ułatwienia stylizacji. section również tutaj nie pasuje, bo nie da się utworzyć żadnego sensownego nagłówka ("Treść artykułu" brzmi jak wymyślone na poczekaniu). Niemniej section w artykule jak najbardziej pojawić się może, ale w przypadku gdy artykuł zawiera w sobie podtytuły (jak np. ten tutorial – nie, nie wzorujcie się na jego kodzie). Wówczas każdy podtytuł z odpowiadającą mu treścią może być traktowany jako osobna section. Z kolei tagi można potraktować jako footer (dodatkowe, poboczne informacje do artykułu) a komentarze – sekcję (mają sensowny tytuł i stanowią spójną całość). Oczywiście można też zrobić inaczej: zarówno tagi, jak i komentarze potraktować jako sekcje i włożyć je w footer. Wypada jednak pamiętać, że definicja stopki sugeruje, że jest ona przeznaczona na zawarcie metadanych:

A footer typically contains information about its section such as who wrote it, links to related documents, copyright data, and the like.

"http://www.w3.org/TR/html5/sections.html#the-footer-element"

Tagi w tym kontekście pasują o wiele bardziej (po prostu opisują dany artykuł jako słowa kluczowe), podczas gdy komentarze już niespecjalnie. Owszem, można je potraktować jako "powiązane dokumenty", jednak są one dośc autonomicznymi tworami i część z nich z powodzeniem mogłaby żyć bez łączności ze swoim "rodzicem". Stąd wydzielenie komentarzy do sekcji i pozostawienie w stopce samych tagów wydaje się bardziej sensownym rozwiązaniem.

Tak to mniej więcej wygląda. Formularz se opuszczę i powrócę do niego później, bo formularze w HTML5 to bardzo ciekawy temat warty więcej niż szybkiego spojrzenia.

Przejdźmy do div#aside. Tworzy on tzw. "boczny pasek" z informacjami luźno związanymi z główną treścią (i tutaj mała dygresja: gdyby chodziło o luźno związane informacje z samym artykułem, mielibyśmy do czynienia z article > aside; w tym wypadku chodzi o całą zawartość main; inna sprawa, że tutaj faktycznie jest to jeden artykuł): autor, tagi, archiwa… Do oznaczania takich rzeczy powstał aside. Oznacza się nim właśnie luźno związane z główną treścią rzeczy, które można zaprezentować samodzielnie (to chyba ulubione słówko w WHATWG).

Idąc dalej, divy z tagami, autorem i archiwami można potraktować jako artykuły. I choć początkowo taka interpretacja specyfikacji wydaje się ciutkę naciągana, to po dogłębniejszym wczytaniu okazuje się (chyba raczej na pewno) właściwa.

This could be a forum post, a magazine or newspaper article, a blog entry, a user-submitted comment, an interactive widget or gadget, or any other independent item of content.

"http://developers.whatwg.org/sections.html#the-article-element"

Najważniejszy jest pogrubiony fragment. Ba, tylko co on znaczy? Idąc za radą doktorów trza pomyśleć czy dany fragment wyciągnięty z kontekstu wciąż ma jakiś sens. Notka o autorze, pozbawiona sąsiedztwa wpisu raczej nie stanie się bełkotem. Lista archiwalnych wpisów również pozostanie listą, tak jak lista tagów listą tagów. Dlatego moim skromnym zdaniem, chociaż na pierwszy rzut oka wydaje się to pewnym nadużyciem, article pasują tutaj idealnie. Rozważania te wspiera opis article, który pojawił się w specyfikacji HTML 5.1, jeszcze bardziej zwracający uwagę na kwestię niezależności danego fragmentu treści:

The article element represents a complete, or self-contained, composition in a document, page, application, or site.

"https://www.w3.org/TR/html51/sections.html#the-article-element"

Szkielet:

Kod:

<aside>
	<article>
		<h3>O autorze</h3>
	</article>
	<article>
		<h3>Tagi</h3>
	</article>
	<article>
		<h3>Archiwum</h3>
	</article>
</aside>

Kolega zwrócił mi uwagę, że tagi i archiwum można potraktować też w inny sposób. Nie da się ukryć, że są to de facto dwie listy odnośników. Dlatego też można je potraktować jako dodatkowe elementy nawigacyjne (otoczyć nav). Moim zdaniem obydwie interpretacje tych elementów są poprawne, a różnica wynika po prostu z innej perspektywy spojrzenia na sprawę. Moja interpretacja wynika z analizy samej natury treści (czy jest ona możliwa do zaprezentowania niezależnie, czy stanowi poboczną informację do głównej treści itd.), natomiast interpretacja kolegi – z analizy wzajemnych relacji i funkcji (czy ta lista odnośników może być potraktowana jako nawigacja, czy prowadzi do innej, powiązanej treści w obrębie witryny itd.). Gdyby ktoś był ciekawy, w specyfikacji HTML5 pojawia się zastosowanie aside > nav właśnie w takim kontekście.

nav nie służy tylko do oznaczania głównego menu strony. Jest znacznikiem do oznaczania elementów nawigacyjnych w ogóle. Jednak nie każda lista odnośników jest elementem nawigacyjnym. Zbiór odnośników do różnych artykułów w Internecie jest po prostu zbiorem odnośników (lub artykułem, w zależności od kontekstu). Natomiast już breadcrumbs czy też kotwice w obrębie jednej strony można potraktować jako element nawigacyjny.

Jeśli używamy na swojej stronie więcej niż jednego nav, powinniśmy zadbać o to, aby każde z nich miało inną nazwę – najlepiej reprezentowaną przez nagłówek, w ostateczności atrybut [aria-label]. Pozwoli to użytkownikom, zwłaszcza korzystającym z czytników ekranowych, na zrozumienie co dany element nawigacyjny im umożliwia (np. czy jest to menu strony, czy spis treści artykułu itd.). Niepisaną zasadą jest także ograniczenie liczby elementów nav do 3–4.

Stopka Bezpośredni link do sekcji

No, to lwia część za nami – została tylko stopka. Tak, ją też zmieniamy. Tym razem div zamienia się w footer. Uff, blog jest już w całości przerobiony na HTML5, ale to nie koniec – to dopiero początek :D

P.S. dla ekstrawaganckich: html, head i body są opcjonalne ;) Jednak nie muszę chyba wspominać, że ich usunięcie może skutkować dziwnym drzewkiem DOM (szczególnie w IE).

Formularze (WebForms 2.0) Bezpośredni link do sekcji

Wyszukiwarka Bezpośredni link do sekcji

W HTML5 pojawia się pełno nowych typów pól i atrybutów formularzy. My zastosujemy raptem ułamek z nich.

Zacznijmy od formularza wyszukiwania. Dla pól wyszukiwania jest przewidziany nowy typ – [type=search]. Choć dzięki temu nasz kod staje się bardziej zrozumiały, to jednak z punktu widzenia użytkownika nie zmienia się absolutnie nic – to pole wciąż zachowuje się jak stare dobre pole tekstowe ([type=text]).

Nowe typy pól Bezpośredni link do sekcji

Oczywiście search to nie jedyny nowy typ pola. Z innych warto wspomnieć:

  • email – dla e-maili
  • url – dla URL-i
  • number – dla liczb
  • date – dla dat
  • color – dla kolorów
  • range – taki fajny slider

Inne bajery i dostępność Bezpośredni link do sekcji

Ale, ale. Można jeszcze bardziej podbajerować dzięki atrybutowi [placeholder]. Robi on to, co tysiące tych badziewnych JS: wyświetla pomocniczy tekst, który znika po kliknięciu w pole (i nie kasuje przy okazji już wprowadzonego zapytania…).

Nie powinien być jednak traktowany jako zastępstwo dla label. Wspomina o tym nawet specyfikacja.

A jeśli już chcesz się nazywać mistrzem formularzy, to dodaj sobie jeszcze atrybut [required], który oznacza, że formularz nie może zostać wysłany jeśli dane pole jest puste. Po przeróbce formularz szukania wygląda następująco:

Kod:

<form action="search.php" method="post">
	<p>
		<label for="search-input">Szukaj:</label>
		<input type="search" id="search-input" name="q" placeholder="Wpisz szukaną frazę…" required>
		<button type="submit" name="submit" value="1">Szukaj</button>
	</p>
</form>

label do pola wyszukiwania można wstawić techniką ukrywania przed graficznymi przeglądarkami, używaną m.in. w HTML5 Boilerplate. Userzy z wizualnymi przeglądarkami nie zobaczą go (a pole wyszukiwania jest na tyle charakterystyczne, że na pewno je rozpoznają), natomiast ci, którzy korzystają z czytników ekranowych nie poczują się zagubieni, gdy natrafią na pole bez etykiety.

PAMIĘTAJ! CSS (jak i obrazki, JS, inne dziwne rzeczy typu Flash, Java, Silverlight) są tylko dodatkami, które nie muszą być dostępne!

Oznacza to, że możesz być pewny tylko tego, że końcowy user zobaczy treść i HTML (patrz: użytkownicy Lynxa). Stąd ważne jest zrozumienie podstaw tworzenia czystego, semantycznego kodu, który – nawet bez CSS – tworzy sensowną i czytelną całość. Dlatego też osobiście wolę tworzyć najpierw HTML dla strony, a dopiero później dorabiać CSS i JS. HTML to kartka papieru, na którą nakładam kolejne warstwy folii (CSS, JS). Podejście to znane jest jako Progressive Enhancement.

Kompatybilność Bezpośredni link do sekcji

Teraz zapewne się zapytasz: a gdzie nowe typy pól formularzy są obsługiwane? Zamiast podawać tak szybko deaktualizujące się informację, odsyłam do odpowiedniego źródła. Brak wsparcia nie oznacza jednak, że trza rezygnować z nowoczesnych formularzy. HTML5 jest pisany z myślą o kompatybilności wstecznej, co znaczy, że jeśli dany typ pola nie jest obsługiwany, pojawi się stare, dobre pole tekstowe. Resztę zachowań – włącznie z walidacją wprowadzonych danych – we wszystkich przeglądarkach można osiągnąć dzięki JS.

Podobnie można przerobić formularz dodawania komentarzy:

Kod:

<form action="https://example.net/comment.php" method="post" id="dodaj-komentarz">
	<h3>Dodaj komentarz</h3>
	<p>
		<label for="comment-author">Nick</label>
		<input type="text" name="author" id="comment-author" required>
	</p>
	<p>
		<label for="comment-email">E-mail</label>
		<input type="email" name="email" id="comment-email" required>
	</p>
	<p>
		<label for="comment-url">Strona</label>
		<input type="url" name="url" id="comment-url">
	</p>
	<p>
		<label for="comment-comment">Komentarz</label>
		<textarea name="comment" id="comment-comment" cols="48" rows="7" required></textarea>
	</p>
	<p>
		<button name="submit" type="submit" id="comment-submit">Wyślij</button>
	</p>
	<input type="hidden" name="comment_post_ID" value="88">
</form>

Tutaj warto wspomnieć o jeszcze jednym nowym atrybucie dla pól formularza: [pattern], który przyjmuje jako wartość wyrażenie regularne, dzięki czemu – jeśli żadne z nowych typów pól formularza nie spełnia naszych wymagań – można wymusić kokretny format danych, np kodu pocztowego:

Kod:

<input type="text" name="zipcode" pattern="\d{2}\-\d{3}">

Naprawdę zachęcam do używania nowych typów formularzy. Jeśli wkrótce wszystkie przeglądarki będą je wspierać, można uprościć walidację danych po stronie serwera (a przynajmniej nie martwić się, że w e-mailu dostajemy JS-a).

Uprościć, nie znaczy zaniechać. Niewalidowanie danych po stronie serwera jest jak wpuszczanie nieznajomego do domu, dając mu do tego klucz do sejfu w sypialni. Sama specyfikacja wspomina, że walidacja po stronie klienta ma jedynie podnosić UX.

[rel] czyli dokąd to prowadzi Bezpośredni link do sekcji

Atrybut [rel] dla linków oznacza ich przeznaczenie, a dokładniej do jakiego zasobu się odnoszą. Warto stosować atrybut [rel] na wszystkich linkach, które mają jakiekolwiek znaczenie semantyczne, np. jeśli link prowadzi do strony o autorze, niech będzie miał odpowiedni [rel]. Jakie [rel] można zatem stosować?

Lista dozwolonych [rel] Bezpośredni link do sekcji

  • index – strona główna
  • author – coś o autorze
  • archive/archives – znany z Wordpressa, prowadzi do archiwum wiadomości. Typ ten niegdyś występował w specyfikacji HTML5, jednak obecnie nie jest nawet typem proponowanym przez Microformats wiki. Niemniej znajduje się w sekcji wykorzystywanych wartości. Osobiście wydaje mi się, że w końcu zostanie przeforsowany, dlatego zostawiam go w kodzie bloga (pomimo, że walidator się rzuca – ale na szczęście to nie nieomylny demiurg)
  • prev – poprzedni wpis
  • next – następny wpis
  • canonical – oryginalny URI do zasobu (czyli ten, który chcemy zaindeksować w Google)
  • nofollow – BlackSEO
  • shortlink – oficjalny, skrócony adres strony
  • tag – do oznaczania tagów

Pamiętaj, że wszystkie [rel] dotyczą aktualnej strony. Tym samym np. niepoprawne jest oznaczenie tagów w chmurce tagów przy pomocy [rel=tag] (gdyż nie odnoszą się one do tej konkretnej strony). Natomiast oznaczenie tak tagów, które występują wewnątrz głównego artykułu (w nagłówku czy stopce) jest już poprawne (bo odnoszą się do treści danej strony).

Rozszerzalność Bezpośredni link do sekcji

Poza tym można tworzyć własne [rel], chociaż większego sensu w tym nie widzę, bo wszystkie potrzebne już istnieją i są na tyle elastyczne, że można je nagiąć do własnych potrzeb. Na szczęście radosne tworzenie jest monitorowane i żeby jakiś [rel] został uznany za poprawny w HTML 5, należy go zgłosić. To samo tyczyło się meta[name], ale uznano ten wymóg za zbędny.

A teraz, drogi blogerze, linki czekają na semantyczne wsparcie! Naprzód!

WAI-ARIA Bezpośredni link do sekcji

Role Bezpośredni link do sekcji

W HTML5 pojawia się nowy atrybut [role], który określa rolę danego elementu na stronie. W przypadku bloga można je rozdzielić przykładowo tak:

  • header (strony) → banner – ogólne informacje o stronie
  • mainmain – główna część strony
  • articlearticle – artykuł, względnie document – dokument
  • article > header, article > footergroup (z tym, że nie wnosi to nic ciekawego tak naprawdę)
  • asidecomplementary – coś uzupełniającego
  • wyszukiwarka → search – nie trza tłumaczyć
  • footer strony → contentinfo – metadane
  • navnavigation – element nawigacyjny

Warto także zauważyć, że dla większości elementów przeglądarki same nadają odpowiednie [role] i dublowanie ich w kodzie jest niezalecane. ARIA przydaje się wówczas, gdy tworzymy pewne struktury od podstaw np. w przypadku wykorzystywania Web Components czy podmienianiu natywnych pól formularza własnymi odpowiednikami.

Ale po co to? Bezpośredni link do sekcji

Dobra, [role] jest jasne, ale co to WAI-ARIA? Otóż WAI to organizacja zajmująca się dostępnością stron internetowych, a ARIA to jej najnowszy standard. ARIA to skrót od Accessible Rich Internet Applications i, jak nazwa wskazuje, powstał po to, by podnieść dostępność tak zaawansowanych aplikacji jak Gmail czy Google Docs. Nic jednak nie szkodzi, aby nasz blog potraktować jak webappa.

Dla tworzących bardziej rozbudowane strony, z wykorzystaniem JS, głównie XHR, mogę polecić jeszcze takie własności jak [aria-live] i [aria-atomic]. Przy ciężkim Ajaksie (czyt. wszystko na History API) wręcz ratują życie.

Przy walidacji formularzy również warto użyć ARIA, zwłaszcza dołączając obok atrybutu [required] atrybut [aria-required] oraz oznaczając niepoprawnie wypełnione pola [aria-invalid].

Po więcej info o WAI-ARIA zapraszam do specyfikacji ARIA in HTML. Natomiast o dostępności najlepiej pisze Heydon Pickering. Po polsku polecam blog Internet bez barier.

Dane semantyczne Bezpośredni link do sekcji

Mikroformaty Bezpośredni link do sekcji

Mikroformaty powstały po to, by w dobie HTML4 niesemantycznym divom nadać semantyczne znaczenie. Mimo że w HTML5 mamy pełno semantycznych znaczników, to jednak mikroformaty wciąż są niezwykle przydatne. Pozwalają nam dokładnie opisać wydarzenia, osoby czy miejsca używając do tego HTML-owego zapisu ogólnie znanych standardów, takich jak np. vcard (format wizytówek, obsługiwany przez większość telefonów komórkowych). Zastosowanie mikroformatów wcale nie jest trudne, wystarczy dodać odpowiednią klasę. Jako przykład zastosuję hCard (odpowiednik vcard) i "oznaczę" boczne info o autorze:

Kod:

<article class="h-card">
	<h3>O autorze blogaska</h3>
	<p>Nazywam się <a href="https://example.net/author" class="p-name u-url">Comandeer</a>, mieszkam w uroczym miasteczku <span class="p-locality">Świętochłowice</span> i interesuję się webmasterką.</p>
</article>

Prawda, że łatwe? W podobny sposób można oznaczać wydarzenia (h-event), przepisy (h-recipe), a także upodobnić HTML do ATOM (h-feed + h-entry).

Microdata Bezpośredni link do sekcji

Microdata (mikrodane) to z kolei nowość w HTML5, która działa podobnie do mikroformatów. Jedyna różnica polega na tym, że korzysta z nowych atrybutów – [itemscope], [itemtype] i [itemprop] oraz z przestrzenii nazw. Najprościej pokazać to na przykładzie:

Kod:

<article itemscope itemtype="http://schema.org/Person">
	<h3>O autorze blogaska</h3>
	<p>Nazywam się <a href="http://example.net/author" itemprop="name url">Comandeer</a>, mieszkam w uroczym miasteczku <span itemprop="address" itemscope itemtype="http://schema.org/PostalAddress"><span itemprop="addressLocality">Świętochłowice</span></span> i interesuję się webmasterką.</p>
</article>

Wygląda i działa bardzo podobnie do mikroformatów (chociaż jest bardziej skomplikowane i – teoretycznie – pozwala odwzorowywać bardziej skomplikowane struktury danych). Co ważne, oba sposoby są znane Google'owi, który korzysta z nich do wyciągania danych ze stron. Korzystanie więc podnosi dostępność treści z poziomu wyszukiwarki.

Google, Yahoo i Bing zaczęły pracować nad nowym standardem oznaczania treści Schema.org, który ma ustandaryzować mikrodane na stronach WWW. Dzięki temu przedsięwzięciu można oznaczyć prawie każdy typ danych. Wydaje mi się, że takie podejście ma szansę wyprzeć mikroformaty, a przynajmniej zmusić je do ewolucji.

Inne formaty danych semantycznych Bezpośredni link do sekcji

Tutaj warto wspomnieć o głównym konkurencie microdata – RDFa – który wygląda dość podobnie, ale jest bardziej XML-friendly. Chociaż obecnie zarówno on, jak i microdata/mikroformaty, są zagrożone przez najnowszy format danych semantycznych, JSON LD. Niemniej ten format, z racji swojej specyfiki, IMO znajdzie zastosowanie głównie w RESTful APIs, jako format zwracanych danych.

Dublin Core Bezpośredni link do sekcji

Dublin Core jest międzynarodowym standardem metadanych (ISO 15836-2003) i służy do opisywania dokumentów. Jest rozwijany i upowszechniany przez organizację Dublin Core Metadata Initiative, mającej na celu stworzenie semantycznej sieci, w której z łatwością można będzie znaleźć dokumenty (pieśń przyszłości). Standard ustala 15 elementów, dzięki którym można dokładniej opisać stronę, lecz nie tylko – praktycznie każdy dokument cyfrowy. Może dzięki temu stanowić zamiennik dla "standardowych" meta. Najczęściej służy jako zamiennik dwóch metatagów: keywords i description. Ich "dublinowe" odpowiedniki to: dcterms.subject i dcterms.description.

Kod:

<meta name="dcterms.description" lang="pl" content="Super hiper wpis na temat czegokolwiek">
<meta name="dcterms.subject" lang="pl" content="Bardzo ważne słowa kluczowe; rozdzielone średnikiem">

Chciałbym tutaj zwrócić uwagę, że warto także podać atrybut [lang] wskazujący na język użyty w metadanych. W końcu to międzynarodowy standard i niekoniecznie opis dokumentu musi być po polsku.

Kilka uwag o dostępności Bezpośredni link do sekcji

Pisząc ten poradnik, skupiałem się głównie na kwestiach semantyki. Skutkiem ubocznym tego jest automatyczne zwiększenie dostępności tak stworzonej strony WWW. Na chwilę obecną nasza strona powinna być już naprawdę dobrze dostosowana dla osób niepełnosprawnych (zwłaszcza po dodaniu kilku rzeczy z opisanego wyżej standardu WAI-ARIA), lecz kilka rzeczy można jeszcze poprawić.

Na początku body warto dodać link odsyłający nas bezpośrednio do main danej strony (przy użyciu opisanych wyżej kotwic):

Kod:

<a href="#tresc" class="focus-only" tabindex="1">Przejdź do treści</a>

Zwiększy to użyteczność dla tych, którzy korzystają z przeglądarek głosowych lub mają zaburzenia psychomotoryczne i są zmuszeni używać jedynie klawiatury. Dla innych ukryjemy to w CSS robiąc np. tak:

Kod:

.focus-only
{
	position:absolute;
	top:-1000px;
	left:-99999px;
}
.focus-only:focus
{
	position:static;
}

Oczywiście link będzie czuły na TAB. Inna metoda (bardziej użyteczna i nie powodująca problemów z wydajnością na urządzeniach mobilnych) to wykorzystanie clip. Stosuje ją m.in. H5BP

Kod:

.focus-only
{
	border: 0;
    clip: rect(0 0 0 0);
    height: 1px;
    margin: -1px;
    overflow: hidden;
    padding: 0;
    position: absolute;
    width: 1px;
    white-space: nowrap;
}
.focus-only:focus
{
	clip: auto;
    height: auto;
    margin: 0;
    overflow: visible;
    position: static;
    width: auto;
    white-space: inherit;
}

Warto także dodać, że niektóre przeglądarki co prawda przeskoczą do odpowiedniego elementu, ale zachowają starą kolejność TAB-owania elementów (czyli będzie TAB-ować menu, które chcieliśmy przeskoczyć) – dlatego dla kontenera z treścią warto dorzucić [tabindex=-1].

Przy okazji warto zauważyć, że bezpośrednia zabawa z atrybutami [tabindex] czy [accesskey] jest średnio przydatna. Narzucony z góry [tabindex] może zrobić więcej szkody niż pożytku i w gruncie rzeczy powinien służyć wyłącznie do uczynienia focusowalnymi tych elementów, które natywnie nie są (czyli de facto winien być używany tylko i wyłącznie w połączeniu z JS i ARIA). Tak samo wydaje mi się, że skróty klawiaturowe lepiej i wygodniej dla użytkownika zrobić jest w JS.

Dla większości elementów sekcjonujących (section, article, nav, aside) warto dodać nagłówki, które – dla piękna – ukryć można przed wizualnymi przeglądarkami podobną techniką, jak ta dla już wspominanego linku .focus-only. Oczywiście nie ma sensu na chamca wtryniać nagłówków dla każdej sekcji – czasami "Untitled section" jest dozwolone. Lepszy jest brak nagłówka niźli bezsensowny nagłówek. Inna rzecz, że jeśli coś nie ma nagłówka, to prawdopodobnie nie jest sekcją. Warto o tym pamiętać, bo nagłówki dla sekcji tworzą swoisty schemat nawigacyjny po stronie, który można wykorzystać do szybkiego przeskakiwania między częściami strony i identyfikowania ich. Tutaj warto jeszcze raz przypomnieć, że każda sekcja powinna mieć odpowiednie [id] – w języku strony. Dzięki temu będzie można linkować do każdej sekcji, co znacząco zwiększa użyteczność strony. Podobna technika jest stosowana w przypadku tego tutorialu, gdzie można zauważyć najczęściej stosowany wzorzec dla tworzenia identyfikatorów: slug z treści nagłówka.

Czasami zdarza się też, że musimy zapewnić jeszcze większy poziom dostępności. Tutaj na pomoc przychodzi nam standard WCAG 2.0, dokładnie opisujący wszelkie aspekty dotyczące dostępności stron WWW. Jest on podzielony na 3 poziomy (A, AA i AAA), określające stopień dostępności (od minimum do sensownego maksimum). Standard ten opisuje naprawdę wszystko, co webmaster powinien wiedzieć o dostępności, stąd można go traktować jako swoistą biblię. Istnieje także oficjalny katechizm.

WCAG powinien znać KAŻDY szanujący się programista sieciowy. Zasady określone w tym standardzie nie są trudne w zastosowaniu (większość sprowadza się do poprawnego użycia HTML-a), a przynoszą spore korzyści w dziedzinie dostępności.

Jeśli przestrzegasz zasad semantyki HTML i nie zapominasz o zasadzie Progressive Enhancement, wówczas prawdopodobnie nie będziesz musiał specjalnie przejmować się kwestiami dostępności strony. Wyjątkiem będą tu kwestie związane z kontrastem, gdyż je bardzo łatwo przeoczyć.

Ostatnie poprawki Bezpośredni link do sekcji

To już prawie koniec! Co jeszcze warto zmienić?

Wydajność i bezpieczeństwo Bezpośredni link do sekcji

  • Zacznijmy od tytułu strony: warto się upewnić, że jest w formacie <Nazwa podstrony> <separator> <Nazwa witryny>, np. Projekty @ Comandeer's Homepage. Ma to duże znaczenie zarówno z punktu widzenia użyteczności (widać od razu, co dana karta przeglądarki zawiera), jak i dostępności (czytnik ekranowy przeczyta najpierw nazwę podstrony, a dopiero potem całą resztę).
  • Wszystkie script (oprócz tego dla IE) warto przerzucić na koniec body (zwiększy to szybkość ładowania strony, bo skrypty w head mogą ją "blokować"). Jeśli mamy bardzo dużo JS, ze złożonymi relacjami pomiędzy poszczególnymi plikami, warto rozważyć architekturę modułową. Czy już wspominałem o atrybucie [defer]?
  • Można się w ogóle pokusić o serwowanie CSS, JS i obrazków z CDN. Jest to jedno z zaleceń Google odnośnie szybkości wczytywania stron: rozłożenie wczytywania na 2 paralelne domeny. Jedna serwuje dynamiczną stronę (czyli PHP i generujemy blogaska), a druga serwuje wszystko, co statyczne. Jednak rozłożenie wczytywania strony to tylko część zalet i bardziej rozbudowane CDN-y korzystają choćby z geolokalizacji, żeby zasysać zasoby z serwera jak najbliżej użytkownika, aby czas wczytywania był jeszcze krótszy. Istnieją także darmowe CDN-y, np. Coral CDN. Bardzo ważnym przeciwskazaniem dla CDN-ów jest fakt, że nie mamy nad nimi kontroli, co sprawia, że de facto uzależniamy swoje bezpieczeństwo od bezpieczeństwa zewnętrznej usługi. Warto mieć to na uwadze.
  • A jeśli już mówimy o bezpieczeństwie zasobów pobieranych z zewnętrznych źródeł, obowiązkową lekturą jest instrukcja użycia Subresource Integrity.
  • Warto też stosować build process, podczas którego będziemy minifikować kod HTML, łączyć i minifikować pliki CSS i JS (być może nawet z przygotowywaniem paczek dla poszczególnych podstron) oraz kompresować obrazki (np. przy pomocy ImageOptim). Bardzo prymitywny przykład takiego rozwiązania można zobaczyć w repozytorium mojej strony domowej.
  • Jak lubimy eksperymentować, to warto przejść całkowicie na HTTPS i protokół HTTP/2. Zwiększy to zarówno bezpieczeństwo, jak i wydajność naszej strony.
  • Jak już jesteśmy przy HTTPS, to warto wspomnieć o HSTS i HPKP.
  • Kontynuując ten temat, jest jeszcze kilka innych pomocnych nagłówków, z czego najwięcej uwagi warto poświęcić Content-Security-Policy, które w swojej najnowszej odsłonie pozwoli nam zabezpieczyć się nawet przed dziurawymi CDN.

Integracja z zewnętrznymi usługami Bezpośredni link do sekcji

  • Warto dodać web app manifest, co pozwoli "uaplikacjowić" się naszemu blogowi. To doskonały wstęp do stworzenia z naszej strony pełnoprawnego Progressive Web Application.
  • Oprócz RSS można dodać także ATOM, bo to o wiele lepszy format i lepiej się z nim pracuje.
  • Dla obrazków w treści artykułu warto stosować ścieżki bezwzględne (te z https:// na początku), bo treść może być udostępniana także przez RSS i ATOM i może pojawić się problem z odnalezieniem właściwego obrazka. Gdy to tylko możliwe, należy wymuszać HTTPS. Zapewnia to większe bezpieczeństwo, a w przyszłości umożliwi korzystanie z HTTP/2.
  • Jeśli masz profil na Google+, rozważ umieszczenie link[rel=author] (jako osoba prywatna) bądź też link[rel=publisher] (jako firma, organizacja, paracyrk…) z [href] ustawionym na adres Twojego profilu. Co prawda Twoje zdjęcie profilowe w wynikach wyszukiwania już się nie pojawi, ale i tak warto taką informację dodać dla innych usług:

    Kod:

    <link rel="author" href="//plus.google.com/108791847143656151689/">
  • Jak już jesteśmy przy społecznościówkach, Facebook też serwuje swoje metatagi a Twtiter nie pozostaje mu dłużny.
  • Warto też serwować ikonkę strony. Najlepiej mieć podstawową – favicon.ico – w głównym folderze witryny. Wtedy, nawet jeśli nie zamieścimy link[rel=icon] w kodzie, przeglądarki sobie ją pobiorą (tak, przeglądarki po prostu na chama szukają ikonki, śląc requesty pod http://naszastrona.pl/favicon.ico). Mając taką podstawową w zapasie, można próbować wcisnąć browserom np coś w PNG właśnie przy pomocy link[rel=icon]. IE < 9 i tak tego nie rozumie, uparcie szukając link[rel=shortcut], zatem ono dostanie ico a reszta ładny PNG (albo nawet animację w GIF). Do tego dochodzą jeszcze np. ikonki dotykowe dla iUrządzeń i inne takie, które też można (a jeśli strona ma być dla mobilnych też – nawet trzeba) zamieścić. Są od tego odpowiednie narzędzia. Uwaga! Generowany kod to prawdziwa kobyła. Tak się to kończy, gdy nie istnieje jeden, powszechny standard.
  • W nowszych Windowsach (7 i 8) można sobie przypiąć stronę i odpalać ją jak zwykłą aplikację (oczywiście w IE). Podobna opcja jest dostępna w Chrome.
  • Chrome na mobilnych urządzeniach pozwala również zmienić kolor paska adresu:

    Kod:

    <meta name="theme-color" content="#db5945">

Kompatybilność Bezpośredni link do sekcji

  • Warto używać media-queries, aby strona sama się dostosowywała do urządzenia użytkownika (nurt responsive webdesign). Opłaca się, bo Google lubi strony mobile friendly (a mój telefon to popiera!).
  • Dla IE wypada słać nagłówek X-UA-Compatible ustawiony na IE=edge. Wymusza to renderowanie strony przy pomocy najnowszych standardów w IE >= 8. Kiedyś można nyło słać ten nagłówek z wartością IE=edge; chrome=1, co wymuszało użycie Chrome Frame. Ten jednak już odszedł na emeryturę… Googlersi to jednak skrajni idealiści. Jeśli nie lubisz wciskać pluginów userowi, zawsze możesz naprawdę kulturalnie poinformować.
  • Na końcu warto poświęcić chwilkę i przetestować stronę, poczynając od Validatora, przechodząc do testu dostępności a na teście szybkości kończąc. Sprawdzenie strony na kilku różnych urządzeniach lub BrowserStack/Sauce Labs też jest dobrym pomysłem.
  • A już na naprawdę samym końcu naprawdę zachęcam, aby odpalić JAWS-a, NVDA, VoiceOver lub jakiś inny czytnik ekranowy (chociaż bardziej bym ufał tej trójce, w kolejności wymieniania) i posłuchać swojej strony. Bo może się okazać, że nie za bardzo jest czego słuchać…

Więcej grzechów nie pamiętam.

Nasz blog Bezpośredni link do sekcji

Oto i pełny przerobiony kod z paroma dodatkami:

Kod:

<<!DOCTYPE html>
	<html lang="pl" dir="ltr" itemscope itemtype="http://schema.org/Blog">
		<head>
			<meta charset="UTF-8">

			<meta itemprop="url" content="https://example.net/Super-hiper-wazny-wpis">
			<meta name="description" content="Super hiper wpis na temat czegokolwiek">
			<meta name="dcterms.description" lang="pl" content="Super hiper wpis na temat czegokolwiek">
			<meta name="keywords" content="Bardzo ważne słowa kluczowe">
			<meta name="dcterms.subject" lang="pl" content="Bardzo ważne słowa kluczowe; rozdzielone średnikiem">
			<meta name="application-name" content="Super hiper blog">
			<meta name="msapplication-tooltip" content="Niesamowity blog o niesamowitych sprawach">
			<meta name="msapplication-starturl" content="http://example.net">
			<meta name="msapplication-window" content="width=1024;height=768">
			<meta property="og:site_name" content="Example.net - fajowy blog, na którym bloguję">
			<meta property="og:url" content="https://example.net">
			<meta property="og:title" content="Super hiper ważny wpis | Example.net - fajowy blog, na którym bloguję">
			<meta property="og:image" content="https://example.net/images/favicon.png">

			<link rel="author" href="https://plus.google.com/108791847143656151689/">
			<link rel="alternate" type="application/rss+xml" title="Wpisy na RSS" href="http://example.net/feed">
			<link rel="alternate" type="application/atom+xml" title="Wpisy na ATOM" href="http://example.net/atom">
			<link rel="index" title="Strona główna" href="https://example.net">
			<link rel="prev" title="Jakiś hiper poprzedni wpis" href="https://example.net/Jakis-hiper-poprzedni-wpis">
			<link rel="next" title="Jakiś super następny wpis" href="https://example.net/Jakis-super-nastepny-wpis">
			<link rel="canonical" href="https://example.net/Super-hiper-wazny-wpis">
			<link rel="pingback" href="https://example.net/xmlrpc.php">
			<link rel="icon" href="https://example.net/images/favicon.png" type="image/png">
			<link rel="apple-touch-icon" href="https://example.net/images/apple-touch-icon.png">
			<link rel="stylesheet" href="https://example.net/css/style.css">

			<title itemprop="name">Super hiper ważny wpis | Example.net - fajowy blog, na którym bloguję</title>

			<!--[if lt IE 9]>
				<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
			<![endif]-->
		</head>
		<body>
			<a href="#tresc" class="focus-only">Przejdź do treści</a>

			<header id="naglowek">
				<h1><a href="https://example.net" rel="index">Example.net - fajowy blog, na którym bloguję</a></h1>
				<p>Motto</p>
				<nav id="menu" itemscope itemtype="http://schema.org/SiteNavigationElement">
					<h2 class="visuallyhidden">Menu główne</h2>
					<ul>
						<li><a href="whatever.html">Whatever</a></li>
						<li><a href="wherever.html">Wherever</a></li>
						<li><a href="whenever.html">Whenever</a></li>
					</ul>
				</nav>
				<form action="search.php" method="post" role="search">
					<p>
						<label class="visuallyhidden" for="search-input">Szukaj:</label>
						<input type="search" id="search-input" name="q" placeholder="Wpisz szukaną frazę…" required aria-required="true">
						<button type="submit" name="submit" value="1">Szukaj</button>
					</p>
				</form>
			</header>

			<main id="tresc" class="hfeed" itemprop="mainEntityOfPage" tabindex="-1">
				<article class="post h-entry" itemprop="blogPost" itemscope itemtype="http://schema.org/BlogPosting" id="super-hiper-wazny-wpis">
					<header>
						<h2 class="p-name" itemprop="headline"><a href="https://example.net/Super-hiper-wazny-wpis" class="bookmark u-uid u-url" rel="bookmark" title="Permalink do Super hiper ważny wpis">Super hiper ważny wpis</a></h2>
						<p class="post-info">Opublikowano <time datetime="2011-01-07T20:40:06+00:00" class="dt-published" itemprop="datePublished">07.01.2011</time> przez <a href="https://example.net/author" itemprop="author" itemscope itemtype="http://schema.org/Person" rel="author" class="author p-author h-card"><span itemprop="name">Comandeer</span></a></p>
					</header>
					<div class="e-content" itemprop="articleBody">
						<figure itemprop="image">
							<picture>
								<source media="(min-width: 45em)" srcset="large-1.jpg 1x, large-2.jpg 2x">
								<source media="(min-width: 18em)" srcset="med-1.jpg 1x, med-2.jpg 2x">
								<source srcset="small-1.jpg 1x, small-2.jpg 2x">
								<img src="small-1.jpg" alt="Kwadratowa ramka z czerwonym krzyżykiem w środku">
							</picture>
							<figcaption>Bardzo ważny obrazek[…],który jest bardzo ważny</figcaption>
						</figure>
						<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin eu justo enim, ac faucibus massa. Vestibulum in elit aliquam purus sollicitudin adipiscing ac et sapien. Curabitur eleifend justo diam, et viverra nisi. Quisque a ipsum vehicula nunc vestibulum posuere. Suspendisse potenti. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vestibulum porttitor, neque eu congue fermentum, velit ante pellentesque arcu, a posuere risus tortor vel ante. Donec et neque at odio hendrerit mattis sed eu tellus. Nullam accumsan leo ut felis suscipit vehicula posuere erat eleifend. Donec semper lorem eu nibh tincidunt varius.</p>
						<h3 id="podtytul">Podtytuł</h3>
						<p>Vivamus leo arcu, convallis id iaculis sit amet, fringilla et nunc. Donec aliquam, justo at mollis porta, enim lorem tempor eros, id iaculis arcu elit ac sem. In et erat eu metus ornare vestibulum non at arcu. Integer in nisi massa. Etiam nulla felis, rhoncus non pharetra sed, vehicula eu risus. Vestibulum sodales nunc nisi, vitae gravida nisl. Quisque lacus ipsum, commodo ac hendrerit vitae, porta dapibus tortor. Mauris sed risus diam. Morbi lacus elit, euismod dapibus interdum id, fermentum et mi. Nam at neque orci. Sed ac hendrerit augue. Vestibulum pharetra mattis mattis. Sed porta turpis dolor, condimentum blandit libero. Aliquam non nisi mi. Nulla nec sem elit. Duis blandit viverra lacus, in convallis mauris dictum et. Ut eget risus enim. Suspendisse potenti. Aenean leo odio, luctus quis eleifend quis, consectetur sit amet ipsum. Curabitur commodo leo ac risus dignissim at porttitor turpis fringilla.</p>
						<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ullamcorper neque a magna sodales sodales. Nulla id enim sem, sit amet ultrices dolor. Vestibulum sollicitudin dolor quis quam vehicula egestas. Ut urna erat, gravida a tristique non, congue nec elit. Aenean tincidunt purus sed nisl semper sagittis. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Vivamus in orci sit amet ligula posuere mollis a in diam. Nam enim tortor, ultrices quis laoreet nec, egestas non leo. Nam non fringilla turpis. Quisque vitae pellentesque nibh. Etiam dictum tincidunt ultricies. Cras sit amet aliquam odio. Morbi quis urna a nulla egestas placerat sed in lacus. Morbi id urna lacinia nunc bibendum ultricies. In pretium leo non odio feugiat porttitor. Donec aliquet purus in purus pretium aliquam. Etiam aliquet nibh ut nibh semper egestas. Cras in purus quam, nec posuere diam. Aliquam erat volutpat.</p>
						<p>Morbi porta blandit nisi at fermentum. Praesent vel sagittis urna. Pellentesque ipsum eros, vestibulum id gravida vitae, dictum vel sapien. Nam placerat lacus non lacus facilisis vitae hendrerit nibh adipiscing. Sed aliquet nisi ligula, eu viverra turpis. Curabitur tincidunt arcu in enim tempus sit amet auctor nunc luctus. Praesent dui turpis, lobortis in euismod quis, fringilla at felis. Nullam ligula purus, mattis nec tristique non, aliquam vitae sem. Quisque sit amet magna magna, eget aliquam orci. Aliquam placerat diam sit amet erat gravida fermentum. Maecenas malesuada nibh quis lorem pellentesque laoreet. Vestibulum pulvinar tincidunt fringilla. Nullam pellentesque felis ac nisi dictum egestas. Nunc metus mi, euismod non convallis nec, varius et felis. Pellentesque vel lacus turpis. In hac habitasse platea dictumst. Morbi sodales mauris a nisi feugiat pulvinar.</p>
						<p>Vivamus vitae lectus ut dui luctus iaculis. Pellentesque quis lectus id ipsum venenatis bibendum. Pellentesque non magna nec purus mollis suscipit. Nulla vestibulum interdum ante, vestibulum ullamcorper est vulputate vitae. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Quisque aliquet mollis rhoncus. Phasellus imperdiet posuere bibendum. Quisque consequat imperdiet nibh vitae pretium. Suspendisse quis eros libero, non luctus mauris. Nulla laoreet nibh at eros scelerisque condimentum. Cras aliquam velit at orci luctus et tincidunt arcu scelerisque. Donec at quam magna. Integer leo leo, ultrices facilisis bibendum vel, feugiat interdum neque. Fusce vitae nibh sapien, sit amet consequat velit. Fusce adipiscing tortor id nibh fringilla sollicitudin. Donec sodales sapien in sapien rutrum rutrum. Nam quis enim nec nibh varius mattis nec in ante. Morbi non est eu diam elementum interdum. Morbi at odio non libero tempus eleifend nec quis ligula. Cras pellentesque mauris sit amet felis vestibulum tincidunt.</p>
					</div>
					<footer>
						<section id="tagi" class="tags" itemprop="articleSection">
							<h3>Tagi</h3>
								<ul>
									<li><a href="https://example.net/tag/Tag1" rel="tag" class="p-category">Tag1</a></li>
									<li><a href="https://example.net/tag/Tag2" rel="tag" class="p-category">Tag2</a></li>
								</ul>
						</section>
					</footer>

					<section id="komentarze" class="comments">
						<h3>Komentarze</h3>
							<article id="comment-25" itemprop="comment" itemscope itemtype="http://schema.org/Comment">
								<header class="comment-meta">
									<a href="#comment-25"><time datetime="2011-01-07T20:41:06+00:00" itemprop="dateCreated">07.01.2011, 20:41</time></a>
									<h4><b itemprop="author" itemscope itemtype="http://schema.org/Person"><a href="http://example.net/" itemprop="name url"><img alt="" src="http://avatary.gdziekolwiek.com/Comandeer" height="48" width="48" itemprop="image">Comandeer</a> skomentował</b></h4>
								</header>
									<p itemprop="text">Ale komentarz!</p>
							</article>
							<article id="comment-26" itemprop="comment" itemscope itemtype="http://schema.org/Comment">
								<header class="comment-meta">
									<a href="#comment-26"><time datetime="2017-01-08T20:08:30+01:00" itemprop="dateCreated">07.01.2017, 20:08</time></a>
									<h4><b itemprop="author" itemscope itemtype="http://schema.org/Person"><a href="http://example.net/" itemprop="name url"><img alt="" src="http://example.net/avatary/Anonim" height="48" width="48" itemprop="image">Anonim</a> skomentował</b></h4>
								</header>
									<p itemprop="text">Inny komentarz!</p>
							</article>

						<form action="https://example.net/comment.php" method="post" id="dodaj-komentarz">
							<h3>Dodaj komentarz</h3>
								<p>
									<label for="comment-author">Nick</label>
									<input type="text" name="author" id="comment-author" required aria-required="true">
								</p>
								<p>
									<label for="comment-email">E-mail</label>
									<input type="email" name="email" id="comment-email" required aria-required="true">
								</p>
								<p>
									<label for="comment-url">Strona</label>
									<input type="url" name="url" id="comment-url">
								</p>
								<p>
									<label for="comment-comment">Komentarz</label>
									<textarea name="comment" id="comment-comment" cols="48" rows="7" required aria-required="true"></textarea>
								</p>
								<p>
									<button name="submit" type="submit" id="comment-submit">Wyślij</button>
								</p>
								<input type="hidden" name="comment_post_ID" value="88">
						</form>
					</section>
				</article>
			</main>

			<aside id="aside">
				<h2>Dodatkowe informacje</h2>
				<article class="author h-card" itemscope itemtype="http://schema.org/Person">
					<h3>O autorze blogaska</h3>
					<p>Nazywam się <a href="https://example.net/author" class="fn p-name u-url" itemprop="name url">Comandeer</a>, mieszkam w uroczym miasteczku <span class="adr p-locality" itemprop="address" itemscope itemtype="http://schema.org/PostalAddress"><span itemprop="addressLocality">Świętochłowice</span></span> i interesuję się webmasterką.</p>
				</article>
				<article class="tags cloud">
					<h3>Tagi</h3>
					<ul>
						<li><a href="https://example.net/tag/Tag1">Tag1</a></li>
						<li><a href="https://example.net/tag/Tag2">Tag2</a></li>
						<li><a href="https://example.net/tag/Tag3">Tag3</a></li>
						<li><a href="https://example.net/tag/Tag2">Tag4</a></li>
					</ul>
				</article>
				<article class="archive">
					<h3>Archiwum</h3>
					<ol>
						<li><a href="https://example.net/archiwum/2011/01" rel="archives">Styczeń 2011</a></li>
						<li><a href="https://example.net/archiwum/2010/12" rel="archives">Grudzień 2010</a></li>
					</ol>
				</article>
			</aside>

			<footer id="stopka">Copyright © 2016 by <a href="https://example.net/author" rel="author">Comandeer</a></footer>

			<script src="https://example.net/jquery.js"></script>
			<script src="https://example.net/scripty.js"></script>
		</body>
	</html>

Przydatne linki Bezpośredni link do sekcji

Standardy i oficjalne materiały Bezpośredni link do sekcji

Poradniki Bezpośredni link do sekcji

Narzędzia Bezpośredni link do sekcji

Poprawki i takie tam Bezpośredni link do sekcji

changelog
  • 08.01.2017 – przeredagowanie; dodanie informacji o script[type=module]; dodanie informacji o bibliotekach has.js i polyfill.io oraz teście cut the mustard; dodanie informacji o alternatywach dla HTML5 shiv oraz komentarzach warunkowych; dodanie informacji o dwóch standardach HTML; usunięcie odwołań do opisu hierarchii nagłówków opartej na sekcjach; dodanie informacji o [id] nagłówków/sekcji; dodanie informacji o dostępności nav; zmiana kodu formularza; aktualizacja informacji o ARIA, meta[name] i mikroformatach; dodanie informacji o czytnikach ekranowych; dodanie informacji o wzorcowym formacie tytułu strony; dodanie linków do kilku narzędzi i czytników ekranowych; aktualizacja informacji o HTML5 Shiv; dodanie informacji o SRI
  • 21.11.2016 – dodanie linków do dwóch oficjalnych walidatorów
  • 24.10.2016 – aktualizacja finalnego kodu
  • 23.07.2016 – dodanie info o HTML 5.1 jako CR + dodanie linku do najnowszej wersji specki HTML 5.x; zmiana przykładu perfekcyjnego bloga
  • 28.05.2016 – poprawienie linków do sekcji o [alt] i picture w specyfikacji HTML 5.1
  • 17.04.2016 – dodanie informacji o aktualizacji algorytmu outline'u w specyfikacji HTML5
  • 09.04.2016 – dodanie linku do algorytmu wyszukiwania deklaracji kodowania w `meta` oraz linku do opisu `X-UA-Compatible` w H5BP
  • 16.03.2016 – dopisanie krótkiego wyjaśnienia w fragmencie o main zachowującym się jak div
  • 16.02.2016 – poprawienie linków o [alt]; odwrócenie changeloga; poprawienie notki o figure
  • 03.02.2016 – lekkie uszczegółowienie opisu figure; przebudowa i aktualizacja sekcji "Ostatnie poprawki"; dopisanie kilku informacji o bezpieczeństwie; utworzenie sekcji o dostępności; przebudowa i aktualizacja sekcji z linkami; uaktualnienie stopki bloga
  • 11.12.2015 – uaktualnienie obrazków z outlinem blogów; dodanie notki o możliwości testowania outline w walidatorze; dodanie linka do walidatora
  • 26.11.2015 – mała poprawka we fragmencie o adresach zasobów na stronie
  • 31.07.2015 – wyjęcie komentarzy poza stopkę artykułu
  • 04.06.2015 – opisanie komentarzy, informacja o relative protocol, uzupełnienie informacji o figure, poprawienie wykorzystania [rel=tag], notka przy [rel] o ich połączeniu z konkretną stroną oraz uaktualnienie kodu bloga
  • 26.04.2015 – podział tutorialu na mniejsze partie (zwłaszcza część poświęconą HTML5)
  • 23.04.2015 – krótka notka na temat wystrzegania się niepotrzebnego stosowania ARIA; poprawiony kod bloga
  • 09.03.2015 – ulepszenie skip linków, uaktualnienie informacji o atrybutach [rel], poprawienie kodu picture oraz krótki dopisek o formacie JSON LD
  • 19.11.2014 – poprawienie zapisu atrybutów, dodanie linku do CanIUse.com i aktualizacja informacji o tagu picture
  • 05.11.2014 – kilka poprawek związanych głównie z ARIA
  • 18.08.2014 – dodanie linku do artykułu o favicons
  • 04.08.2014 – poprawnie kodu formularzu (wywalenie [tabindex] i wyjęcie przycisku poza dl)
  • 13.07.2014 – dodanie kilku informacji o ARIA, faviconach oraz przeredagowanie kilku fragmentów; rozróżnienie między nav a menu
  • 16.04.2014 – uwaga początkowa + podlinkowanie książki Ferrante i Kursu HTML + uwagi o [alt]; pewna zmiana w stosunku do [tabindex] i [accesskey]
  • 10.04.2014 – dodanie kilku linków, aktualizacja fragmentu o picture, dodanie części o podstawowych stylach i porady o testowaniu strony
  • 21.11.2013 – dodanie fragmentu o [pattern] i kilka dodatkowych uwag na temat aside
  • 20.11.2013 – zmiana sposobu generowania tutorialu (kod powinien być czystszy), zmiana kodu artykułu (głównie section, footer), wyjaśnienie wątpliwości z cite, aktualności związane z responsywnymi obrazkami oraz nagłówkami
  • 20.09.2013 – dodałem nagłówki w kilku miejscach ostatecznego kodu bloga oraz usunąłem z niego hgroup
  • 10.03.2013 – oddanie sprawiedliwości tagowi main, dodanie kilku linków, troszkę poprawek
  • 10.01.2013 – dodano kilka linków, dopisano kilka informacji (m.in. o OpenGraph wspomniano)
  • 06.01.2013 – gryzło mnie sumienie o label na wyszukiwarce. Toteż dopisałem, opisałem i przesadziłem ;) również dodałem/zmieniłem/poprawiłem kilka linków i doaktualizowałem pewne informacje. No i przekroczyłem limit znaków ;) kod HTML początkowy i końcowy walnięte na serwer :P
  • 29.12.2012 – dopisek o elemencie main
  • 28.11.2012 – małe poprawki w kilku miejscach, dodanie kilku linków
  • 17.09.2012 – pojawił się akapicik o responsive images, zmiany w linkach
  • 25.07.2012 – kilka poprawek wymuszonych zmianami w specyfikacji i trochę więcej o Schema.org + kilka takich tam uwag o różnych elementach
  • 20.10.2011 – poprawiłem kilka linków i literówek, lepiej sformatowałem tekst, uzupełniłem informację o mikrodanych, mała zmiana w markupie artykułu
  • 09.01.2011 – pierwsza wersja

Komentarze

comments powered by Disqus