<h3>Tryby pracy przeglądarek</h3>

<p>
Przeglądarki internetowe posiadają dwa tryby pracy:
tryb <em>quirks mode</em> oraz tryb <em>strict mode</em>.
Terminy te są tłumaczone w interfejsie przeglądarki <span class="program">Firefox</span> jako
<em>tryb standardów</em> oraz <em>tryb wstecznej zgodności</em>.
Można powiedzieć, że tryb <em>quirks mode</em> jest przeznaczony do interpretacji
starych witryn niezgodnych ze standardami, zaś tryb <em>strict mode</em> &mdash;
do interpretacji witryn przestrzegających standardów W3C.
Różnice interpretacji witryn WWW w obu trybach
dotyczą wyłącznie arkuszy stylów CSS.
</p>

<p>
Oba tryby są konieczne i występują we wszystkich przeglądarkach.
Obecność trybu <em>quirks mode</em> jest wymuszona
przez ogromną ilość stron WWW, które
były przygotowane w czasach, gdy standardy sieciowe
dopiero powstawały. Witryny takie:
</p>

<ul>
<li>nie stosują CSS w ogóle lub w bardzo ograniczonym stopniu,</li>
<li>arkusze stylów są często niezgodne ze specyfikacją CSS
i opierają się na rozwiązaniach, które wystąpiły w jakiejś archaicznej już dzisiaj przeglądarce,</li>
<li>nie zawierają deklaracji <span class="variable">DOCTYPE</span>
(lub zawierają jedną z postaci HTML 4 Transitional),</li>
<li>stosują tabele do układu strony,</li>
<li>stosują różne przestarzałe znaczniki (na czele z <span class="variable">font</span> i
<span class="variable">center</span>).</li>
</ul>

<p>
Dla przeglądarki nie pozwalającej na odwiedzanie witryn
niezgodnych ze standardami
niedostępna byłaby większa część internetu.
Takie oprogramowanie byłoby bezużyteczne.
</p>

<p>
Z drugiej strony tryb <em>strict mode</em> przeglądarek jest odbiciem
powolnej ewolucji sieci WWW w kierunku przestrzegania standardów.
Wykonanie witryny zgodnej ze standardami i
całkowite przystosowanie jej do
trybu <em>quirks mode</em> zupełnie mijałoby się z celem.
</p>

<p>
Najprawdopodobniej liczba witryn zgodnych ze standardami będzie
w ciągu najbliższych lat rosła.
Czy jednak w przyszłości nastąpi całkowite przejście na tryb <em>strict mode</em>
(do tego stopnia, że tryb <em>quirks mode</em> zniknie z przeglądarek)?
Z racji na ilość witryn, jakie należy poddać aktualizacji,
raczej nie jest to perspektywa najbliższych kilku lat.
Chociaż należy zauważyć, że główny czynnik wstrzymujący przejście
na tryb <em>strict mode</em> przestaje mieć znaczenie.
Czynnikiem tym jest procent przeglądarek wymagających
przystosowania witryn do <em>quirks mode</em>.
Według najnowszych badań dostępnych na witrynie
<a href="http://www.ranking.pl">http://www.ranking.pl</a>
przeglądarki wspierające <em>strict mode</em>
stanowią 92,1%
(<span class="program">MSIE 6.x</span>,
<span class="program">Firefox 1.x</span>,
<span class="program">Opera 9.x</span>).
</p>

<p>
Dodam jeszcze, że w obydwu tych trybach przeglądarka
ignoruje wszelkie błędy HTML oraz CSS.
Praca w trybie <em>strict mode</em> nie oznacza, że przeglądarka informuje o błędach.
Różnica pracy w obu trybach polega na tym, że
w trybie <em>strict mode</em> interpretacja CSS będzie (lub być powinna) zgodna z
ustaleniami zawartymi w specyfikacjach dostępnych na stronie W3C.
Natomiast w trybie <em>quirks mode</em> wystąpi wiele różnic,
których istnienie ma podłoże historyczne.
</p>

<h3>Przykładowe różnice w interpretacji CSS w trybach <em>quirks mode</em> oraz <em>strict mode</em></h3>

<p>
Przykładowe różnice w interpretacji stylów CSS to:
</p>

<ul>
<li>wyznaczanie szerokości pudełka,</li>
<li>centrowanie elementów blokowych,</li>
<li>wyświetlanie obrazów.</li>
</ul>

<p>
Pierwszy problem polega na tym, że wpis:
</p>

