toscho.design

WordPress: Internet Explorer ohne CSS-Hacks ansprechen

Den Internet Explorer betrachten die meisten Webentwickler zu Recht als chronische Krankheit. Neben anderen Browsern sieht auch die kommende Version 9 eher bedrückend aus. Ehe wir diesem Browser keine Extrawurst mehr braten müssen, wird noch viel Zeit vergehen.

Um den IE im Stylesheet gesondert anzusprechen, brauchen wir weder Hacks im CSS noch eine zusätzliche Datei oder gar (pfui!) eine serverseitige Browserweiche. Wir müssen nur das Element <html> über Conditional Comments anpassen. Diese Idee hatte Paul Irish schon 2008.

Ich habe das neulich in einem WordPress-Theme eingesetzt und mag es so sehr, daß ich künftig all meine Themes damit ausrüsten werde.
Ein wenig umständlich: Die Sprachattribute werden in WordPress mit der Funktion language_attributes() erzeugt – und die hat ein fest eingebautes echo, das man nicht abschalten kann. Ich will nun nicht drei Meter Code in der header.php stehen haben, deshalb habe ich mir zwei kleine Funktionen gebaut. Die Funktion get_language_attributes() ist obendrein etwas schlanker als das Original, und sie gibt das Attribut dir nur aus, wenn der Text von rechts nach links läuft. Andernfalls ist es an dieser Stelle überflüssig.

Doch zum Code, er gehört in die functions.php:

<?php
/**
 * html5 start tag + language attribute + conditional tags for IE Win
 * @link   http://paulirish.com/?p=88
 * @param  bool $print
 * @return void|string
 */
function htmlstart($print = TRUE)
{
    $out  = '<!Doctype html>';
    $lang = get_language_attributes();
    $ies  = array (
        6 => 'lte6 lte7 lte8'
    ,   7 => 'lte7 lte8'
    ,   8 => 'lte8'
    ,   9 => ''
    );

    foreach ( $ies as $n => $class )
    {
        $out .= "<!--[if IE $n]><html $lang class='ie ie$n $class lte9'><![endif]-->";
    }

    $out .= "<!--[if !IE]><!--><html $lang><!--<![endif]-->";

    if ( ! $print )
    {
        return $out;
    }

    print $out;
}

if ( ! function_exists('get_language_attributes') )
{
    /**
     * Returns the language attributes.
     *
     * Unobstrusive copy from the core.
     * Requires WP 3.0+
     *
     * @param string $doctype The type of html document (xhtml|html).
     */
    function get_language_attributes($doctype = 'html') {
        $output = is_rtl() ? 'dir="rtl"' : '';

        if ( $lang = get_bloginfo('language') )
        {
            $output .= ( ( get_option('html_type') != 'text/html'
                || $doctype == 'xhtml' )
                ? ' xml:' : '') . 'lang="' . $lang . '"';
        }

        return apply_filters('language_attributes', $output);
    }
}

Im Theme rufen wir die Funktion dort auf, wo früher die Doctype-Deklaration und das Start-Tag standen.
Die Ausgabe sieht (hier aufgehübscht) etwa so aus:

<!Doctype html>
<!--[if IE 6]>
    <html lang="de-DE" class='ie ie6 lte6 lte7 lte8 lte9'>
<![endif]-->
<!--[if IE 7]>
    <html lang="de-DE" class='ie ie7 lte7 lte8 lte9'>
<![endif]-->
<!--[if IE 8]>
    <html lang="de-DE" class='ie ie8 lte8 lte9'>
<![endif]-->
<!--[if IE 9]>
    <html lang="de-DE" class='ie ie9 lte9'>
<![endif]-->
<!--[if !IE]><!-->
    <html lang="de-DE">
<!--<![endif]-->

Nein, das ist kein sehr schönes Markup mehr. Aber so richtig schlimmes auch nicht. Obendrein validiert es.

Im Stylesheet können wir den Internet Explorer jetzt ganz einfach mit der passenden Klasse ansprechen:

.ie8
{
    top:        10px;
}
.lte7
{
    top:        15px;
}

Das kann ich mir viel besser merken als Kommentarhacks oder Spielereien mit ungültigen Selektoren und Eigenschaften.

Mehrere Internet Explorer auf einem Windows kann man sich mit der Utilo IE Collection einrichten. Zum Testen der Conditional Comments habe ich im Labor eine kleine Seite eingerichtet: CC-Test.

