IE 6+7 bugy: Problémy se seznamy (aktualizováno)

Internet Explorer 6 není dokonalý prohlížeč. Jeho vykreslovací jádro chybuje, zadýchá se pokaždé, když od něj kodér chce byť jen trochu složitější konstrukci podle not CSS 2. Vykreslovací jádro Trident, které je srdcem Internet Exploreru, není však vůbec špatné. Čtvrtá verze tohoto jádra, kterou obsahuje Internet Explorer 6, je dokonce poměrně dobrá na poměry, které vládly ve standardech v letech 2000–2001, kdy bylo CSS2.1 v nedohlednu a CSS2 stále ještě půdou, na niž noha jiného prohlížeče než IE pořádně nevstoupila. To se odvážila až mimořádně povedená Mozilla 1.0 v létě 2002 a použitelná Opera 7 o rok později.

Z předchozího textu si prosím zapamatujte tyto dva údaje:
  • IE6 obsahuje vykreslovací jádro Trident IV,
  • Trident IV byl vyvíjen v letech 2000–2001,

Právě jádro Trident IV přineslo dvě závažné chyby ve vykreslování seznamů, o kterých však prakticky nikdo neví. Jsou dokonce tak neznámé, že si jich nevšimli ani vývojáři vykreslovacího jádra Trident V, které je implementováno v Internet Exploreru 7. Ano, správně, uplynulo celých pět let. Nemějme to však Microsoftu za zlé.

Chyba 1: Nepřičtu se, ani kdyby ses na hlavu stavěl

První chybu a celý tento článek nastartoval Plaváček, když si všiml, že v IE7 se všechny položky číslovaných seznamů označují jako „1.“. Den předtím přidal do inkriminovaného stylopisu tuto deklaraci, aby se vyhnul Zmizíkovi:

* {
  ...
  ...
  min-height: 1px;
}

A právě tato deklarace vypustila dlouho skrývaného Krakena, chybu svými parametry málo vídanou. Pokud nastavíte položce číslovaného seznamu libovolný rozměr (width, height, min-width, min-height), tato položka bude označena jako „1.“. Chyba se projevuje pouze ve vykreslovacích jádrech Trident IV a Trident V (tedy IE6 a IE7). Je zcela irelevantní, zdali se prohlížeč nachází v quirk či standardním módu, pouze je třeba zohlednit fakt, že IE6 v obou módech a IE7 v quirk módu minimální výšku ani šířku neumí. Podívejte se na tento vzorový kód:

<style>
li {
  width: 500px;
}
</style>

<ol>
  <li>test</li>
  <li>test</li>
  <li>test</li>
</ol>

Takovou vlastností je například width. Pokud prvku nastavíte jakoukoliv šírku kromě automatické (width: auto), vlastnost hasLayout se změní na true. To stejné se, pro zajímavost, stane, když nastavíte proprietární vlastnost zoom. Právě nastavení zoom: 1 se dá vhodně využít pro testovací účely. Ale o tom někdy příště.

Jak můžete vidět, v příkladu je pro prvek LI nastavena šířka. Vlastnost hasLayout prvku LI tedy nabývá hodnoty true. V praxi hasLayout nastavené na true mění či ruší účinek některých dalších CSS vlastností, například display. Víte, že prvek seznamu má výchozí vlastnost display nastavenu na hodnotu list-item. Toto nastavení s sebou mimo jiné nese i příznak, který říká, že jádro má u tohoto prvku navyšovat vnitřní počítadlo. Právě tento příznak změna hasLayout ničí.

Je třeba tedy explicitně obnovit stav před změnou hasLayout. Toho dosáhneme snadno deklarací display: list-item. Výsledný kód vypadá následovně:

<style>
li {
  width: 500px;
  display: list-item;
}
</style>

<ol>
  <li>test</li>
  <li>test</li>
  <li>test</li>
</ol>

Chyba 2: Když se odrážky rozhodnou schovat

Pokud je první chyba závažná, pak tato druhá je ještě o chlup závažnější. Projevila se, když jsem si prvně hrál s Plaváčkovým kódem, a její příčina je v podstatě úplně stejná, pouze řešení se liší. Prohlédněte si tento kód:

<style>
ol {
  width: 500px;
}
</style>

<ol>
  <li>test</li>
  <li>test</li>
  <li>test</li>
</ol>

Kód vypadá velmi podobně jako ten předchozí, viďte? Když si ukázku otevřete v Internet Exploreru, uvidíte, že chybějí odrážky. Napadne vás: Aha, ta stejná chyba! Pro seznam je nastavena vlastnost width, takže seznam má hasLayout roven true, to ovlivnilo nějakou vnitřní vlastnost, která zajišťuje vykreslování odrážek.

A máte pravdu. Je to zhruba takto. Ale co s tím? Znám dvě řešení, jedno využívá slabiny quirk módu Internet Exploreru a to druhé funguje. :o) Ukážu vám jen to druhé.

Psst, to první řešení je nastavit display: inline pro seznam, ale je to prasárna!

Když nyní víte, že seznamy vykreslují odrážky mimo hranice kontejneru, jímž jsou určeny, snadno vás už napadne, že změna vlastnosti hasLayout prostě tyto „přebytky“ odřízla. Potřebujete dostat odrážky do kontejneru, na což je naštěstí v CSS vlastnost, a to list-style-position (toto neplatí, čtěte update níže). Stačí ji nastavit na hodnotu inside.

Ukázka řešení:

<style>
ol {
  width: 500px;
  list-style-position: inside;
}
</style>

<ol>
  <li>test</li>
  <li>test</li>
  <li>test</li>
</ol>

Update:

Knopi v komentářích nastínil jiné, v případě seznamů, jejichž položky se mohou zalomit na více řádků, mnohem lepší řešení. Stačí prvkům LI nastavit dostatečný levý margin, aby se čísla dostala zpět do kontejneru. Viz komentáře č. 14 a 16.

Naopak použití vlastnosti list-style-position nedoporučuji. Pokud má seznam více než devět prvků, začne se text položek seznamu „slévat“ dohromady s řadovými číslicemi.

Zdrojový kód nového řešení je v komentáři č. 16.

Závěrem

Určitě se teď ptáte, proč si takových chyb nevšimli vývojáři už dříve. Vysvětlení je snadné. S Plaváčkem jsme se shodli, že v praxi se nesetkáváme se situacemi, kdy bychom potřebovali číslovanému seznamu nastavit šířku či výšku jeho položky. To stejné platí i o druhé chybě – když už potřebujeme zadat seznamu šířku, tak neponecháváme odrážky, protože se téměř vždy jedná o menu, u kterého každý rozumný kodér řeší odrážky, jsou-li třeba, pomocí background-image.

Ani tyto praktické postřehy nic nemění na faktu, že se jedná o chyby závažné, které naštěstí mají jednoduchá řešení. Mějte se hezky.

3. 11. 2006, 13.59 | (X)HTML, CSS, Prohlížeče.


Zanechte komentář





Můžete použít Texy! formátování.
Pokud se obsah boxů níže mění, zatímco píšete, potom žádné číslice nevyplňujte. V takovém případě antispam funguje, pouze se prohlížeči nepovedlo skrýt tento box.