<pre>
div {
    width  : 100px;
    margin : 20px;
}
</pre>

<p>
będzie błędnie interpretowany przez <span class="program">IE5</span> oraz
<span class="program">IE6</span> (ale tylko w trybie <em>quirks mode</em>).
<span class="program">IE5</span> ustali faktyczną szerokość elementu na 100, podczas gdy prawidłowa wartość
powinna wynosić 140 (100 + lewy margines 20 + prawy margines 20).
</p>

<p>
Drugi problem polega na tym, że
wyśrodkowanie elementu blokowego wykonywane prawidłowo:
</p>

<pre>
margin : 0 auto;
</pre>

<p>
nie zadziała w <span class="program">IE5</span>. W przeglądarce tej należy użyć atrybutu:
</p>

<pre>
text-align : center;
</pre>

<p>
Wreszcie trzeci problem, wyświetlanie obrazków, dotyczy
wielu przeglądarek, nie tylko <span class="program">IE</span>.
Element <span class="variable">img</span>, który pierwotnie był elementem blokowym,
po wprowadzeniu stylów CSS został przemianowany na element tekstowy.
Pod obrazkami pojawiła się kilkupikselowa pozioma przerwa.
Wynika to z tego, że wysokość elementów tekstowych
jest tak dobrana, by w linii zmieściły się litery takie jak j, p,
czy g sięgające poniżej linii centralnej tekstu.
Problem ten rozwiążemy zmieniając typ elementu <span class="variable">img</span>:
</p>

<pre>
img {
    display : block;
}
</pre>

<p>
lub wysokość linii elementu blokowego, w którym obraz został umieszczony:
</p>

<pre>
line-height : 0;
</pre>

<h3>Problemy z trybami pracy</h3>

<p>
Głównym zmartwieniem jest to, że ta sama witryna może wyglądać inaczej
w tej samej przeglądarce. Nie mówię tutaj o zmianie wersji przeglądarki.
O tym wiemy wszyscy, że przy przejściu z numeru <span class="program">IE5</span> do
<span class="program">IE6</span> należy spodziewać się różnic.
Mówię o tym, że ta sama witryna
może inaczej wyglądać wyświetlana w trybie <em>strict mode</em>
w <span class="program">IE6</span>
oraz w trybie <em>quirks mode</em> w <span class="program">IE6</span>.
</p>

<p>
Czyli do całego galimatiasu przeglądarkowego należy doliczyć jeszcze jeden czynnik:
tryb pracy. Czynnikami, które mogą wpływać na wygląd witryny są więc:
</p>

<ul>
<li>rodzaj przeglądarki (np. <span class="program">IE</span>/<span class="program">FF</span>/<span class="program">Netscape</span>/<span class="program">Opera</span>)</li>
<li>wersja przeglądarki (np. <span class="program">IE5</span>, <span class="program">IE6</span> lub <span class="program">Netscape</span> 4.75, <span class="program">Netscape</span> 8),</li>
<li>tryb pracy przeglądarki: <em>strict mode</em> lub <em>quirks mode</em>.</li>
</ul>

<p>
Czy zdarzyło Ci się kiedyś deja-vu: strona, która przed sekundą wyglądała poprawnie,
bez wprowadzania jakichkolwiek zmian w stylach czy w kodzie HTML nagle się rozjechała?
Ja z tym problemem spotkałem się już kilkukrotnie,
za każdym razem kosztowało mnie to wiele dodatkowej pracy.
Plik CSS &mdash; bez zmian. Plik HTML &mdash; prawie bez zmian.
A układ rozjeżdża się.
</p>

<p>
Winny był właśnie tryb pracy przeglądarki.
Witryna, która poprawnie wygląda w trybie <em>strict mode</em> może
rozjeżdżać się w trybie <em>quirks mode</em>. I na odwrót.
Zatem badając wygląd witryny, trzeba mieć na uwadze tryb pracy przeglądarki.
</p>

<h3>Jak stwierdzić tryb pracy przeglądarki?</h3>

<p>
Tryb pracy przeglądarki możemy stwierdzić wykorzystując skrypt JavaScript.
Jeśli w dokumencie HTML umieścisz kod:
</p>

<pre>
&lt;script type=&quot;text/javascript&quot;&gt;
    alert(document.compatMode);
&lt;/script&gt;
</pre>