14 Kommentare

  1. datenkind am 28.09.2010 · 09:11

    Sowas in der Richtung nutze ich eigentlich schon lange – ich glaub sogar aus dem Post von Irish heraus. Weiß ich gar nicht mehr.
    Allerdings hab ich es bisher immer händisch gemacht und nicht so ausführlich, sondern direkt nur die Version angesprochen. Und alles in den body ausgelagert.

    Aber coole Sache, spart eigentlich einiges an Arbeit, wenn ich mich auch erst an die Klassensammlung (zumindest optisch) gewöhnen müsste.

    Manchmal reicht ja auch einfach sowas hier:
    http://datenkind.de/you-suck-but-you-rock/

  2. Felix de Ruiter am 28.09.2010 · 11:07

    Hallo Thomas,

    worin liegt denn der Vorteil gegenüber der gebräuchlichen Art, die Conditional Comments als body-Klasse anzulegen? Warum das ganze im html-Element und dann auch noch als Funktion?

    Noch eine Frage: Was hast du gegen eine server-seitige Abfrage? Ich finde, dass das wesetentlich eleganter ist, als auf Conditional Comments zurückzugreifen.

    PS: In deinem Kommentar-Formular zappeln die Eingabefelder nervös herum, weil sich nur die Rahmenbreite, aber nicht die Höhe oder Innenabstand verändern. Außerdem kann man nicht erkennen, in welcher Zeile man sich befindet, wenn die Position am linken Rand der Textarea liegt.

    Liebe Grüße
    Felix

  3. Peter am 28.09.2010 · 12:20

    Dies ist die einzig wahre Methode IE-spezifisches CSS einzubauen.

    Man sollte vielleicht noch erwähnen, dass class auf html-Elementen erst ab HTML5 erlaubt ist. Für alles andere kann man das class-Attribut in den body stecken, kommt auf das gleiche raus.

  4. Thomas Scholz am 28.09.2010 · 17:28

    @Felix de Ruiter: Wenn man erst für body die CC einsetzt, blockiert das im IE den Download aller anderen Elemente, bis das Stylesheet komplett geladen wurde.
    Steht aber mindestens ein CC vor dem ersten Stylesheet, passiert das nicht. Da das Starttag für html vor dem ersten Stylesheet kommen muß, das für body aber danach, lädt die Seite im IE mit der hier vorgestellten Methode also etwas schneller.

    Serverseitige Abfragen muß man umständlich aus cachenden Proxys heraushalten. Das klappt nicht zuverlässig und schadet allen Lesern, weil sie jetzt den Geschwindigkeitsvorteil des Caches nicht mehr nutzen können. Obendrein ist der UA-String sehr unzuverlässig. Das ist nicht elegant, sondern vergrößert einfach die Summe der Probleme.

  5. Felix de Ruiter am 28.09.2010 · 18:25

    Alles klar, danke für die Antwort und für den Artikel! =)

  6. Ralf am 28.09.2010 · 20:03

    Mal ne Frage: Muss die Conditional-Kirmes im Head-Bereich sein? Ich würde anstatt dem foreach einfach den User-Agenten abfragen und dann die entsprechende Klasse ausgeben.

    Conditional Comments sind doch eher was für statische Seiten.

  7. Thomas Scholz am 28.09.2010 · 21:39

    @Ralf: Exakt diese Frage habe ich zwei Absätze darüber beantwortet. Conditional Comments werden vom Browser ausgewertet; wie die Seiten erzeugt werden, hat damit nichts zu tun.

  8. David am 29.09.2010 · 11:05

    Kommt ja gar nicht in Frage, dass ich mein Stylesheet und das Markup derart aufblähe, nur um diw IEs einzubeziehen. Die bekommen ein extrastylesheet per CC und gut ist. Diesen zusätzlichen Request nehm ich gern in Kauf, dafür hab ich weniger Daten für die Nutzer normaler Browser.

  9. Ralf am 30.09.2010 · 03:50

    "Obendrein ist der UA-String sehr unzuverlässig."
    Könnte ich jetzt nicht bestätigen. Ausgenommen diejenigen, die ihren UA-String verschleiern. Und die sind, meiner Ansicht nach, selber schuld.

    "Serverseitige Abfragen muß man umständlich aus cachenden Proxys heraushalten."
    Das Problem hast du generell bei allen (dynamisch erstellten) Webseiten. Wenn du jetzt den Artikel da oben einfach nur aktualisierst, hättest du ein ähnliches Problem.
    Entweder es wird ein anderer Inhalt gesendet, dann sollte auch der Proxy seine Daten ändern. Oder der Proxy liefert stur einfach die gespeicherte Webseite aus ohne beim Server nachzufragen. In dem Fall sollte man sich Gedanken über einen anderen Proxy machen.

    Das es etwas aufwendiger ist für jede IE-Version eine andere Version der Webseite zu cachen, stimmt. Das kann man aber durch z.B. Server Side Includes (SSI) oder PHP-Mechanismen abdämpfen indem man nur die Teile der Webseite dynamisch generiert, die sich ändern, und andere Teile, die sich nicht bei jeder Abfrage ändern, in den Cache packt.

    Beim Cachen gebe ich dir Recht. Wäre aufwendiger. Beim Proxy nicht. Ein schlecht konfigurierter Proxy kann nicht Sorge des Webdesigners sein.

  10. Lena am 04.10.2010 · 23:41

    Ach Du Scheiße. Entschuldige, das passt nicht zum Thema. Du schreibst göttlich. Ich wickel mich sofort in ein Versteck ein, denn ich dachte (besser: ich hoffte), ich könnte schreiben. Komm raus aus diesem Versteck hier: "[if IE 6]". Und schreib. Prosa, Lyrik, ein Buch von mir aus, aber tu´s bitte. Danke.

  11. Sebastian am 05.10.2010 · 08:54

    Finde es einfach eh nur übel das es eine solche Krankheit wie den IE noch gibt, es gibt soviel klasse Alternativen da draußen. Also weswegen beim IE bleiben ?

    Aber trotzdem vielen Dank für die Lösung dieses Problems!

  12. Reinfried am 08.10.2010 · 09:13

    Danke für das Tipp, im September IE ist 30% den Browsern, und IE6 und 7 nur 13%, aber wir brauchen auch Hacks für die neue Versionen....endlos!

  13. Sabine am 28.11.2010 · 13:31

    Warum kann eine normal gestaltete Internetseite nicht einfach überall gleich aussehen, man muss sich doch irgendwie auf einen Standart (der dann für alle gilt!) einigen können!

  14. Frank Rost am 19.12.2010 · 21:08

    @Sabine: Standard ... ;)

    Die IE Seuche wird uns ja leider solange wie es Windowsrechner gibt verfolgen. Zumindest sind die nötigen Anpassungen nicht mehr so schlimm wie in den IE6 Zeiten.

    Danke jedenfalls für den Tipp zum Hack!