Łukasz Aranowski - strona domowa!

XHTML 1.1 i atrybut TARGET

Wstęp

Miałem problem. Chciałem zgodnie z najnowszymi standardami zakodować stronę w XHTML 1.1. Walidatorowi W3C nie spodobało się jednak użycie w elemencie a atrybutu target="_blank". Wpisałem szybko w polskiego Google'a "XHTML target" i co znalazłem?

Znacie to uczucie gdy na jakimś forum zadajecie jakieś pytanie i naraz odzywa się mnóstwo mędrków, co udowadniają Ci że jesteś kretynem, bo tak naprawdę wcale nie potrzebujesz rozwiązywać swojego problemu? Tak właśnie było tym razem. Okazało się, że przede mną ten problem miało mnóstwo ludzi i każdy z nich został wyśmiany. Zamiast napisać im gdzie mogą znaleźć rozwiązanie swojego problemu, mnóstwo "życzliwych" poświęciło swój czas na tłumaczenie im dlaczego nie powinni go rozwiązywać. Oczywiście nie chodziło o to, żeby pomóc pytającemu. Chodziło o prosty fakt ukrycia własnej niewiedzy.

Faktycznie, W3C świadomie wyrzuciło atrybut target z XHTML 1.1 wychodząc z założenia, że to użytkownik ma decydować czy strona docelowa ma mu się ukazać w nowym czy w tym samym oknie. Atrybut ten pierwotnie służył do obsługi ramek, jednak już od dawna większość webmasterów używała go właśnie do wyświetlania linków w nowym oknie.

Jednak dla rozwiązań biznesowych, gdzie chcemy klientowi pokazać jakiegoś ciekawego linka, ale nie chcemy go wyrzucać z naszej strony jest to nadal przydatny atrybut. Na stronach, które ja projektuję z reguły wszystkie linki zewnętrzne otwierają się w nowym oknie, a wewnętrzne - w tym samym. Czyli atrybut ten ciągle mi się przydaje.

Rozwiązanie

Obejście problemu braku atrybutu target w specyfikacji XHTML wydaje się możliwe do rozwiązania używając JavaScript. Jednak po pierwsze zaśmiecamy w ten sposób nasz kod zbędnymi skryptami, a ponadto uniemożliwiamy poprawne indeksowanie naszych linków przez Google, a co za tym idzie utrudniamy pozycjonowanie naszych stron i serwisów docelowych dla opisywanych linków. Jak to rozwiązać?

Po przemyśleniu sprawy i wielu godzinach spędzonych w sieci mogę zaproponować takie rozwiązanie (PHP jest konieczne, aby serwować stronę w różnych trybach, ale pewnie i tak już go używasz skoro piszesz w XHTML 1.1).

<?
if ((strpos($_SERVER['HTTP_ACCEPT'], 'application/xhtml+xml') !== false) OR (strpos($_SERVER['HTTP_USER_AGENT'], 'W3C_Validator') !== false))
     {
     $wstaw_meta = false;
     header('Content-Type: application/xhtml+xml; charset=iso-8859-2');
     header("Vary: Accept");
     echo '<?xml version="1.0" encoding="ISO-8859-2"?>'."\n";
     echo '<?xml-stylesheet type="text/css" href="styl.css"?>'."\n";
     echo '<!DOCTYPE html PUBLIC "-//mendel.pl//DTD XHTML 1.1 plus target//EN" "http://www.mendel.pl/DTD/xhtml11-target.dtd">'."\n";
     echo '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pl">'."\n";
     }
else
     {
     $wstaw_meta = true;
     header('Content-Type: text/html; charset=iso-8859-2');
     header("Vary: Accept");
     echo '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">'."\n";
     echo '<html lang="pl">'."\n";
     }
?>
<head>
<title>Przykład: XHTML + TARGET</title>
<? if ($wstaw_meta) echo '<link rel="Stylesheet" href="styl.css" type="text/css" />'."\n"; ?>
</head>
<body>
<p>To jest przykład dokumentu XHTML 1.1 z poprawną walidacją mimo użycia niedozwolonego atrybutu TARGET.</p>
<p><a href="http://www.pttk.pl/" target="_blank">PTTK</a></p>
</body>
</html>

Co się dzieje w tym dokumencie?

Po pierwsze warunek w pierwszej linii sprawdza czy Twoja przeglądarka akceptuje typ MIME przesyłanego dokumentu 'application/xhtml+xml'. Ten tryb pracy przeglądarki jest konieczny aby sens miało serwowanie jej strony w XHTML. Obsługują go niemal wszystkie przeglądarki z wyjątkiem... Internet Explorera. Szkoda słów...

Zatem jeśli przeglądarka nie akceptuje tego typu (i nie jest walidatorem W3C), to serwowany jest jej nagłówek HTML 4.01 Transitional trybem 'text/html' i po problemie.

Jeśli jednak warunek z pierwszej linii jest spełniony, to wtedy za pomocą trybu 'application/xhtml+xml' przesyłamy jej nagłówek XHTML 1.1 z bardzo dziwną deklaracją DOCTYPE.

Przypatrzmy się tej deklaracji:

<!DOCTYPE html PUBLIC "-//mendel.pl//DTD XHTML 1.1 plus target//EN" "http://www.mendel.pl/DTD/xhtml11-target.dtd">

Otóż odwołuje się ona do pliku DTD umieszczonym... na tym serwerze. :-) Co to za plik i o co chodzi?

XHTML jest tworem złożonym z modułów. Moduły te odpowiadają za obecność w XHTML różnych elementów i ich atrybutów. Nie wszystkie istniejące moduły są włączone w oficjalną wersję XHTML. Popatrzmy na źródło wskazanego tutaj pliku DTD (pliku określającego typ dokumentu):

<!ENTITY % XHTML.version "-//mendel.pl//DTD XHTML 1.1 plus target//EN">
<!ENTITY % xhtml11.dtd PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
%xhtml11.dtd;
<!ENTITY % xhtml-target.mod PUBLIC "-//W3C//ELEMENTS XHTML Target 1.0//EN" "http://www.w3.org/TR/xhtml-modularization/DTD/xhtml-target-1.mod">
%xhtml-target.mod;

Plik ten de facto składa się z trzech poleceń. Pierwsze deklaruje jego nazwę, drugie ładuje wszystkie moduły "oficjalnego" XHTML, a trzecie dodaje moduł zawierający atrybut target. Skąd? Oczywiście z serwera W3C. Konsorcjum owo przygotowało ten moduł, jednak nie włączyło go do tej wersji języka. Prezentowany plik właśnie to robi - dołącza do XHTML 1.1 moduł obsługujący atrybut target. Umożliwia to poprawną walidację pliku go wykorzystującego.

Zakończenie

Możesz w swoich plikach odwoływać się do pliku DTD na mendel.pl. Zapewniam, że go nie skasuję, bo sam go będę używał. Możesz jednak również - dla swojego komfortu psychicznego - utworzyć go u siebie w serwisie, zmienić mu nazwę i odwoływać się w deklaracji DOCTYPE do swojego własnego pliku DTD.

I nie przejmuj się wszystkimi, co w odpowiedzi na Twoje pytania o użycie target w XHTML 1.1 odpowiadali Ci, że się nie da i nie wolno. Da się i wolno. :-)

Poprawny XHTMLPoprawny CSS
Powrót do strony głównej
Ostatnia zmiana: 4 sierpnia 2017 r.