<p>
to ujrzysz komunikat informujący o trybie pracy przeglądarki podczas interpretacji
tego konkretnego dokumentu.
Komunikat <span class="variable">CSS1Compat</span> oznacza, że dokument jest interpretowany w trybie standardów
(<em>strict mode</em>).
Natomiast komunikat <span class="variable">BackCompat</span>
oznacza, że przeglądarka działa w trybie wstecznej zgodności (<em>quirks mode</em>).
</p>

<p>
Rozwiązanie takie zadziała w przeglądarkach:
</p>

<ul>
<li><span class="program">Firefox</span></li>
<li><span class="program">Internet Explorer 6</span></li>
<li><span class="program">Opera</span></li>
<li><span class="program">Netscape</span></li>
</ul>

<p>
natomiast nie zadziała w <span class="program">IE5</span>.
</p>

<p>
Dodatkowo, korzystając z <span class="program">Firefoxa</span> możesz posłużyć się
oknem dialogowym
<span class="option">Narzędzia &rarr; Informacje o stronie</span>.
Rysunek 1 przedstawia informacje o witrynie interpretowanej w trybie
<em>strict mode</em> (Tryb standardów).
Natomiast rysunek 2 przedstawia informacje o witrynie interpretowanej w trybie
<em>quirks mode</em> (Tryb wstecznej zgodności).
</p>

#####{$figures[1]}#####

#####{$figures[2]}#####

<p>
Zaletą tego rozwiązania jest fakt, że nie musisz wprowadzać
jakichkolwiek zmian w kodzie HTML. Dzięki temu, możesz zbadać tryb
wyświetlania dowolnej witryny w internecie
(a nie tylko stron tworzonych przez Ciebie).
</p>

<h3>W jaki sposób przeglądarka wybiera tryb pracy?</h3>

<p>
Do tego służy element <span class="variable">DOCTYPE</span>.
Technika taka jest nazywana w terminologii anglojęzycznej <em>doctype switching</em>
lub <em>doctype sniffing</em>.
Brak elementu <span class="variable">DOCTYPE</span> wymusza tryb <em>quirks mode</em>.
Jeśli zatem przyzwyczaiłeś się do pomijania <span class="variable">DOCTYPE</span>,
to pora zmienić nawyki.
Pomijając <span class="variable">DOCTYPE</span> tworzysz witryny,
które są interpretowane w trybie <em>quirks mode</em>, a co za tym idzie wszelkie
rozwiązania HTML/CSS będziesz musiał ponownie zweryfikować w trybie
standardów.
</p>

<p>
W zależności od stosowanego elementu <span class="variable">DOCTYPE</span>
różne przeglądarki mogą pracować w różnych trybach.
Najprostszą regułą jest:
</p>

<ul>
<li>brak elementu <span class="variable">DOCTYPE</span> włącza tryb <em>quirks mode</em></li>
<li>element <span class="variable">DOCTYPE</span> języka XHTML 1.0 strict włącza tryb <em>strict mode</em></li>
</ul>

<p>
Oto pełna postać elementu DOCTYPE języka XHTML 1.0 strict:
</p>

<pre>
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot;
    &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;
</pre>

<p>
Bardziej skomplikowane reguły
przełączania trybów różnych przeglądarek znajdziesz pod adresem
<a href="http://hsivonen.iki.fi/doctype/">http://hsivonen.iki.fi/doctype/</a>.
Co ciekawe, nowe, nieznane elementy <span class="variable">DOCTYPE</span> włączają tryb zgodności ze standardami.
</p>

<p>
Pamiętaj, że wybór trybu pracy przeglądarki dotyczy wyłącznie dokumentów
opatrzonych nagłówkiem <span class="variable">Content-Type: text/html</span>.
Dokumenty o nagłówku <span class="variable">Content-Type: application/xhtml+xml</span> są zawsze
interpretowane w trybie standardów.
</p>

<h3>Problemy z <span class="program">IE</span></h3>

<p>
Przeglądarka <span class="program">Internet Explorer</span> wymaga, by element DOCTYPE był pierwszym elementem
na stronie WWW.
Jeśli przed DOCTYPE umieścisz jakikolwiek komentarz HTML:
</p>

<pre>
&lt;!--  opis strony  --&gt;
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot;
    &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;
...
</pre>

<p>
lub znacznik XML:
</p>

<pre>
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot;
    &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;
...
</pre>

<p>
to <span class="program">Internet Explorer</span> będzie pracował
w trybie <em>quirks mode</em>.
Musisz zatem pilnować, by przed <span class="variable">DOCTYPE</span> nie umieszczać żadnych
wpisów (przynajmniej w wersji wysyłanej do <span class="program">IE</span>).
</p>

