http://sietook.druskova.sk/?ukaz=archiv&id=255#obsah
Otázka pro vás: Proč profesní sebevražda?
Nápověda: Peter Druska je autorem knihy o XHTML a mnoha článků zaobírajících se právě tímto značkovacím jazykem.
Prosím, rozepište se v komentářích.
http://sietook.druskova.sk/?ukaz=archiv&id=255#obsah
Otázka pro vás: Proč profesní sebevražda?
Nápověda: Peter Druska je autorem knihy o XHTML a mnoha článků zaobírajících se právě tímto značkovacím jazykem.
Prosím, rozepište se v komentářích.
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: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é.
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>
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>
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.
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.
This is a translation of my previous article Obrázek na pozadí horizontální čáry (HR) bez obalového prvku v IE (czech). Vilém Málek convinced me that the best thing I can do is to translate and publish it – so the whole community can profit from it. So don't complain about my horrid English. If you laugh now, stop reading. I really mean it! :o) OK, let's advance to the article.
I'm kind of mythbuster and CSS is my playground. Yesterday while reading some long forgotten bookmarks I noticed that Marek Prokop as well as Petr Václavek didn't succeed when trying to get rid of the annoying border which is surrounding HR element in IE and which prevents this element to be used as a canvas for some kind of fancier separator. I know the solution.
Here is the thing: you have some paragraphs which you wanna have separated using some kind of fancy line or ornament. But you like semantics as well as the users of text browsers, so you want those paragraphs to be separated using <hr> element in the source code. What are the options?
You might wonder whats co complicated using the option number one. In that case look at the example.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<title>Image on a background of horizontal rule</title>
<style type="text/css">
hr {
border: none;
background: url('image.gif') center center no-repeat;
height: 15px;
}
</style>
<p>Lorem ipsum...</p>
<hr>
<p>Lorem ipsum...</p>
<hr>
<p>Lorem ipsum...</p>
If you have opened the page in one of the modern browsers, e.g. Firefox, Opera or Safari, you can see the intended result. The paragraphs are separated by three „quarterfoils“, which I borrowed from Marek Prokop. But – if you used Internet Explorer, and it doesn't care which version (yes, including IE7!), you can see some kind of border around the <hr> element even thought I've set border: none in the stylesheet for it.
At this moment are both Marek Prokop and Petr Václavek concordantly shoulder-shrugging. They say the solution doesn't exist.
That's how I imagine the previous attempts to solve the problem ended. Maybe someone took a look round the Internet and found that there are some unpractical solutions using the clip property (the rule must be absolutely positioned) or filters (the content is reduced to 1×1 px so you can't apply border, background color or texture on the background for the rule). Maybe he used such solution and achieved some kind of Pyrrhic victory, which lacked of elegance and practicalness. So what did I find out?
Maybe you know that Explorer 5.5 has been gifted by brand new zoom property which allows coder to decrease and increase elements on the page. If I tell you that the content border of <hr> has a width of only one pixel and that Internet Explorer is not that bad in rounding, maybe you'll figure it out by yourselves.
All you need is to reduce the line to less than 50% of its width using the zoom property (in fact, the first safe value is 40%) and the width of the border will be rounded down to zero! I'm not going to make it linger – it works. Plus <hr> has one very convenient ability – it keeps its set width whatsoever the zoom is!
The solution could look like this one:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<title>Image on a background of horizontal rule</title>
<style type="text/css">
hr {
border: none;
background: url('image.gif') center center no-repeat;
height: 15px;
}
</style>
<!--[if lte IE 7]>
<style type="text/css">
hr {
background-image: url('four-times-larger-image.gif');
height: 60px;
zoom: 25%;
}
</style>
<![endif]-->
<p>Lorem ipsum...</p>
<hr>
<p>Lorem ipsum...</p>
<hr>
<p>Lorem ipsum...</p>
The second link points to a solution showing that coder is able to further style the horizontal rule which is quite useful in many cases.
This is not perfect way to do it, but personally I think it's the first practical way. The one extra image is worth the effect. I don't know about anybody figuring out the solution before me, but if you do or if you know a better way how to achieve such effect, please use the comments to let me know. Maybe I'll show you how to get rid of unwanted „margin“ round the <hr> element next time, thus how to clear safely without the annoying gap in IE.
Comments are welcome!
Rád bořím mýty a hraju si s kaskádovými styly. Dnes jsem si při čtení dávno zaprášených záložek přečetl u Marka Prokopa a Petra Václavka, že se jim v IE nepodařilo zbavit se otravného borderu kolem prvku <hr> tak, aby mohli na pozadí umístit obrázek nějakého jiného, elegantnějšího oddělovače. Já řešení znám.
Můžete se ptát, co je tak obtížného na splnění bodu jedna. V tom případě se podívejte na ukázku.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<title>Obrázek na pozadí prvku HR</title>
<style type="text/css">
hr {
border: none;
background: url('obrazek.gif') center center no-repeat;
height: 15px;
}
</style>
<p>Lorem ipsum...</p>
<hr>
<p>Lorem ipsum...</p>
<hr>
<p>Lorem ipsum...</p>
Pokud jste ukázku otevřeli v nějakém moderním prohlížeči, například Firefoxu, Opeře či Safari, vidíte zamýšlený výsledek. Odstavce jsou odděleny třemi čtyřlísky, které jsem si vypůjčil od Marka Prokopa. Pokud jste však použili libovolnou verzi Internet Exploreru (ano, včetně IE7!), vidíte kolem ornamentu okraje čáry i přes to, že pro prvek <hr> jsem ve stylopisu nastavil border: none;
V tomto okamžiku svorně krčí rameny jak Marek Prokop, tak Petr Václavek. Prý řešení neexistuje.
Takhle nějak si představuji, že skončily veškeré předchozí pokusy. Možná se ještě někdo porozhlédl po internetu a zjistil, že existují nepraktická řešení využívající CSS vlastnosti clip (čára musí být absolutně pozicovaná) nebo filtrů (obsah redukován na 1×1 pixel, nelze tedy na čáru například aplikovat border, background-color nebo opakovat vzorek na pozadí). Možná tato řešení použil a dosáhl tak nejvýš pyrrhova vítězství, které však postrádalo eleganci či praktičnost. Co jsem tedy vymyslel já?
Stačí pomocí vlastnosti zoom zmenšit čáru na méně než polovinu (v praxi je nejvyšší funkční hodnota 40% původní velikosti) a šířka rámečku kolem obsahu se zaokrouhlí na nulu. Nebudu vás napínat – funguje to. <hr> má navíc jednu příhodnou vlastnost – ať už ji zoomnete jakkoliv, vždy zachovává nastavenou šířku!
Výsledek by mohl vypadat nějak takto:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<title>Obrázek na pozadí prvku HR</title>
<style type="text/css">
hr {
border: none;
background: url('obrazek.gif') center center no-repeat;
height: 15px;
}
</style>
<!--[if lte IE 7]>
<style type="text/css">
hr {
background-image: url('ctyrnasobne-velky-obrazek.gif');
height: 60px;
zoom: 25%;
}
</style>
<![endif]-->
<p>Lorem ipsum...</p>
<hr>
<p>Lorem ipsum...</p>
<hr>
<p>Lorem ipsum...</p>
Druhý odkaz ukazuje, že moje řešení dává kodérovi možnost s takto nastylovanou čárou dále pracovat a upravovat ji.
Není to úplně ideální způsob, ale osobně jej pokládám za první opravdu použitelný – ten jeden obrázek navíc mně osobně za ten efekt stojí. Nejsem si vědom toho, že by na něco podobného přišel někdo přede mnou, ale pokud tomu tak opravdu je – nebo pokud znáte lepší a čistější řešení – prosím, odkažte na ně v komentářích. Příště vám možná ukážu, jak se v IE zbavit toho otravného marginu-nemarginu nad a pod čárou a jak tedy clearovat bez zbytečného vertikálního rozestupu.
Komentáře k tématu vítány.
Při tvorbě složitějších javascriptových aplikací občas potřebujete vrátit všechny elementy na stránce. V jedné své aplikaci jsem (v polospánku, rauši či jiném podobném hnutí mysli) použil tuto nebezpečnou konstrukci:
prvky = document.all ? document.all : document.getElementsByTagName('*');
Co hůř, připadlo mi to jako schůdné řešení, instinkty mlčely. Praxe však ukázala své drápky o den později, když jsem aplikace testoval v různých prohlížečích. Deset jich prošlo, ten jedenáctý – Opera 9 – nikoliv. Zkušení javascripteři už si poklepávají na čelo a pro Ty méně zkušené přicházím s vysvětlením.
Ve výše uvedeném kódu testuji prohlížeč na podporu kolekce document.all, kterou představil Internet Explorer ve své čtvrté verzi a kterou také převzali mnohé konkurenční prohlížeče. Tato kolekce má obsahovat všechny prvky na stránce, ale její chování není nikterak závazně popsáno, tzn. ve specifikaci DOM ji nenajdete.
Přesto tuto kolekci podporují všechny tři nejrozšířenější
prohlížeče – Explorer, Mozilla/Firefox i Opera. Zatímco podpora
u Mozilly je tichá, dotaz if (document.all)
vrací hodnotu
false
, Opera se k podpoře kolekce document.all hrdě hlásí.
To znamená, že v Opeře se do proměnné prvky
v příkladu nahoře uloží prvky obsažené právě v kolekci
document.all. Zde je kámen úrazu.
Opera 9 je důsledná a v této kolekci obsahuje nejen všechny elementy (HTML, HEAD, META, SCRIPT, BODY, P atd.), ale i anonymní textové uzly. Pokud se vyznáte v DOM, víte, o čem mluvím. Pro ostatní drobné zjednodušení – tyto textové uzly se vytvoří všude tam, kde daný element obsahuje libovolná textová data. V elementu <script> jde například o zdrojový kód skriptu, v elementu <p> o text odstavce atd. Takové uzly jsou jiného typu než uzly elementů a nelze s nimi pracovat stejným způsobem, například nenabývají žádné hodnoty metody tagName, která běžně vrací jméno elementu.
Vy však chcete vrátit pouze elementy, textové uzly vás nejspíše nezajímají, proto je vám podobná kolekce k ničemu. Chcete Opeře podstrčit druhý zápis, ten s hvězdičkou a standardní metodou getElementsByTagName. Tady jsem chyboval, když jsem tuto metodu nepoužil jako výchozí. Myslel jsem až příliš na Explorer do verze 5.5, který zápis s hvězdičkou (která říká, že chci vybrat všechny elementy, jedno jakého jména) nedokázal zpracovat. Přitom se nabízí mnohem bezpečnější zápis, a to:
prvky = document.getElementsByTagName('*').length > 0 ? document.getElementsByTagName('*') : document.all;
A to je celé kouzlo.
(Pro pokročilé javascriptaře a pro úplnost dodávám, že při práci s XML dokumenty či fragmenty dokumentů se tato metoda může krutě vymstít a skončit kritickou chybou v prohlížečích, které volání document.all vůbec neznají, v případě, že budeme pracovat s prázdným dokumentem či jeho zlomkem. V takovém případě je jedinou cestou pečlivé testování podpory jednotlivých metod a navrácených výsledků.)