Implementační chyby v prohlížečích – double margin a peekaboo bug

25. února 2004

V druhém článku ze série o implementačních chybách v prohlížečích poodhalíme dvě nejčastěji řešené chyby, vznikající v Internet Exploreru při použití plovoucích boxů. Jedná se o takzvaný „Peekaboo bug“ a problém dvojnásobného okraje (double margin).

Plovoucím boxem rozumíme box, který má nastavenou vlastnost float. Podle specifikace CSS je plovoucí box odsunut k levému nebo pravému okraji výplně obsahujícího boxu. Plovoucí box je vyjmut z toku dokumentu a ostatní bloky se proto formátují stejně, jako by v dokumentu vůbec neexistoval. Jen řádky jsou podle plovoucího boxu patřičně zúženy a říkáme, že jej obtékají.

Peekaboo

Peekaboo je velmi nepříjemná ale řešitelná chyba, jejíž název je složeninou anglického „Peek a boo“. Zajímavé na ní je, že se týká jen Internet Exploreru verze 6 ve standardním i kompatibilním režimu, u starších verzí IE se chyba nevyskytuje.

Chybu je možné popsat takto: Jestliže v dokumentu existuje plovoucí box obtékáný odstavcovým textem, a zároveň dolní krana okraje zmíněného plovoucího boxu je níže, než dolní hrana okraje odstavcového textu, pak není odstavcový text vykreslen. Demonstrujme si chybu příkladem:

<html>
<head>
  <title>Peekaboo</title>
  <style type=“text/css“>
    #sample {
      padding : 10px;
      color : white;
      background-color : black; /* Podmínka vzniku chyby */
    }
    #floated {
      width : 70px;
      height : 70px;
      float : left; /* Podmínka vzniku chyby */
      background-color : #dadada;
    }
    #p2 {
      clear : left;
      background-color : gray;
    }
  </style>
</head>
<body>
<div id=“sample“>
  <div id=“floated“>
  </div>
  <div id=“p1″>
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nullam augue. Maecenas pharetra ultrices tellus.
  </div>
  <div id=“p2″>
    Nunc pretium, odio quis vestibulum pretium, augue mauris iaculis lectus, a placerat nibh ipsum at est. Donec venenatis mi.
  </div>
</div>
</body>
</html>

Pohleďme, jak by měl být prohlížečem příklad vykreslen a jak jej vykresluje Internet Explorer 6:

Správné vykreslení příkladu
Správné vykreslení příkladu

Vykreslení příkladu v IE6
Vykreslení příkladu v IE6

Na první pohled to vypadá, jako by jeden odstavec v dokumentu chyběl. Pravdou však je, že Internet Explorer v tomto případě chybně vykresluje pozadí nadřazeného bloku později než text, který tím pádem není vidět. O jeho přítomnosti se lze ale snadno přesvědčit pomocí myši tím, že se pokusíme v předpokládaném místě text vybrat:

Výběr textu myší
Výběr textu myší

Zúžíme-li okno prohlížeče tak, aby dolní hrana okraje problematického odstavce byla ve svislém směru textem odsunuta až pod úroveň dolního okraje plovoucího boxu, pak je problematický odstavec v celé své délce vykreslen řádně:

Delší odstavec je vykreslen
Delší odstavec je vykreslen

Kde je problém

Aby chyba vznikla, musí být splněno souběžně několik podmínek:

  1. Existuje box (v příkladu pojmenovaný „sample“) s deklarovaným pozadím (rodina vlastností background). Tento box nemá explicitně zadanou šířku (vlastnost width) ani výšku (vlastnost height).
  2. Box „sample“ obsahuje plovoucí box (v příkladu pojmenovaný „floated“).
  3. Plovoucí box „floated“ je obtékán odstavcovým textem (v příkladu pojmenovaný „p1“), přičemž odstavců může být libovolné množství, nejméně však jeden. Celková výška odstavce či odstavců (včetně okrajů, rámečku a výplně) je menší, než celková výška plovoucího boxu.
  4. Odstavcový text „p1“ je následován elementem s definovanou vlastností clear.
  5. V hierarchii elementů dokumentu neexistuje mezi elementem generujícím obsahujícím box „sample“ a elementem generujícím plovoucí box „floated“ další element, který by měl explicitně nastavenou výšku nebo šířku.