<h3>Problemy z różnicami <span class="program">IE5</span>/<span class="program">IE6</span></h3>

<p>
Problemy z przeglądarką <span class="program">IE</span> nie kończą się na
zagadnieniach opisanych w poprzednim punkcie.
Znacznie poważniejszym problemem jest wspomniany
błąd w interpretacji szerokości pudełka.
Opis tego problemu znajdziesz pod adresem
<a href="http://en.wikipedia.org/wiki/internet_explorer_box_model_bug">http://en.wikipedia.org/wiki/Internet_Explorer_box_model_bug</a>.
</p>

<p>
W skrócie, <span class="program">Internet Explorer 5</span> wyznacza szerokość elementu
wyłącznie na podstawie atrybutu <span class="variable">width</span>.
Prawidłowo: powinien do atrybutu <span class="variable">width</span> dodać marginesy,
padding oraz obramowanie.
Jeśli na przykład w kodzie HTML pojawi się element <span class="variable">div</span>:
</p>

<pre>
&lt;div id=&quot;tekst&quot;&gt;
Lorem ipsum...
&lt;/div&gt;
</pre>

<p>
opatrzony stylami:
</p>

<pre>
#tekst {
    width   : 200px;
    padding : 50px;
}
</pre>

<p>
to <span class="program">IE5</span> ustali jego szerokość na 200 pikseli,
podczas gdy prawidłowa wartość wynosi 300 pikseli
(tj. 200 + lewy padding 50 + prawy padding 50 = 300).
</p>

<p>
Problem ten dotyczy <span class="program">Internet Explorera 5</span> (przeglądarka ta ma tylko
jeden tryb pracy: <em>quirks mode</em>;
nie posiada ona trybu <em>strict mode</em>)
oraz <span class="program">Internet Explorera 6</span>
w trybie <em>quirks mode</em> (<span class="program">Internet Explorer 6</span> w trybie <em>strict mode</em>
poprawnie interpretuje szerokość pudełka).
</p>

<p>
Jakie są konsekwencje tego błędu?
Wbrew pozorom dość poważne. Jeśli bowiem zechcesz pracować w trybie <em>strict mode</em>
i tworzyć witryny zgodne ze standardami to na przeszkodzie stanie przeglądarka <span class="program">IE5</span>
(wykorzystywana &mdash; wg danych z <a href="http://ranking.pl">http://ranking.pl</a> &mdash;
przez 2,7% polskich internautów).
</p>

<p>
Witryna zgodna ze standardami będzie poprawnie interpretowana przez <span class="program">IE6</span>
zaś błędnie przez <span class="program">IE5</span>. Jak zatem przygotować arkusze stylów, które będą
inne dla przeglądarki <span class="program">IE6</span> (i wszystkich przeglądarek
pracujących w trybie <em>strict mode</em>) a inne dla <span class="program">IE5</span>?
Czy da się przygotować rozwiązanie powyższego problemu
bez stosowania technik po stronie serwera (np. PHP i wartości
<span class="variable">$_SERVER[&#39;HTTP_USER_AGENT&#39;]</span>)?
</p>

<h4>Rozwiązanie pierwsze: zmiana atrybutów CSS w JavaScript</h4>

<p>
Pierwsze z rozwiązań wykorzystuje skrypt JS.
Skrypt zawiera jedną funkcję o nazwie <span class="variable">przestyluj()</span>.
Funkcja ta jest wywoływana po pobraniu dokumentu,
przed wyświetleniem. Dzieje się to dzięki wykorzystaniu zdarzenia <span class="variable">onload</span>
elementu <span class="variable">body</span>:
</p>

<pre>
...
&lt;body onload=&quot;przestyluj();&quot;&gt;
..
</pre>

<p>
Wewnątrz funkcji odbywa się sprawdzenie.
Czy przeglądarka to <span class="program">Internet Explorer</span>:
</p>

<pre>
if (navigator.userAgent.indexOf(&quot;MSIE&quot;) != -1) {
    ...
}
</pre>

<p>
Jeśli tak, to dalej sprawdzamy, czy przeglądarka potrafi pracować
w trybie <em>strict mode</em>. Fakt ten stwierdzamy
porównując <span class="variable">document.compatMode</span> z wartością
<span class="variable">CSS1Compat</span>.
Jeśli tak, to podajemy poprawną wartość <span class="variable">width</span> wynoszącą 200.
W przeciwnym razie (czyli dla przeglądarki <span class="program">IE5</span>) podajemy
błędną wartość <span class="variable">width</span> równą 300:
</p>

<pre>
if (document.compatMode == 'CSS1Compat') {
    //style dla IE w trybie strict (np. IE 6)
    var tmp = document.getElementById("tekst");
    tmp.style.width = 200;
} else {
    //style dla IE w trybie quirks (np. IE 5)
    var tmp = document.getElementById("tekst");
    tmp.style.width = 300;
}
</pre>

<p>
Oczywiście rozwiązanie takie zadziała offline (nie wymaga ono
PHP), pod warunkiem, że włączona jest interpretacja skryptów JavaScript.
</p>

<p>
Kompletny kod funkcji <span class="variable">przestyluj()</span> jest przedstawiony na listingu 1.
</p>

#####{$listings[1]}#####

#####{$frames[1]}#####

<h4>Rozwiązanie drugie: komentarze HTML będące instrukcjami dla <span class="program">IE</span></h4>

<p>
Drugim, lepszym, sposobem dostarczenia odmiennych stylów dla <span class="program">IE5</span>
oraz <span class="program">IE6</span> jest wykorzystanie
specjalnych komentarzy HTML interpretowanych wyłącznie przez przeglądarki <span class="program">IE</span>.
Komentarz taki przyjmuje postać:
</p>

<pre>
&lt;!--[if gte IE 6]&gt;
...
...zawartość przeznaczona dla
...IE w wersji od 6 wzwyż
...
&lt;![endif]--&gt;
</pre>

<p>
lub
</p>

<pre>
&lt;!--[if lt IE 6]&gt;
...
...zawartość przeznaczona dla
...IE w wersji poniżej 6
...
&lt;![endif]--&gt;
</pre>

<p>
Każda inna przeglądarka powinna oba powyższe wpisy potraktować
jako komentarze HTML (zwróć uwagę, że są one umieszczone
pomiędzy <span class="variable">&lt;!--</span>
oraz <span class="variable">--&gt;</span>).
Natomiast <span class="program">IE</span> (bez względu na wersję) potraktuje je jako instrukcje <span class="variable">if</span>.
Warunki instrukcji zawierając operatory
<span class="variable">gte</span> oraz <span class="variable">lt</span>.
Są to skróty od angielskich terminów <em>greater than or equal</em>
(ang. większe lub równe niż) oraz <em>less than</em> (ang. mniejsze niż).
</p>

<p>
Jeśli więc w dokumencie HTML umieścisz wpisy:
</p>

<pre>
&lt;!--[if gte IE 6]&gt;
&lt;style type=&quot;text/css&quot;&gt;
#tekst {
    width : 200px;
}
&lt;/style&gt;
&lt;![endif]--&gt;

&lt;!--[if lt IE 6]&gt;
&lt;style type=&quot;text/css&quot;&gt;
#tekst {
    width : 300px;
}
&lt;/style&gt;
&lt;![endif]--&gt;
</pre>

<p>
to przeglądarka <span class="program">IE6</span> otrzyma poprawną wartość 200, zaś przeglądarka
<span class="program">IE5</span> wartość 300, uwzględniającą błąd wyznaczania szerokości pudełka.
</p>

#####{$frames[2]}#####

<h3>Podsumowanie</h3>

<p>
Jeśli myślisz o tworzeniu witryn zgodnych ze standardami,
to powinieneś zwrócić uwagę na tryb pracy przeglądarki.
Myślą przyszłościowo rozsądnym rozwiązaniem wydaje mi się
przygotowywanie witryn, które będą interpretowane
(przez wszystkie nowe przeglądarki) w trybie standardów (<em>strict mode</em>).
</p>

<p>
Jeśli duży procent odwiedzin odbywa się przy użyciu przeglądarki <span class="program">IE5</span>,
to problem z wyznaczaniem szerokości pudełka rozwiążesz
stosując specjalny skrypt JS lub komentarze
będące instrukcjami <span class="variable">if</span> dla <span class="program">IE</span>.
</p>

<p>
Pamiętaj, że jeśli wykonywane przez Ciebie witryny są
interpretowane w trybie <em>quirks mode</em>,
to nie zbliżasz się do standardów. Przekształcenie witryny
poprawnie wyglądającej w trybie <em>quirks mode</em>, tak by była ona interpretowana w trybie
<em>strict mode</em> może wymagać (szczególnie w odniesieniu do <span class="program">IE</span>) wiele pracy.
</p>

#####{$tables[1]}#####

#####{$tables[2]}#####