Řešení

Známe příčiny i důsledky chyby, takže se můžeme pokusit náš příklad opravit tak, aby k chybě nedocházelo. Možností je více, vybírám jen ty použitelné:

  1. Přidejme obsahujícímu boxu „sample“ deklaraci width, nebo height. V našem případě přidejme ke stylovému zápisu deklaraci: #sample { width : 100%; }.
  2. Deklarujme u obsahujícího boxu „sample“ vlastnost line-height. V našem případě přidejme ke stylovému zápisu deklaraci: #sample { line-height : 1.2; }.
  3. U odstavcového textu „p1“ nastavme vlastnost position na hodnotu relative. V našem případě přidejme ke stylovému zápisu deklaraci: #p1 { position : relative; }.

Dvojnásobný okraj

Dvojnásobný okraj, v angličtině „double margin“, je chyba Internet Exploreru verzí 5, 5.5 a 6, a to ve standardním i kompatibilním režimu. Chybu lze popsat velmi jednoduše – vlevo plovoucí box má 2x větší levý okraj oproti deklaraci. Analogicky i plovoucí box vpravo má dvojnásobně větší pravý okraj proti deklaraci. Opět bude nejlépe použít příkladu:

<html>
<head>
  <title>Double margin</title>
  <style type=“text/css“>
    #sample {
      background-color : #aeaeae;
      border : 2px solid black;
    }
    #p1, #p2 {
      margin-left : 35px;
      width : 150px;
      border : 2px solid black;
      background-color : #dadada;
    }
    #p1 { float : left; }
    #p2 { clear : left; }
  </style>
</head>
<body>
<div id=“sample“>
  <div id=“p1″>
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
  </div>
  <div>&nbsp;</div>
  <div id=“p2″>
    Vestibulum congue convallis ante. Fusce facilisis volutpat nibh.
  </div>
</div>
</body>
</html>

Správné vykreslení příkladu
Správné vykreslení příkladu

Plovoucí box má v IE dvojnásobný okraj
Plovoucí box má v IE dvojnásobný okraj

Řešení

V předchozím článku jsem se zmiňoval o matrjošce, kterou můžeme stejně dobře použít i k ošetření dvojnásobného okraje. U plovoucího boxu nastavíme levý okraj na nulu, v HTML kódu do elementu generujícího plovoucí box vnoříme další blokový element a kýžený okraj nastavíme u něj. Vezměme náš příklad a opravme jej matrjoškou:

<html>
<head>
  <title>Double margin – matrjoska hack</title>
  <style type=“text/css“>
    #sample {
      background-color : #aeaeae;
      border : 2px solid black;
    }
    #p1 div, #p2 {
      margin-left : 35px;
      border : 2px solid black;
      background-color : #dadada;
    }
    #p1 {
      float : left;
      width : 185px;
    }
    #p2 {
      clear : left;
      width : 150px;
    }
  </style>
</head>
<body>
<div id=“sample“>
  <div id=“p1″>
    <div>
      Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
    </div>
  </div>
  <div>&nbsp;</div>
  <div id=“p2″>
    Vestibulum congue convallis ante. Fusce facilisis volutpat nibh.
  </div>
</div>
</body>
</html>

Bohužel, matrjoška bývá někdy poměrně těžkopádná (například u obtékaných obrázků). Naštěstí má IE další, v tomto případě velmi příjemnou, vlastnost – deklarujeme-li u plovoucího boxu vlastnost display: inline;, IE u tohoto boxu okraj nezdvojí, a vykreslí jej řádně. Ptáte se, co na to specifikace? V CSS 2.1 je definováno, že až na hodnotu none je vlastnost display u plovoucích boxů ignorována. Jde tedy o čisté řešení bez vedlejších účinků. Náš příklad ošetříme přidáním následující deklarace ke stylovému zápisu: #p1 { display : inline; }.

Myslím, že na jeden článek jsou tyto dvě implementační chyby více než dostačující. Budu však rád, když v komentářích zveřejníte vlastní nápady nebo další známé triky na jejich řešení.

Odkazy, zdroje

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *