<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ars Longa, Vita Brevis &#187; HTML</title>
	<atom:link href="http://blog.sjinks.pro/tag/html/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.sjinks.pro</link>
	<description>Quod scripsi, scripsi</description>
	<lastBuildDate>Mon, 06 Feb 2012 17:56:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>HTML Parser для Qt</title>
		<link>http://blog.sjinks.pro/c-cpp/qt/942-html-parser-qt/</link>
		<comments>http://blog.sjinks.pro/c-cpp/qt/942-html-parser-qt/#comments</comments>
		<pubDate>Wed, 07 Sep 2011 08:03:07 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[Qt]]></category>
		<category><![CDATA[C/C++]]></category>
		<category><![CDATA[DOM]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/?p=942</guid>
		<description><![CDATA[Использование libxml2 для разбора документов HTML в Qt XML — это, конечно, хорошо, но очень часто требуется разбирать документы HTML, которые могут и не быть валидными. В Qt есть множество классов для работы с XML, но они не подходят для HTML, так как ошибки в HTML для них фатальны. Ниже приведён вариант парсера для HTML, основанный на [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/c-cpp/qt/942-html-parser-qt/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Использование libxml2 для разбора документов <a href="http://blog.sjinks.pro/tag/html/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  HTML">HTML</a> в <a href="http://blog.sjinks.pro/tag/qt/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  Qt">Qt</a></em></h2>
<p><a href="http://blog.sjinks.pro/tag/xml/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  XML">XML</a> — это, конечно, хорошо, но очень часто требуется разбирать документы HTML, которые могут и не быть валидными.</p>
<p>В Qt есть множество классов для работы с XML, но они не подходят для HTML, так как ошибки в HTML для них фатальны.</p>
<p>Ниже приведён вариант парсера для HTML, основанный на библиотеке libxml2.<span id="more-942"></span></p>
          
<div class="codebox">
    <div class="the_code" style="" id="p9425">
        <div class="code cpp-qt" id="p942code5">
<span class="co2">#ifndef LIBXML2READER_H</span><br />
<span class="co2">#define LIBXML2READER_H</span><br />
<br />
<span class="co2">#include &lt;QtXml/QXmlReader&gt;</span><br />
<span class="co2">#include &lt;libxml/xmlstring.h&gt;</span><br />
<br />
<span class="kw2">class</span> LibXml2ReaderPrivate<span class="sy0">;</span><br />
<br />
<span class="kw2">class</span> LibXml2Reader <span class="sy0">:</span> <span class="kw2">public</span> <span class="kw5">QXmlReader</span> <span class="br0">&#123;</span><br />
<span class="kw2">public</span><span class="sy0">:</span><br />
&nbsp; &nbsp; LibXml2Reader<span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> ~LibXml2Reader<span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">bool</span> feature<span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw5">QString</span><span class="sy0">&amp;</span> name<span class="sy0">,</span> <span class="kw4">bool</span><span class="sy0">*</span> ok <span class="sy0">=</span> 0<span class="br0">&#41;</span> const<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">void</span> setFeature<span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw5">QString</span><span class="sy0">&amp;</span> name<span class="sy0">,</span> <span class="kw4">bool</span> value<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">bool</span> hasFeature<span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw5">QString</span><span class="sy0">&amp;</span> name<span class="br0">&#41;</span> const<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">void</span><span class="sy0">*</span> property<span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw5">QString</span><span class="sy0">&amp;</span> name<span class="sy0">,</span> <span class="kw4">bool</span><span class="sy0">*</span> ok <span class="sy0">=</span> 0<span class="br0">&#41;</span> const<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">void</span> setProperty<span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw5">QString</span><span class="sy0">&amp;</span> name<span class="sy0">,</span> <span class="kw4">void</span><span class="sy0">*</span> value<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">bool</span> hasProperty<span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw5">QString</span><span class="sy0">&amp;</span> name<span class="br0">&#41;</span> const<span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">void</span> setEntityResolver<span class="br0">&#40;</span><span class="kw5">QXmlEntityResolver</span><span class="sy0">*</span> handler<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw5">QXmlEntityResolver</span><span class="sy0">*</span> entityResolver<span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span> const<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">void</span> setDTDHandler<span class="br0">&#40;</span><span class="kw5">QXmlDTDHandler</span><span class="sy0">*</span> handler<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw5">QXmlDTDHandler</span><span class="sy0">*</span> DTDHandler<span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span> const<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">void</span> setContentHandler<span class="br0">&#40;</span><span class="kw5">QXmlContentHandler</span><span class="sy0">*</span> handler<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw5">QXmlContentHandler</span><span class="sy0">*</span> contentHandler<span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span> const<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">void</span> setErrorHandler<span class="br0">&#40;</span><span class="kw5">QXmlErrorHandler</span><span class="sy0">*</span> handler<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw5">QXmlErrorHandler</span><span class="sy0">*</span> errorHandler<span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span> const<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">void</span> setLexicalHandler<span class="br0">&#40;</span><span class="kw5">QXmlLexicalHandler</span><span class="sy0">*</span> handler<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw5">QXmlLexicalHandler</span><span class="sy0">*</span> lexicalHandler<span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span> const<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">void</span> setDeclHandler<span class="br0">&#40;</span><span class="kw5">QXmlDeclHandler</span><span class="sy0">*</span> handler<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw5">QXmlDeclHandler</span><span class="sy0">*</span> declHandler<span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span> const<span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">bool</span> parse<span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw5">QXmlInputSource</span><span class="sy0">&amp;</span> input<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">bool</span> parse<span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw5">QXmlInputSource</span><span class="sy0">*</span> input<span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
<br />
<span class="kw2">private</span><span class="sy0">:</span><br />
&nbsp; &nbsp; Q_DISABLE_COPY<span class="br0">&#40;</span>LibXml2Reader<span class="br0">&#41;</span><br />
&nbsp; &nbsp; Q_DECLARE_PRIVATE<span class="br0">&#40;</span>LibXml2Reader<span class="br0">&#41;</span><br />
&nbsp; &nbsp; QScopedPointer<span class="sy0">&lt;</span>LibXml2ReaderPrivate<span class="sy0">&gt;</span> d_ptr<span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw2">friend</span> <span class="kw2">class</span> LibXml2ReaderLocator<span class="sy0">;</span><br />
<span class="br0">&#125;</span><span class="sy0">;</span><br />
<br />
<span class="co2">#endif // LIBXML2READER_H</span>
        </div>
    </div>
</div>

          
<div class="codebox">
    <div class="the_code" style="" id="p9426">
        <div class="code cpp-qt" id="p942code6">
<span class="co2">#include &quot;libxml2reader.h&quot;</span><br />
<span class="co2">#include &lt;cstring&gt;</span><br />
<span class="co2">#include &lt;libxml/tree.h&gt;</span><br />
<span class="co2">#include &lt;libxml/parser.h&gt;</span><br />
<span class="co2">#include &lt;libxml/HTMLparser.h&gt;</span><br />
<br />
<span class="kw2">class</span> LibXml2ReaderLocator <span class="sy0">:</span> <span class="kw2">public</span> <span class="kw5">QXmlLocator</span> <span class="br0">&#123;</span><br />
<span class="kw2">public</span><span class="sy0">:</span><br />
&nbsp; &nbsp; LibXml2ReaderLocator<span class="br0">&#40;</span>LibXml2Reader<span class="sy0">*</span> r<span class="br0">&#41;</span> <span class="sy0">:</span> reader<span class="br0">&#40;</span>r<span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">int</span> columnNumber<span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span> const<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">virtual</span> <span class="kw4">int</span> lineNumber<span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span> const<span class="sy0">;</span><br />
<span class="kw2">private</span><span class="sy0">:</span><br />
&nbsp; &nbsp; LibXml2Reader<span class="sy0">*</span> reader<span class="sy0">;</span><br />
<span class="br0">&#125;</span><span class="sy0">;</span><br />
<br />
<span class="kw2">class</span> LibXml2ReaderPrivate <span class="br0">&#123;</span><br />
<span class="kw2">public</span><span class="sy0">:</span><br />
&nbsp; &nbsp; ~LibXml2ReaderPrivate<span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
<span class="kw2">private</span><span class="sy0">:</span><br />
&nbsp; &nbsp; LibXml2ReaderPrivate<span class="br0">&#40;</span>LibXml2Reader<span class="sy0">*</span> reader<span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw4">static</span> <span class="kw4">void</span> startDocument<span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw4">static</span> <span class="kw4">void</span> endDocument<span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw4">static</span> <span class="kw4">void</span> startElement<span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> name<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">**</span> attrs<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw4">static</span> <span class="kw4">void</span> endElement<span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> name<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw4">static</span> <span class="kw4">void</span> comment<span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> value<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw4">static</span> <span class="kw4">void</span> cdataBlock<span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> value<span class="sy0">,</span> <span class="kw4">int</span> len<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw4">static</span> <span class="kw4">void</span> processingInstruction<span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> target<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> data<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw4">static</span> <span class="kw4">void</span> characters<span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> ch<span class="sy0">,</span> <span class="kw4">int</span> len<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw4">static</span> <span class="kw4">void</span> ignorableWhitespace<span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> ch<span class="sy0">,</span> <span class="kw4">int</span> len<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw4">static</span> <span class="kw4">void</span> internalSubset<span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> name<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> publicId<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> systemId<span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw4">void</span> parse<span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw5">QXmlInputSource</span><span class="sy0">*</span> input<span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; QScopedPointer<span class="sy0">&lt;</span>LibXml2ReaderLocator<span class="sy0">&gt;</span> locator<span class="sy0">;</span><br />
&nbsp; &nbsp; Q_DECLARE_PUBLIC<span class="br0">&#40;</span>LibXml2Reader<span class="br0">&#41;</span><br />
&nbsp; &nbsp; LibXml2Reader<span class="sy0">*</span> q_ptr<span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw5">QXmlEntityResolver</span><span class="sy0">*</span> entityresolver<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw5">QXmlDTDHandler</span><span class="sy0">*</span> &nbsp; &nbsp; dtdhandler<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw5">QXmlContentHandler</span><span class="sy0">*</span> contenthandler<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw5">QXmlErrorHandler</span><span class="sy0">*</span> &nbsp; errorhandler<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw5">QXmlLexicalHandler</span><span class="sy0">*</span> lexicalhandler<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw5">QXmlDeclHandler</span><span class="sy0">*</span> &nbsp; &nbsp;declhandler<span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; xmlParserCtxt<span class="sy0">*</span> context<span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw2">friend</span> <span class="kw2">class</span> LibXml2ReaderLocator<span class="sy0">;</span><br />
<span class="br0">&#125;</span><span class="sy0">;</span><br />
<br />
LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">LibXml2ReaderPrivate</span><span class="br0">&#40;</span>LibXml2Reader<span class="sy0">*</span> reader<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="sy0">:</span> q_ptr<span class="br0">&#40;</span>reader<span class="br0">&#41;</span><span class="sy0">,</span> entityresolver<span class="br0">&#40;</span>0<span class="br0">&#41;</span><span class="sy0">,</span> dtdhandler<span class="br0">&#40;</span>0<span class="br0">&#41;</span><span class="sy0">,</span> contenthandler<span class="br0">&#40;</span>0<span class="br0">&#41;</span><span class="sy0">,</span> errorhandler<span class="br0">&#40;</span>0<span class="br0">&#41;</span><span class="sy0">,</span> lexicalhandler<span class="br0">&#40;</span>0<span class="br0">&#41;</span><span class="sy0">,</span> declhandler<span class="br0">&#40;</span>0<span class="br0">&#41;</span><span class="sy0">,</span> context<span class="br0">&#40;</span>0<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; this<span class="sy0">-&gt;</span><span class="me3">locator</span>.<span class="me1">reset</span><span class="br0">&#40;</span><span class="kw1">new</span> LibXml2ReaderLocator<span class="br0">&#40;</span>reader<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">parse</span><span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw5">QXmlInputSource</span><span class="sy0">*</span> input<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; htmlSAXHandler handler<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw5">QByteArray</span> arr <span class="sy0">=</span> input<span class="sy0">-&gt;</span><span class="me3">data</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">toLocal8Bit</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span><span class="sy0">*</span> data <span class="sy0">=</span> arr.<span class="me1">data</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; std<span class="sy0">::</span><span class="kw3">memset</span><span class="br0">&#40;</span><span class="sy0">&amp;</span>handler<span class="sy0">,</span> 0<span class="sy0">,</span> <span class="kw3">sizeof</span><span class="br0">&#40;</span>handler<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; handler.<span class="me1">startDocument</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">=</span> <span class="sy0">&amp;</span>LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">startDocument</span><span class="sy0">;</span><br />
&nbsp; &nbsp; handler.<span class="me1">endDocument</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">=</span> <span class="sy0">&amp;</span>LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">endDocument</span><span class="sy0">;</span><br />
&nbsp; &nbsp; handler.<span class="me1">startElement</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy0">=</span> <span class="sy0">&amp;</span>LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">startElement</span><span class="sy0">;</span><br />
&nbsp; &nbsp; handler.<span class="me1">endElement</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy0">=</span> <span class="sy0">&amp;</span>LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">endElement</span><span class="sy0">;</span><br />
&nbsp; &nbsp; handler.<span class="me1">comment</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">=</span> <span class="sy0">&amp;</span>LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">comment</span><span class="sy0">;</span><br />
&nbsp; &nbsp; handler.<span class="me1">cdataBlock</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy0">=</span> <span class="sy0">&amp;</span>LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">cdataBlock</span><span class="sy0">;</span><br />
&nbsp; &nbsp; handler.<span class="me1">processingInstruction</span> <span class="sy0">=</span> <span class="sy0">&amp;</span>LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">processingInstruction</span><span class="sy0">;</span><br />
&nbsp; &nbsp; handler.<span class="me1">characters</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy0">=</span> <span class="sy0">&amp;</span>LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">characters</span><span class="sy0">;</span><br />
&nbsp; &nbsp; handler.<span class="me1">ignorableWhitespace</span> &nbsp; <span class="sy0">=</span> <span class="sy0">&amp;</span>LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">ignorableWhitespace</span><span class="sy0">;</span><br />
&nbsp; &nbsp; handler.<span class="me1">internalSubset</span> &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy0">=</span> <span class="sy0">&amp;</span>LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">internalSubset</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; this<span class="sy0">-&gt;</span><span class="me3">context</span> <span class="sy0">=</span> htmlCreatePushParserCtxt<span class="br0">&#40;</span><span class="sy0">&amp;</span>handler<span class="sy0">,</span> <span class="kw1">this</span><span class="sy0">,</span> data<span class="sy0">,</span> xmlStrlen<span class="br0">&#40;</span><span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span><span class="kw4">const</span> xmlChar<span class="sy0">*&gt;</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="st0">&quot;&quot;</span><span class="sy0">,</span> XML_CHAR_ENCODING_NONE<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; htmlParseChunk<span class="br0">&#40;</span>this<span class="sy0">-&gt;</span><span class="me3">context</span><span class="sy0">,</span> <span class="kw2">NULL</span><span class="sy0">,</span> 0<span class="sy0">,</span> 1<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; htmlFreeParserCtxt<span class="br0">&#40;</span>this<span class="sy0">-&gt;</span><span class="me3">context</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; xmlCleanupParser<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">startDocument</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; LibXml2ReaderPrivate<span class="sy0">*</span> r <span class="sy0">=</span> <span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span>LibXml2ReaderPrivate<span class="sy0">*&gt;</span><span class="br0">&#40;</span>c<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>r<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; r<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="sy0">-&gt;</span><span class="me3">startDocument</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">endDocument</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; LibXml2ReaderPrivate<span class="sy0">*</span> r <span class="sy0">=</span> <span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span>LibXml2ReaderPrivate<span class="sy0">*&gt;</span><span class="br0">&#40;</span>c<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>r<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; r<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="sy0">-&gt;</span><span class="me3">endDocument</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">startElement</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> name<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">**</span> attrs<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; LibXml2ReaderPrivate<span class="sy0">*</span> r <span class="sy0">=</span> <span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span>LibXml2ReaderPrivate<span class="sy0">*&gt;</span><span class="br0">&#40;</span>c<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>r<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw5">QXmlAttributes</span> a<span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">int</span> i <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>attrs<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span>attrs<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span><span class="sy0">*</span> name &nbsp;<span class="sy0">=</span> <span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span><span class="kw4">const</span> <span class="kw4">char</span><span class="sy0">*&gt;</span><span class="br0">&#40;</span>attrs<span class="br0">&#91;</span>i<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw4">const</span> <span class="kw4">char</span><span class="sy0">*</span> value <span class="sy0">=</span> <span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span><span class="kw4">const</span> <span class="kw4">char</span><span class="sy0">*&gt;</span><span class="br0">&#40;</span>attrs<span class="br0">&#91;</span>i<span class="sy0">+</span>1<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; i <span class="sy0">+=</span> <span class="nu0">2</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; a.<span class="me1">append</span><span class="br0">&#40;</span>name<span class="sy0">,</span> <span class="st0">&quot;&quot;</span><span class="sy0">,</span> <span class="st0">&quot;&quot;</span><span class="sy0">,</span> value ? value <span class="sy0">:</span> name<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw5">QString</span> uri <span class="sy0">=</span> <span class="st0">&quot;&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw5">QString</span> localName <span class="sy0">=</span> <span class="st0">&quot;&quot;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw5">QString</span> qName <span class="sy0">=</span> <span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span><span class="kw4">const</span> <span class="kw4">char</span><span class="sy0">*&gt;</span><span class="br0">&#40;</span>name<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; r<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="sy0">-&gt;</span><span class="me3">startElement</span><span class="br0">&#40;</span>uri<span class="sy0">,</span> localName<span class="sy0">,</span> qName<span class="sy0">,</span> a<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">endElement</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> name<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; LibXml2ReaderPrivate<span class="sy0">*</span> r <span class="sy0">=</span> <span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span>LibXml2ReaderPrivate<span class="sy0">*&gt;</span><span class="br0">&#40;</span>c<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>r<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; r<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="sy0">-&gt;</span><span class="me3">endElement</span><span class="br0">&#40;</span><span class="kw5">QString</span><span class="br0">&#40;</span><span class="st0">&quot;&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw5">QString</span><span class="br0">&#40;</span><span class="st0">&quot;&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw5">QString</span><span class="br0">&#40;</span><span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span><span class="kw4">const</span> <span class="kw4">char</span><span class="sy0">*&gt;</span><span class="br0">&#40;</span>name<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">comment</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> value<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; LibXml2ReaderPrivate<span class="sy0">*</span> r <span class="sy0">=</span> <span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span>LibXml2ReaderPrivate<span class="sy0">*&gt;</span><span class="br0">&#40;</span>c<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>r<span class="sy0">-&gt;</span><span class="me3">lexicalhandler</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; r<span class="sy0">-&gt;</span><span class="me3">lexicalhandler</span><span class="sy0">-&gt;</span><span class="me3">comment</span><span class="br0">&#40;</span><span class="kw5">QString</span><span class="sy0">::</span><span class="me2">fromLocal8Bit</span><span class="br0">&#40;</span><span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span><span class="kw4">const</span> <span class="kw4">char</span><span class="sy0">*&gt;</span><span class="br0">&#40;</span>value<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">cdataBlock</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> value<span class="sy0">,</span> <span class="kw4">int</span> len<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; LibXml2ReaderPrivate<span class="sy0">*</span> r <span class="sy0">=</span> <span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span>LibXml2ReaderPrivate<span class="sy0">*&gt;</span><span class="br0">&#40;</span>c<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>r<span class="sy0">-&gt;</span><span class="me3">lexicalhandler</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; r<span class="sy0">-&gt;</span><span class="me3">lexicalhandler</span><span class="sy0">-&gt;</span><span class="me3">startCDATA</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>r<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw5">QByteArray</span> arr<span class="br0">&#40;</span><span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span><span class="kw4">const</span> <span class="kw4">char</span><span class="sy0">*&gt;</span><span class="br0">&#40;</span>value<span class="br0">&#41;</span><span class="sy0">,</span> len<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="sy0">-&gt;</span><span class="me3">characters</span><span class="br0">&#40;</span>arr<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; r<span class="sy0">-&gt;</span><span class="me3">lexicalhandler</span><span class="sy0">-&gt;</span><span class="me3">endCDATA</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">processingInstruction</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> target<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> data<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; LibXml2ReaderPrivate<span class="sy0">*</span> r <span class="sy0">=</span> <span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span>LibXml2ReaderPrivate<span class="sy0">*&gt;</span><span class="br0">&#40;</span>c<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>r<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; r<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="sy0">-&gt;</span><span class="me3">processingInstruction</span><span class="br0">&#40;</span><span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span><span class="kw4">const</span> <span class="kw4">char</span><span class="sy0">*&gt;</span><span class="br0">&#40;</span>target<span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span><span class="kw4">const</span> <span class="kw4">char</span><span class="sy0">*&gt;</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">characters</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> ch<span class="sy0">,</span> <span class="kw4">int</span> len<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; LibXml2ReaderPrivate<span class="sy0">*</span> r <span class="sy0">=</span> <span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span>LibXml2ReaderPrivate<span class="sy0">*&gt;</span><span class="br0">&#40;</span>c<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>r<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; r<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="sy0">-&gt;</span><span class="me3">characters</span><span class="br0">&#40;</span><span class="kw5">QString</span><span class="sy0">::</span><span class="me2">fromLocal8Bit</span><span class="br0">&#40;</span><span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span><span class="kw4">const</span> <span class="kw4">char</span><span class="sy0">*&gt;</span><span class="br0">&#40;</span>ch<span class="br0">&#41;</span><span class="sy0">,</span> len<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">ignorableWhitespace</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> ch<span class="sy0">,</span> <span class="kw4">int</span> len<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; LibXml2ReaderPrivate<span class="sy0">*</span> r <span class="sy0">=</span> <span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span>LibXml2ReaderPrivate<span class="sy0">*&gt;</span><span class="br0">&#40;</span>c<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>r<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; r<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="sy0">-&gt;</span><span class="me3">ignorableWhitespace</span><span class="br0">&#40;</span><span class="kw5">QString</span><span class="sy0">::</span><span class="me2">fromLocal8Bit</span><span class="br0">&#40;</span><span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span><span class="kw4">const</span> <span class="kw4">char</span><span class="sy0">*&gt;</span><span class="br0">&#40;</span>ch<span class="br0">&#41;</span><span class="sy0">,</span> len<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2ReaderPrivate<span class="sy0">::</span><span class="me2">internalSubset</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="sy0">*</span> c<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> name<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> publicId<span class="sy0">,</span> <span class="kw4">const</span> xmlChar<span class="sy0">*</span> systemId<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; LibXml2ReaderPrivate<span class="sy0">*</span> r <span class="sy0">=</span> <span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span>LibXml2ReaderPrivate<span class="sy0">*&gt;</span><span class="br0">&#40;</span>c<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>r<span class="sy0">-&gt;</span><span class="me3">lexicalhandler</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw5">QString</span> n<span class="br0">&#40;</span><span class="kw5">QString</span><span class="sy0">::</span><span class="me2">fromLocal8Bit</span><span class="br0">&#40;</span><span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span><span class="kw4">const</span> <span class="kw4">char</span><span class="sy0">*&gt;</span><span class="br0">&#40;</span>name<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw5">QString</span> p<span class="br0">&#40;</span><span class="kw5">QString</span><span class="sy0">::</span><span class="me2">fromLocal8Bit</span><span class="br0">&#40;</span><span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span><span class="kw4">const</span> <span class="kw4">char</span><span class="sy0">*&gt;</span><span class="br0">&#40;</span>publicId<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw5">QString</span> s<span class="br0">&#40;</span><span class="kw5">QString</span><span class="sy0">::</span><span class="me2">fromLocal8Bit</span><span class="br0">&#40;</span><span class="kw2">reinterpret_cast</span><span class="sy0">&lt;</span><span class="kw4">const</span> <span class="kw4">char</span><span class="sy0">*&gt;</span><span class="br0">&#40;</span>systemId<span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; r<span class="sy0">-&gt;</span><span class="me3">lexicalhandler</span><span class="sy0">-&gt;</span><span class="me3">startDTD</span><span class="br0">&#40;</span>n<span class="sy0">,</span> p<span class="sy0">,</span> s<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; r<span class="sy0">-&gt;</span><span class="me3">lexicalhandler</span><span class="sy0">-&gt;</span><span class="me3">endDTD</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
<span class="br0">&#125;</span><br />
<br />
LibXml2Reader<span class="sy0">::</span><span class="me2">LibXml2Reader</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="sy0">:</span> d_ptr<span class="br0">&#40;</span><span class="kw1">new</span> LibXml2ReaderPrivate<span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
<span class="br0">&#125;</span><br />
<br />
LibXml2Reader<span class="sy0">::</span><span class="me2">~LibXml2Reader</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">bool</span> LibXml2Reader<span class="sy0">::</span><span class="me2">feature</span><span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw5">QString</span><span class="sy0">&amp;,</span> <span class="kw4">bool</span><span class="sy0">*</span> ok<span class="br0">&#41;</span> <span class="kw4">const</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>ok<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">*</span>ok <span class="sy0">=</span> false<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; <span class="kw1">return</span> false<span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2Reader<span class="sy0">::</span><span class="me2">setFeature</span><span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw5">QString</span><span class="sy0">&amp;,</span> <span class="kw4">bool</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">bool</span> LibXml2Reader<span class="sy0">::</span><span class="me2">hasFeature</span><span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw5">QString</span><span class="sy0">&amp;</span><span class="br0">&#41;</span> <span class="kw4">const</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> false<span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span><span class="sy0">*</span> LibXml2Reader<span class="sy0">::</span><span class="me2">property</span><span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw5">QString</span><span class="sy0">&amp;,</span> <span class="kw4">bool</span><span class="sy0">*</span> ok<span class="br0">&#41;</span> <span class="kw4">const</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>ok<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">*</span>ok <span class="sy0">=</span> false<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="nu0">0</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2Reader<span class="sy0">::</span><span class="me2">setProperty</span><span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw5">QString</span><span class="sy0">&amp;,</span> <span class="kw4">void</span><span class="sy0">*</span><span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">bool</span> LibXml2Reader<span class="sy0">::</span><span class="me2">hasProperty</span><span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw5">QString</span><span class="sy0">&amp;</span><span class="br0">&#41;</span> <span class="kw4">const</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> false<span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2Reader<span class="sy0">::</span><span class="me2">setEntityResolver</span><span class="br0">&#40;</span><span class="kw5">QXmlEntityResolver</span><span class="sy0">*</span> handler<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; Q_D<span class="br0">&#40;</span>LibXml2Reader<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; d<span class="sy0">-&gt;</span><span class="me3">entityresolver</span> <span class="sy0">=</span> handler<span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw5">QXmlEntityResolver</span><span class="sy0">*</span> LibXml2Reader<span class="sy0">::</span><span class="me2">entityResolver</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span> <span class="kw4">const</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">const</span> LibXml2ReaderPrivate<span class="sy0">*</span> d <span class="sy0">=</span> this<span class="sy0">-&gt;</span><span class="me3">d_func</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> d<span class="sy0">-&gt;</span><span class="me3">entityresolver</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2Reader<span class="sy0">::</span><span class="me2">setDTDHandler</span><span class="br0">&#40;</span><span class="kw5">QXmlDTDHandler</span><span class="sy0">*</span> handler<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; Q_D<span class="br0">&#40;</span>LibXml2Reader<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; d<span class="sy0">-&gt;</span><span class="me3">dtdhandler</span> <span class="sy0">=</span> handler<span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw5">QXmlDTDHandler</span><span class="sy0">*</span> LibXml2Reader<span class="sy0">::</span><span class="me2">DTDHandler</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span> <span class="kw4">const</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">const</span> LibXml2ReaderPrivate<span class="sy0">*</span> d <span class="sy0">=</span> this<span class="sy0">-&gt;</span><span class="me3">d_func</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> d<span class="sy0">-&gt;</span><span class="me3">dtdhandler</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2Reader<span class="sy0">::</span><span class="me2">setContentHandler</span><span class="br0">&#40;</span><span class="kw5">QXmlContentHandler</span><span class="sy0">*</span> handler<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; Q_D<span class="br0">&#40;</span>LibXml2Reader<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; d<span class="sy0">-&gt;</span><span class="me3">contenthandler</span> <span class="sy0">=</span> handler<span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw5">QXmlContentHandler</span><span class="sy0">*</span> LibXml2Reader<span class="sy0">::</span><span class="me2">contentHandler</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span> <span class="kw4">const</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">const</span> LibXml2ReaderPrivate<span class="sy0">*</span> d <span class="sy0">=</span> this<span class="sy0">-&gt;</span><span class="me3">d_func</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> d<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2Reader<span class="sy0">::</span><span class="me2">setErrorHandler</span><span class="br0">&#40;</span><span class="kw5">QXmlErrorHandler</span><span class="sy0">*</span> handler<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; Q_D<span class="br0">&#40;</span>LibXml2Reader<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; d<span class="sy0">-&gt;</span><span class="me3">errorhandler</span> <span class="sy0">=</span> handler<span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw5">QXmlErrorHandler</span><span class="sy0">*</span> LibXml2Reader<span class="sy0">::</span><span class="me2">errorHandler</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span> <span class="kw4">const</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">const</span> LibXml2ReaderPrivate<span class="sy0">*</span> d <span class="sy0">=</span> this<span class="sy0">-&gt;</span><span class="me3">d_func</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> d<span class="sy0">-&gt;</span><span class="me3">errorhandler</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2Reader<span class="sy0">::</span><span class="me2">setLexicalHandler</span><span class="br0">&#40;</span><span class="kw5">QXmlLexicalHandler</span><span class="sy0">*</span> handler<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; Q_D<span class="br0">&#40;</span>LibXml2Reader<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; d<span class="sy0">-&gt;</span><span class="me3">lexicalhandler</span> <span class="sy0">=</span> handler<span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw5">QXmlLexicalHandler</span><span class="sy0">*</span> LibXml2Reader<span class="sy0">::</span><span class="me2">lexicalHandler</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span> <span class="kw4">const</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">const</span> LibXml2ReaderPrivate<span class="sy0">*</span> d <span class="sy0">=</span> this<span class="sy0">-&gt;</span><span class="me3">d_func</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> d<span class="sy0">-&gt;</span><span class="me3">lexicalhandler</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">void</span> LibXml2Reader<span class="sy0">::</span><span class="me2">setDeclHandler</span><span class="br0">&#40;</span><span class="kw5">QXmlDeclHandler</span><span class="sy0">*</span> handler<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; Q_D<span class="br0">&#40;</span>LibXml2Reader<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; d<span class="sy0">-&gt;</span><span class="me3">declhandler</span> <span class="sy0">=</span> handler<span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw5">QXmlDeclHandler</span><span class="sy0">*</span> LibXml2Reader<span class="sy0">::</span><span class="me2">declHandler</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span> <span class="kw4">const</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw4">const</span> LibXml2ReaderPrivate<span class="sy0">*</span> d <span class="sy0">=</span> this<span class="sy0">-&gt;</span><span class="me3">d_func</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> d<span class="sy0">-&gt;</span><span class="me3">declhandler</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">bool</span> LibXml2Reader<span class="sy0">::</span><span class="me2">parse</span><span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw5">QXmlInputSource</span><span class="sy0">&amp;</span> input<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> this<span class="sy0">-&gt;</span><span class="me3">parse</span><span class="br0">&#40;</span><span class="sy0">&amp;</span>input<span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">bool</span> LibXml2Reader<span class="sy0">::</span><span class="me2">parse</span><span class="br0">&#40;</span><span class="kw4">const</span> <span class="kw5">QXmlInputSource</span><span class="sy0">*</span> input<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; Q_D<span class="br0">&#40;</span>LibXml2Reader<span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>d<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; d<span class="sy0">-&gt;</span><span class="me3">contenthandler</span><span class="sy0">-&gt;</span><span class="me3">setDocumentLocator</span><span class="br0">&#40;</span>d<span class="sy0">-&gt;</span><span class="me3">locator</span>.<span class="me1">data</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; d<span class="sy0">-&gt;</span><span class="me3">parse</span><span class="br0">&#40;</span>input<span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw1">return</span> true<span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">int</span> LibXml2ReaderLocator<span class="sy0">::</span><span class="me2">columnNumber</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span> <span class="kw4">const</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> this<span class="sy0">-&gt;</span><span class="me3">reader</span><span class="sy0">-&gt;</span><span class="me3">d_func</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me3">context</span><span class="sy0">-&gt;</span><span class="me3">input</span><span class="sy0">-&gt;</span><span class="me3">col</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="kw4">int</span> LibXml2ReaderLocator<span class="sy0">::</span><span class="me2">lineNumber</span><span class="br0">&#40;</span><span class="kw4">void</span><span class="br0">&#41;</span> <span class="kw4">const</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> this<span class="sy0">-&gt;</span><span class="me3">reader</span><span class="sy0">-&gt;</span><span class="me3">d_func</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me3">context</span><span class="sy0">-&gt;</span><span class="me3">input</span><span class="sy0">-&gt;</span><span class="me3">line</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p>Использование:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p9427">
        <div class="code cpp-qt" id="p942code7">
&nbsp; &nbsp; <span class="kw5">QByteArray</span> data<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw5">QXmlInputSource</span> src<span class="sy0">;</span><br />
&nbsp; &nbsp; LibXml2Reader reader<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw5">QDomDocument</span> doc<span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="coMULTI">/* здесь читаем данные в data */</span><br />
<br />
&nbsp; &nbsp; src.<span class="me1">setData</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; doc.<span class="me1">setContent</span><span class="br0">&#40;</span><span class="sy0">&amp;</span>src<span class="sy0">,</span> <span class="sy0">&amp;</span>reader<span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="coMULTI">/* doc будет содержать дерево DOM, построенное из документа HTML */</span>
        </div>
    </div>
</div>

<p>В файл проекта нужно будет добавить две строки:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p9428">
        <div class="code text" id="p942code8">
INCLUDEPATH += /usr/include/libxml2<br />
LIBS &nbsp; &nbsp; &nbsp; &nbsp;+= -lxml2
        </div>
    </div>
</div>

<p>В <code>INCLUDEPATH</code> помещается путь к заголовочным файлам libxml2, в <code>LIBS</code> — опции компилятора для подключения библиотеки libxml2.</p>
<p>Скачать:</p>
<ul>
<li><a href='http://static.sjinks.info/wp-content/uploads/2011/09/libxml2reader.h'>libxml2reader.h</a></li>
<li><a href='http://static.sjinks.info/wp-content/uploads/2011/09/libxml2reader.cpp'>libxml2reader.cpp</a></li>
</ul>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/c-cpp/qt/942-html-parser-qt/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/c-cpp/qt/942-html-parser-qt/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>KSES в WordPress: можно ли проще?</title>
		<link>http://blog.sjinks.pro/wordpress/894-kses-wordpress-could-it-be-simplier/</link>
		<comments>http://blog.sjinks.pro/wordpress/894-kses-wordpress-could-it-be-simplier/#comments</comments>
		<pubDate>Thu, 10 Feb 2011 06:07:09 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[KSES]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[производительность]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/?p=894</guid>
		<description><![CDATA[Регулярные выражения против DOM XML Вчера мне довелось разбираться с тем, как работает KSES в WordPress. KSES (рекурсивный акроним от KSES Strips Evil Scripts) — подсистема в WordPress (изначально написанная Ulf Harnhammar), предназначенная для проверки и очистки текста, введённого пользователем: она позволяет задать список допустимых тэгов, стилей и протоколов и на основе этих параметров убрать из текста [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/wordpress/894-kses-wordpress-could-it-be-simplier/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Регулярные выражения против <a href="http://blog.sjinks.pro/tag/dom/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  DOM">DOM</a> <a href="http://blog.sjinks.pro/tag/xml/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  XML">XML</a></em></h2>
<p>Вчера мне довелось разбираться с тем, как работает <a href="http://blog.sjinks.pro/tag/kses/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  KSES">KSES</a> в <a href="http://blog.sjinks.pro/tag/wordpress/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  WordPress">WordPress</a>.</p>
<p>KSES (рекурсивный акроним от KSES Strips Evil Scripts) — подсистема в WordPress (изначально написанная Ulf Harnhammar), предназначенная для проверки и очистки текста, введённого пользователем: она позволяет задать список допустимых тэгов, стилей и протоколов и на основе этих параметров убрать из текста пользователя всё, что им не соответствует.</p>
<p>KSES является довольно стабильной подсистемой; что немаловажно, KSES <em>работает</em>. Работает —  не трогай, а то сломаешь…<span id="more-894"></span></p>
<p>Лично мне в KSES не нравится использование регулярных выражений. Одна из причин — теория разработки компиляторов. Известно, что <a href="http://blog.sjinks.pro/tag/html/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  HTML">HTML</a> — это грамматика второго типа в иерархии Хомского (контекстно-свободная грамматика), а регулярные выражения — грамматика третьего типа (регулярная грамматика). Грамматика второго типа является более сложной, нежели грамматика третьего типа. Как следствие, описать более простой грамматикой то, что соответствует более сложной, очень трудно (вряд ли возможно на 100%, но это моё мнение).</p>
<p>Что плохо, среди <a href="http://codex.wordpress.org/Automated_Testing">тестов WordPress</a> я не нашёл тестов для KSES. Что может означать, что, вероятно, никто из разработчиков не строил и не проверял граф путей в KSES; как следствие, не гарантии, что при граничных условиях всё будет работать нормально.</p>
<p>Другая причина, по которой я не люблю регулярные выражения — это скорость: особой производительностью они не отличаются. Хотя с другой стороны, объёмы проверяемого текста не так велики, чтобы KSES оказывал существенное влияние на <a href="http://blog.sjinks.pro/tag/performance/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  производительность">производительность</a>.</p>
<p>Каковы альтернативы? <a href="http://htmlpurifier.org/comparison">Обзор</a>.</p>
<p>На <em>мой</em> взгляд, самая удобная альтернатива — использование DOM XML и работа с полученным деревом. Тем более, что в <a href="http://blog.sjinks.pro/tag/php/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  PHP">PHP</a> есть соответствующая поддержка. А парсер на C в любом случае быстрее парсера на <a href="http://blog.sjinks.pro/tag/php/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  PHP">PHP</a>.</p>
<p>Парсер DOM XML в PHP позволяет работать даже с некорректным HTML. Что означает, что он берёт на себя решение проблемы с неправильно закрытыми или незакрытыми тэгами. Парсер понимает HTML entities и преобразует их в нормальный текст. Что означает, что не нужно возиться с разными форматами записи entities и переводить их к одному виду (чему в KSES уделено не мало кода). И так далее.</p>
<p>Для проверки некоторых идей я написал небольшой класс, который делает <em>почти</em> то же самое, что и KSES, только иначе <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Я ни в коем случае не рассматриваю его как замену KSES.</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p89410">
        <div class="code php" id="p894code10">
<span class="kw2">&lt;?php</span><br />
&nbsp; &nbsp; <span class="kw2">class</span> Xex<br />
&nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">private</span> <span class="re0">$protocols</span> <span class="sy0">=</span> <span class="kw1">array</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">private</span> <span class="re0">$tags</span> &nbsp; &nbsp; &nbsp;<span class="sy0">=</span> <span class="kw1">array</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">private</span> <span class="re0">$css</span> &nbsp; &nbsp; &nbsp; <span class="sy0">=</span> <span class="kw1">array</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">private</span> <span class="re0">$strip_comments</span> &nbsp; &nbsp;<span class="sy0">=</span> <span class="kw4">true</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">private</span> <span class="re0">$strip_script_text</span> <span class="sy0">=</span> <span class="kw4">true</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">private</span> <span class="re0">$strip_style_text</span> &nbsp;<span class="sy0">=</span> <span class="kw4">true</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">private</span> <span class="re0">$script_text</span> <span class="sy0">=</span> <span class="kw4">true</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">private</span> <span class="re0">$style_text</span> &nbsp;<span class="sy0">=</span> <span class="kw4">true</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">private</span> <span class="re0">$trim_text</span> <span class="sy0">=</span> <span class="kw4">false</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> __construct<span class="br0">&#40;</span><span class="kw1">array</span> <span class="re0">$tags</span> <span class="sy0">=</span> <span class="kw4">null</span><span class="sy0">,</span> <span class="kw1">array</span> <span class="re0">$protocols</span> <span class="sy0">=</span> <span class="kw4">null</span><span class="sy0">,</span> <span class="kw1">array</span> <span class="re0">$css</span> <span class="sy0">=</span> <span class="kw4">null</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw4">null</span> <span class="sy0">!==</span> <span class="re0">$tags</span><span class="br0">&#41;</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">tags</span> <span class="sy0">=</span> <span class="re0">$tags</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw4">null</span> <span class="sy0">!==</span> <span class="re0">$protocols</span><span class="br0">&#41;</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">protocols</span> <span class="sy0">=</span> <span class="kw3">array_combine</span><span class="br0">&#40;</span><span class="re0">$protocols</span><span class="sy0">,</span> <span class="re0">$protocols</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw4">null</span> <span class="sy0">!==</span> <span class="re0">$css</span><span class="br0">&#41;</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">css</span> <span class="sy0">=</span> <span class="kw3">array_combine</span><span class="br0">&#40;</span><span class="re0">$css</span><span class="sy0">,</span> <span class="re0">$css</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">protected</span> <span class="kw2">function</span> checkProtocols<span class="br0">&#40;</span><span class="re0">$str</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$s</span> <span class="sy0">=</span> <span class="kw3">str_replace</span><span class="br0">&#40;</span><span class="kw1">array</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es1">\r</span>&quot;</span><span class="sy0">,</span> <span class="st0">&quot;<span class="es1">\n</span>&quot;</span><span class="sy0">,</span> <span class="st0">&quot;<span class="es1">\t</span>&quot;</span><span class="sy0">,</span> <span class="st0">&quot;&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="st_h">''</span><span class="sy0">,</span> <span class="re0">$str</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$s</span> <span class="sy0">=</span> <span class="kw3">explode</span><span class="br0">&#40;</span><span class="st_h">':'</span><span class="sy0">,</span> <span class="re0">$s</span><span class="sy0">,</span> 2<span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// See http://tools.ietf.org/html/rfc3986#section-3.1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">preg_match</span><span class="br0">&#40;</span><span class="st_h">'/^[a-z][a-z0-9+.-]*$/'</span><span class="sy0">,</span> <span class="re0">$s</span><span class="br0">&#91;</span>0<span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="sy0">&amp;&amp;</span> <span class="sy0">!</span><span class="kw1">isset</span><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">protocols</span><span class="br0">&#91;</span><span class="re0">$s</span><span class="br0">&#91;</span>0<span class="br0">&#93;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="st_h">''</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$str</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">protected</span> <span class="kw2">function</span> sanitizeCss<span class="br0">&#40;</span><span class="re0">$css</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$css</span> <span class="sy0">=</span> <span class="kw3">str_replace</span><span class="br0">&#40;</span><span class="kw1">array</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es1">\n</span>&quot;</span><span class="sy0">,</span><span class="st0">&quot;<span class="es1">\r</span>&quot;</span><span class="sy0">,</span><span class="st0">&quot;<span class="es1">\t</span>&quot;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="st_h">''</span><span class="sy0">,</span> <span class="re0">$css</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">preg_match</span><span class="br0">&#40;</span><span class="st_h">'![\\(&amp;=}]|/\\*!'</span><span class="sy0">,</span> <span class="re0">$css</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="st_h">''</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$arr</span> <span class="sy0">=</span> <span class="kw3">explode</span><span class="br0">&#40;</span><span class="st_h">';'</span><span class="sy0">,</span> <span class="kw3">trim</span><span class="br0">&#40;</span><span class="re0">$css</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$css</span> <span class="sy0">=</span> <span class="st_h">''</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$arr</span> <span class="kw1">as</span> <span class="re0">$x</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$x</span> <span class="sy0">=</span> <span class="kw3">trim</span><span class="br0">&#40;</span><span class="re0">$x</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$x</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$found</span> <span class="sy0">=</span> <span class="kw4">false</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw4">false</span> <span class="sy0">===</span> <span class="kw3">strpos</span><span class="br0">&#40;</span><span class="re0">$x</span><span class="sy0">,</span> <span class="st_h">':'</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$found</span> <span class="sy0">=</span> <span class="kw4">true</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$parts</span> <span class="sy0">=</span> <span class="kw3">explode</span><span class="br0">&#40;</span><span class="st_h">':'</span><span class="sy0">,</span> <span class="re0">$x</span><span class="sy0">,</span> 2<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">isset</span><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">css</span><span class="br0">&#91;</span><span class="kw3">rtrim</span><span class="br0">&#40;</span><span class="re0">$parts</span><span class="br0">&#91;</span>0<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$found</span> <span class="sy0">=</span> <span class="kw4">true</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$found</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$css</span> <span class="sy0">.=</span> <span class="re0">$x</span> <span class="sy0">.</span> <span class="st_h">';'</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$css</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">protected</span> <span class="kw2">function</span> parseDOM<span class="br0">&#40;</span>DOMNode <span class="re0">$el</span><span class="sy0">,</span> DOMNode <span class="re0">$new</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">switch</span> <span class="br0">&#40;</span><span class="re0">$el</span><span class="sy0">-&gt;</span><span class="me1">nodeType</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> XML_ELEMENT_NODE<span class="sy0">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$prefix</span> <span class="sy0">=</span> <span class="re0">$el</span><span class="sy0">-&gt;</span><span class="me1">prefix</span> ? <span class="br0">&#40;</span><span class="re0">$el</span><span class="sy0">-&gt;</span><span class="me1">prefix</span> <span class="sy0">.</span> <span class="st_h">':'</span><span class="br0">&#41;</span> <span class="sy0">:</span> <span class="st_h">''</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$tag</span> &nbsp; &nbsp;<span class="sy0">=</span> <span class="re0">$prefix</span> <span class="sy0">.</span> <span class="re0">$el</span><span class="sy0">-&gt;</span><span class="me1">tagName</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw1">isset</span><span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">tags</span><span class="br0">&#91;</span><span class="re0">$tag</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$n</span> <span class="sy0">=</span> <span class="re0">$new</span><span class="sy0">-&gt;</span><span class="me1">appendChild</span><span class="br0">&#40;</span><span class="re0">$el</span><span class="sy0">-&gt;</span><span class="me1">cloneNode</span><span class="br0">&#40;</span><span class="kw4">false</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$el</span><span class="sy0">-&gt;</span><span class="me1">hasAttributes</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$attrs</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">tags</span><span class="br0">&#91;</span><span class="re0">$tag</span><span class="br0">&#93;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$el</span><span class="sy0">-&gt;</span><span class="me1">attributes</span> <span class="kw1">as</span> <span class="re0">$a</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="kw1">isset</span><span class="br0">&#40;</span><span class="re0">$attrs</span><span class="br0">&#91;</span><span class="re0">$a</span><span class="sy0">-&gt;</span><span class="me1">name</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$n</span><span class="sy0">-&gt;</span><span class="me1">removeAttribute</span><span class="br0">&#40;</span><span class="re0">$a</span><span class="sy0">-&gt;</span><span class="me1">name</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">elseif</span> <span class="br0">&#40;</span><span class="st_h">'style'</span> <span class="sy0">==</span> <span class="re0">$a</span><span class="sy0">-&gt;</span><span class="me1">name</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$css</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">sanitizeCss</span><span class="br0">&#40;</span><span class="re0">$a</span><span class="sy0">-&gt;</span><span class="me1">value</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$css</span> <span class="sy0">!=</span> <span class="re0">$a</span><span class="sy0">-&gt;</span><span class="me1">value</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$n</span><span class="sy0">-&gt;</span><span class="me1">setAttribute</span><span class="br0">&#40;</span><span class="re0">$a</span><span class="sy0">-&gt;</span><span class="me1">name</span><span class="sy0">,</span> <span class="re0">$css</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">elseif</span> <span class="br0">&#40;</span><span class="kw3">in_array</span><span class="br0">&#40;</span><span class="re0">$a</span><span class="sy0">-&gt;</span><span class="me1">name</span><span class="sy0">,</span> <span class="kw1">array</span><span class="br0">&#40;</span><span class="st_h">'xmlns'</span><span class="sy0">,</span> <span class="st_h">'profile'</span><span class="sy0">,</span> <span class="st_h">'href'</span><span class="sy0">,</span> <span class="st_h">'src'</span><span class="sy0">,</span> <span class="st_h">'cite'</span><span class="sy0">,</span> <span class="st_h">'classid'</span><span class="sy0">,</span> <span class="st_h">'codebase'</span><span class="sy0">,</span> <span class="st_h">'data'</span><span class="sy0">,</span> <span class="st_h">'usemap'</span><span class="sy0">,</span> <span class="st_h">'longdesc'</span><span class="sy0">,</span> <span class="st_h">'action'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$s</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">checkProtocols</span><span class="br0">&#40;</span><span class="re0">$a</span><span class="sy0">-&gt;</span><span class="me1">value</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$s</span> <span class="sy0">!=</span> <span class="re0">$a</span><span class="sy0">-&gt;</span><span class="me1">value</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$n</span><span class="sy0">-&gt;</span><span class="me1">setAttribute</span><span class="br0">&#40;</span><span class="re0">$a</span><span class="sy0">-&gt;</span><span class="me1">name</span><span class="sy0">,</span> <span class="re0">$s</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$tag</span> <span class="sy0">==</span> <span class="st_h">'script'</span> <span class="sy0">&amp;&amp;</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">strip_script_text</span> <span class="sy0">||</span> <span class="re0">$tag</span> <span class="sy0">==</span> <span class="st_h">'style'</span> <span class="sy0">&amp;&amp;</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">strip_style_text</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$n</span> <span class="sy0">=</span> <span class="re0">$new</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$el</span><span class="sy0">-&gt;</span><span class="me1">hasChildNodes</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$el</span><span class="sy0">-&gt;</span><span class="me1">childNodes</span> <span class="kw1">as</span> <span class="re0">$e</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">parseDOM</span><span class="br0">&#40;</span><span class="re0">$e</span><span class="sy0">,</span> <span class="re0">$n</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> XML_TEXT_NODE<span class="sy0">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">trim_text</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$new</span><span class="sy0">-&gt;</span><span class="me1">appendChild</span><span class="br0">&#40;</span><span class="re0">$el</span><span class="sy0">-&gt;</span><span class="me1">cloneNode</span><span class="br0">&#40;</span><span class="kw4">true</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$new</span><span class="sy0">-&gt;</span><span class="me1">appendChild</span><span class="br0">&#40;</span><span class="kw2">new</span> DOMText<span class="br0">&#40;</span><span class="kw3">trim</span><span class="br0">&#40;</span><span class="re0">$el</span><span class="sy0">-&gt;</span><span class="me1">wholeText</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> XML_CDATA_SECTION_NODE<span class="sy0">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$new</span><span class="sy0">-&gt;</span><span class="me1">appendChild</span><span class="br0">&#40;</span><span class="re0">$el</span><span class="sy0">-&gt;</span><span class="me1">cloneNode</span><span class="br0">&#40;</span><span class="kw4">true</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">case</span> XML_COMMENT_NODE<span class="sy0">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$parent</span> <span class="sy0">=</span> <span class="re0">$el</span><span class="sy0">-&gt;</span><span class="me1">parentNode</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$parent</span> <span class="sy0">&amp;&amp;</span> <span class="re0">$parent</span><span class="sy0">-&gt;</span><span class="me1">tagName</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$prefix</span> <span class="sy0">=</span> <span class="re0">$parent</span><span class="sy0">-&gt;</span><span class="me1">prefix</span> ? <span class="br0">&#40;</span><span class="re0">$parent</span><span class="sy0">-&gt;</span><span class="me1">prefix</span> <span class="sy0">.</span> <span class="st_h">':'</span><span class="br0">&#41;</span> <span class="sy0">:</span> <span class="st_h">''</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$tag</span> &nbsp; &nbsp;<span class="sy0">=</span> <span class="re0">$prefix</span> <span class="sy0">.</span> <span class="re0">$parent</span><span class="sy0">-&gt;</span><span class="me1">tagName</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="st_h">'style'</span> <span class="sy0">==</span> <span class="re0">$tag</span> <span class="sy0">&amp;&amp;</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">style_text</span> <span class="sy0">||</span> <span class="st_h">'script'</span> <span class="sy0">==</span> <span class="re0">$tag</span> <span class="sy0">&amp;&amp;</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">script_text</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$new</span><span class="sy0">-&gt;</span><span class="me1">appendChild</span><span class="br0">&#40;</span><span class="kw2">new</span> DOMText<span class="br0">&#40;</span><span class="re0">$el</span><span class="sy0">-&gt;</span><span class="me1">data</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">strip_comments</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$new</span><span class="sy0">-&gt;</span><span class="me1">appendChild</span><span class="br0">&#40;</span><span class="re0">$el</span><span class="sy0">-&gt;</span><span class="me1">cloneNode</span><span class="br0">&#40;</span><span class="kw4">true</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">default</span><span class="sy0">:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">break</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">public</span> <span class="kw2">function</span> sanitize<span class="br0">&#40;</span><span class="re0">$s</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$dom</span> <span class="sy0">=</span> <span class="kw2">new</span> DOMDocument<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$dom</span><span class="sy0">-&gt;</span><span class="me1">recover</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">=</span> <span class="kw4">true</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$dom</span><span class="sy0">-&gt;</span><span class="me1">strictErrorChecking</span> <span class="sy0">=</span> <span class="kw4">false</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$dom</span><span class="sy0">-&gt;</span><span class="me1">substituteEntities</span> &nbsp;<span class="sy0">=</span> <span class="kw4">true</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$dom</span><span class="sy0">-&gt;</span><span class="me1">resolveExternals</span> &nbsp; &nbsp;<span class="sy0">=</span> <span class="kw4">false</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$dom</span><span class="sy0">-&gt;</span><span class="me1">formatOutput</span> &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy0">=</span> <span class="kw4">false</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$old</span> <span class="sy0">=</span> <span class="kw3">libxml_use_internal_errors</span><span class="br0">&#40;</span><span class="kw4">true</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$s</span> <span class="sy0">=</span> <span class="kw3">str_replace</span><span class="br0">&#40;</span><span class="kw3">chr</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="st_h">''</span><span class="sy0">,</span> <span class="re0">$s</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$s</span> <span class="sy0">=</span> <span class="kw3">preg_replace</span><span class="br0">&#40;</span><span class="st_h">'!&lt;([^a-z\\?\\!/])!i'</span><span class="sy0">,</span> <span class="st_h">'&amp;lt;$1'</span><span class="sy0">,</span> <span class="re0">$s</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$s</span> <span class="sy0">=</span> <span class="kw3">preg_replace</span><span class="br0">&#40;</span><span class="st_h">'!&lt;((?:[\\?\\!/]\\s*)?[a-z][^&gt;]*)(?=&lt;)!i'</span><span class="sy0">,</span> <span class="st_h">'&amp;lt;$1'</span><span class="sy0">,</span> <span class="re0">$s</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sy0">@</span><span class="re0">$dom</span><span class="sy0">-&gt;</span><span class="me1">loadHTML</span><span class="br0">&#40;</span><span class="re0">$s</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">libxml_use_internal_errors</span><span class="br0">&#40;</span><span class="re0">$old</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$new</span> <span class="sy0">=</span> <span class="re0">$dom</span><span class="sy0">-&gt;</span><span class="me1">createDocumentFragment</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$new</span><span class="sy0">-&gt;</span><span class="me1">appendChild</span><span class="br0">&#40;</span><span class="kw2">new</span> DOMElement<span class="br0">&#40;</span><span class="st_h">'wrap'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">parseDOM</span><span class="br0">&#40;</span><span class="re0">$dom</span><span class="sy0">-&gt;</span><span class="me1">documentElement</span><span class="sy0">,</span> <span class="re0">$new</span><span class="sy0">-&gt;</span><span class="me1">firstChild</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$dom</span><span class="sy0">-&gt;</span><span class="me1">replaceChild</span><span class="br0">&#40;</span><span class="re0">$new</span><span class="sy0">,</span> <span class="re0">$dom</span><span class="sy0">-&gt;</span><span class="me1">documentElement</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$s</span> <span class="sy0">=</span> <span class="re0">$dom</span><span class="sy0">-&gt;</span><span class="me1">saveXML</span><span class="br0">&#40;</span><span class="re0">$dom</span><span class="sy0">-&gt;</span><span class="me1">documentElement</span><span class="sy0">,</span> LIBXML_NOEMPTYTAG<span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">substr</span><span class="br0">&#40;</span><span class="re0">$s</span><span class="sy0">,</span> <span class="kw3">strpos</span><span class="br0">&#40;</span><span class="re0">$s</span><span class="sy0">,</span> <span class="st_h">'&lt;wrap&gt;'</span><span class="br0">&#41;</span> <span class="sy0">+</span> 6<span class="sy0">,</span> <span class="sy0">-</span>7<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="sy1">?&gt;</span>
        </div>
    </div>
</div>

<p>Менее 200 строк против почти полутора тысяч.</p>
<p>На 45-килобайтном документе DOM быстрее KSES от 5 до 9 раз.<br />
На 90-килобайтном документе DOM быстрее KSES от 6 до 9 раз.<br />
На 180-килобайтном документе DOM быстрее KSES от 9 до 10 раз.</p>
<p>Производительность зависит от количества тэгов и стилей (разбор стилей реализован практически одинаково). Например, на домашней странице Google XEX может опережать KSES в 25 раз; если же соединить домашнюю страницу Google саму с собой 4 раза, разница во времени сокращается.</p>
<p>На домашней странице WordPress разница в 7 раз.</p>
<p>На <a href="http://blog.sjinks.pro/test/accordion/accordion1.html">этой странице</a> разница в 4 раза.</p>
<p>Всё-таки KSES очень медленный…</p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/wordpress/894-kses-wordpress-could-it-be-simplier/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/wordpress/894-kses-wordpress-could-it-be-simplier/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>Генерация карты сайта в HTML из XML</title>
		<link>http://blog.sjinks.pro/seo/847-html-stemap-generation-from-xml/</link>
		<comments>http://blog.sjinks.pro/seo/847-html-stemap-generation-from-xml/#comments</comments>
		<pubDate>Sun, 07 Nov 2010 01:22:20 +0000</pubDate>
		<dc:creator>Wandering Soul</dc:creator>
				<category><![CDATA[SEO]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[XML]]></category>
		<category><![CDATA[XSL]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/?p=847</guid>
		<description><![CDATA[Помогаем ботам найти все страница сайта Проблема: есть достаточно большой сайт, у которого есть карта в формате XML. Есть бот, который этот сайт индексирует. Но бот не может найти страницы, имеющие уровень вложенности больше трёх. Нужно помочь боту проиндексировать весь сайт. Самый простой способ — создание страницы, в которой будут перечислены все страницы сайта и размещение на [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/seo/847-html-stemap-generation-from-xml/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Помогаем ботам найти все страница сайта</em></h2>
<p><strong>Проблема:</strong> есть достаточно большой сайт, у которого есть <a href="/sitemap.xml">карта в формате XML</a>. Есть бот, который этот сайт индексирует. Но бот не может найти страницы, имеющие уровень вложенности больше трёх. Нужно помочь боту проиндексировать весь сайт.</p>
<p>Самый простой способ — создание страницы, в которой будут перечислены все страницы сайта и размещение на неё ссылки из подвала сайта. Идеальный кандидат на такую страницу — карта сайта в формате <a href="http://blog.sjinks.pro/tag/xml/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  XML">XML</a>. Проблема в том, что не все боты утруждают себя разбором <a href="http://blog.sjinks.pro/tag/xml/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  XML">XML</a>-карт. Для таких ботов карту нужно преобразовывать в формат <a href="http://blog.sjinks.pro/tag/html/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  HTML">HTML</a>.<span id="more-847"></span></p>
<p>Как и в <a href="http://blog.sjinks.pro/linux/722-transform-sitemap-to-siege-url-list/">другом похожем случае</a>, на помощь приходит преобразование <a href="http://blog.sjinks.pro/tag/xsl/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  XSL">XSL</a>.</p>
<p>Пример шаблона стилей XML:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p84713">
        <div class="code xml" id="p847code13">
<span class="sc3"><span class="re1">&lt;?xml</span> <span class="re0">version</span>=<span class="st0">&quot;1.0&quot;</span> <span class="re0">encoding</span>=<span class="st0">&quot;utf-8&quot;</span><span class="re2">?&gt;</span></span><br />
<span class="sc3"><span class="re1">&lt;xsl:stylesheet</span> <span class="re0">version</span>=<span class="st0">&quot;1.0&quot;</span> <span class="re0">xmlns:xsl</span>=<span class="st0">&quot;http://www.w3.org/1999/XSL/Transform&quot;</span> <span class="re0">xmlns:x</span>=<span class="st0">&quot;http://www.sitemaps.org/schemas/sitemap/0.9&quot;</span> <span class="re0">xmlns</span>=<span class="st0">&quot;http://www.w3.org/1999/xhtml&quot;</span> <span class="re0">exclude-result-prefixes</span>=<span class="st0">&quot;x&quot;</span><span class="re2">&gt;</span></span><br />
&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;xsl:output</span> <span class="re0">method</span>=<span class="st0">&quot;xml&quot;</span> <span class="re0">indent</span>=<span class="st0">&quot;yes&quot;</span> <span class="re0">encoding</span>=<span class="st0">&quot;UTF-8&quot;</span> <span class="re0">doctype-public</span>=<span class="st0">&quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;</span> <span class="re0">doctype-system</span>=<span class="st0">&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;</span><span class="re2">/&gt;</span></span><br />
&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;xsl:strip-space</span> <span class="re0">elements</span>=<span class="st0">&quot;*&quot;</span><span class="re2">/&gt;</span></span><br />
<br />
&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;xsl:template</span> <span class="re0">match</span>=<span class="st0">&quot;/x:urlset&quot;</span><span class="re2">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;html<span class="re2">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;head<span class="re2">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;meta</span> <span class="re0">http-equiv</span>=<span class="st0">&quot;Content-Type&quot;</span> <span class="re0">content</span>=<span class="st0">&quot;text/html; charset=utf-8&quot;</span><span class="re2">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;title<span class="re2">&gt;</span></span></span>Site Map<span class="sc3"><span class="re1">&lt;/title<span class="re2">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/head<span class="re2">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;body<span class="re2">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;h1<span class="re2">&gt;</span></span><span class="re1">&lt;a</span> <span class="re0">href</span>=<span class="st0">&quot;http://blog.sjinks.pro/&quot;</span><span class="re2">&gt;</span></span>Карта сайта<span class="sc3"><span class="re1">&lt;/a<span class="re2">&gt;</span></span><span class="re1">&lt;/h1<span class="re2">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;ul<span class="re2">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;xsl:apply-templates</span> <span class="re0">select</span>=<span class="st0">&quot;x:url&quot;</span><span class="re2">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;xsl:sort</span> <span class="re0">select</span>=<span class="st0">&quot;lastmod&quot;</span> <span class="re0">order</span>=<span class="st0">&quot;descending&quot;</span><span class="re2">/&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/xsl:apply-templates<span class="re2">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/ul<span class="re2">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/body<span class="re2">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/html<span class="re2">&gt;</span></span></span><br />
&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/xsl:template<span class="re2">&gt;</span></span></span><br />
<br />
&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;xsl:template</span> <span class="re0">match</span>=<span class="st0">&quot;/x:urlset/x:url&quot;</span><span class="re2">&gt;</span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;li<span class="re2">&gt;</span></span><span class="re1">&lt;strong<span class="re2">&gt;</span></span><span class="re1">&lt;a</span> <span class="re0">href</span>=<span class="st0">&quot;{x:loc}&quot;</span><span class="re2">&gt;</span><span class="re1">&lt;xsl:value-of</span> <span class="re0">select</span>=<span class="st0">&quot;x:loc&quot;</span> <span class="re0">disable-output-escaping</span>=<span class="st0">&quot;yes&quot;</span><span class="re2">/&gt;</span><span class="re1">&lt;/a<span class="re2">&gt;</span></span><span class="re1">&lt;/strong<span class="re2">&gt;</span></span><span class="re1">&lt;xsl:if</span> <span class="re0">test</span>=<span class="st0">&quot;x:lastmod&quot;</span><span class="re2">&gt;</span></span> (<span class="sc3"><span class="re1">&lt;xsl:value-of</span> <span class="re0">select</span>=<span class="st0">&quot;x:lastmod&quot;</span> <span class="re0">disable-output-escaping</span>=<span class="st0">&quot;yes&quot;</span><span class="re2">/&gt;</span></span>)<span class="sc3"><span class="re1">&lt;/xsl:if<span class="re2">&gt;</span></span><span class="re1">&lt;/li<span class="re2">&gt;</span></span></span><br />
&nbsp; &nbsp; <span class="sc3"><span class="re1">&lt;/xsl:template<span class="re2">&gt;</span></span></span><br />
<span class="sc3"><span class="re1">&lt;/xsl:stylesheet<span class="re2">&gt;</span></span></span>
        </div>
    </div>
</div>

<p>Преобразование выполняется так:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p84714">
        <div class="code bash" id="p847code14">
xsltproc <span class="re5">-o</span> <span class="sy0">/</span>path<span class="sy0">/</span>to<span class="sy0">/</span>sitemap.html <span class="sy0">/</span>path<span class="sy0">/</span>to<span class="sy0">/</span>sitemap2html.xml <span class="sy0">/</span>path<span class="sy0">/</span>to<span class="sy0">/</span>sitemap.xml
        </div>
    </div>
</div>

<p>Можно выполнение <code>xsltproc</code> повесить на крон и наслаждаться результатом.</p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/seo/847-html-stemap-generation-from-xml/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/seo/847-html-stemap-generation-from-xml/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Создание отражения рисунка с помощью JavaScript</title>
		<link>http://blog.sjinks.pro/javascript/356-image-reflection-with-javascript/</link>
		<comments>http://blog.sjinks.pro/javascript/356-image-reflection-with-javascript/#comments</comments>
		<pubDate>Sun, 16 Nov 2008 22:12:36 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[canvas]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[эффекты]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/?p=356</guid>
		<description><![CDATA[HTML 5 приходит на помощь Постановка задачи: из исходного изображения получить отраженное изображение: Дополнительное условие: генерировать изображение на стороне клиента (то есть без использования GD, ImageMagick и иже с ними). В черновике стандарта HTML&#160;5 пристутствует такой замечательный элемент как &#60;canvas&#62;. Если вкратце, то данный элемент предназначен для создания изображений при помощи JavaScript. Впервые элемент &#60;canvas&#62; [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/javascript/356-image-reflection-with-javascript/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em><a href="http://blog.sjinks.pro/tag/html/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  HTML">HTML</a> 5 приходит на помощь</em></h2>
<p><strong>Постановка задачи:</strong> из исходного изображения </p>
<p><img src="http://static.sjinks.info/wp-content/uploads/2008/11/source.png" alt="Исходное изображение" title="Исходное изображение" width="363" height="240" class="alignnone size-full wp-image-357" /></p>
<p>получить отраженное изображение:</p>
<p><img src="http://static.sjinks.info/wp-content/uploads/2008/11/dest.png" alt="Исходное изображение с отражением" title="Исходное изображение с отражением" width="363" height="476" class="alignnone size-full wp-image-358" /></p>
<p><strong>Дополнительное условие:</strong> генерировать изображение на стороне клиента (то есть без использования GD, ImageMagick и иже с ними).<span id="more-356"></span></p>
<p>В черновике стандарта HTML&nbsp;5 пристутствует такой замечательный элемент как <span class="codebox"><code class="html"><span class="sc2">&lt;canvas&gt;</span></code></span>. Если вкратце, то данный элемент предназначен для создания  изображений при помощи <a href="http://blog.sjinks.pro/tag/javascript/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  JavaScript">JavaScript</a>.</p>
<p>Впервые элемент <span class="codebox"><code class="html"><span class="sc2">&lt;canvas&gt;</span></code></span> был представлен компанией Apple и использовался как компонент WebKit для Mac&nbsp;OS&nbsp;X в таких приложениях как Dashboard и Safari.</p>
<p>Поддержка <span class="codebox"><code class="html"><span class="sc2">&lt;canvas&gt;</span></code></span> в Gecko появилась в версии 1.5, в Presto с версии 9.0 веб-браузера Opera. Текущие версии Internet Explorer (включая восьмую бету) не поддерживают <span class="codebox"><code class="html"><span class="sc2">&lt;canvas&gt;</span></code></span>. Несмотря на это, для поставленной задачи существует <a href="http://blog.sjinks.pro/tag/cross-browser/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  кросс-браузерное решение">кросс-браузерное решение</a>.</p>
<p>В Microsoft Internet Explorer отражения с прозрачностью можно достичь путём использования комбинации фильтров. В частности, для вертикального отражения используется фильтр <code>flipv</code>, для горизонтального&nbsp;&mdash;&nbsp;<code>fliph</code>. Про реализацию прозрачности в Internet Explorer, наверное, знает каждый: <code>progid:DXImageTransform.Microsoft.Alpha</code>. Тем не менее, не все знают, что можно задавать градиентную прозрачность.</p>
<p>Перейдём к решению. Пусть у нас имеется такая <a href="http://blog.sjinks.pro/tag/markup/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  разметка">разметка</a>:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p35618">
        <div class="code html" id="p356code18">
<span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;container&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">img</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;image&quot;</span> <span class="kw3">src</span><span class="sy0">=</span><span class="st0">&quot;image.png&quot;</span> <span class="kw3">alt</span><span class="sy0">=</span><span class="st0">&quot;Image&quot;</span><span class="sy0">/</span>&gt;</span><br />
<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span>
        </div>
    </div>
</div>

<p>Будем полагать, что ширина и высота контейнера заданы (если мы делаем отражение по вертикали, то ширина контейнера совпадает с шириной рисунка, а высота контейнера в два раза больше высоты рисунка; аналогично для горизонтального отражения).</p>
<p>Начнём с классики (MSIE).</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p35619">
        <div class="code javascript" id="p356code19">
<span class="coMULTI">/**<br />
&nbsp;* @param container &lt;div id=&quot;container&quot;&gt;<br />
&nbsp;* @param image &lt;img id=&quot;image&quot;&gt;<br />
&nbsp;* @param ratio Коэффициент сжатия/растягивания отражения<br />
&nbsp;* @param opacity_start Начальная (ближняя к отражаемому изображению) непрозрачность <br />
&nbsp;* @param opacity_end Конечная непрозрачность<br />
&nbsp;* @param horizontal 0 = вертикальное отражение, 1 = горизонтальное отражение<br />
&nbsp;*/</span><br />
<span class="kw2">function</span> reflect_image<span class="br0">&#40;</span>container<span class="sy0">,</span> image<span class="sy0">,</span> ratio<span class="sy0">,</span> opacity_start<span class="sy0">,</span> opacity_end<span class="sy0">,</span> horizontal<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">var</span> reflection &nbsp;<span class="sy0">=</span> document.<span class="me1">createElement</span><span class="br0">&#40;</span><span class="st0">'img'</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; reflection.<span class="me1">src</span> <span class="sy0">=</span> image.<span class="me1">src</span><span class="sy0">;</span><br />
&nbsp; &nbsp; reflection.<span class="me1">style</span>.<span class="me1">width</span> <span class="sy0">=</span> image.<span class="me1">width</span> <span class="sy0">+</span> <span class="st0">'px'</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="nu0">0</span> <span class="sy0">==</span> horizontal<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; reflection.<span class="me1">style</span>.<span class="me1">filter</span> <span class="sy0">=</span> <span class="st0">'flipv progid:DXImageTransform.Microsoft.Alpha(opacity='</span><span class="sy0">+</span><span class="br0">&#40;</span>opacity_start<span class="sy0">*</span><span class="nu0">100</span><span class="br0">&#41;</span><span class="sy0">+</span><span class="st0">', style=1, finishOpacity='</span><span class="sy0">+</span><span class="br0">&#40;</span>opacity_end<span class="sy0">*</span><span class="nu0">100</span><span class="br0">&#41;</span><span class="sy0">+</span><span class="st0">', startx=0, starty=0, finishx=0, finishy='</span><span class="sy0">+</span><span class="br0">&#40;</span>ratio<span class="sy0">*</span><span class="nu0">100</span><span class="br0">&#41;</span><span class="sy0">+</span><span class="st0">')'</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; reflection.<span class="me1">style</span>.<span class="me1">filter</span> <span class="sy0">=</span> <span class="st0">'fliph progid:DXImageTransform.Microsoft.Alpha(opacity='</span><span class="sy0">+</span><span class="br0">&#40;</span>opacity_start<span class="sy0">*</span><span class="nu0">100</span><span class="br0">&#41;</span><span class="sy0">+</span><span class="st0">', style=1, finishOpacity='</span><span class="sy0">+</span><span class="br0">&#40;</span>opacity_end<span class="sy0">*</span><span class="nu0">100</span><span class="br0">&#41;</span><span class="sy0">+</span><span class="st0">', startx=0, starty=0, finishx='</span><span class="sy0">+</span><span class="br0">&#40;</span>ratio<span class="sy0">*</span><span class="nu0">100</span><span class="br0">&#41;</span><span class="sy0">+</span><span class="st0">', finishy=0)'</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; container.<span class="me1">appendChild</span><span class="br0">&#40;</span>reflection<span class="br0">&#41;</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p>В случае с IE всё просто и сводится к заданию соответствующих фильтров. С браузерами, поддерживающими HTML&nbsp;5, всё гораздо сложнее (ad deliberandum: сколько строк занимает программа на C++, если она использует COM-технологию?)</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p35620">
        <div class="code javascript" id="p356code20">
<span class="coMULTI">/**<br />
&nbsp;* @param container &lt;div id=&quot;container&quot;&gt;<br />
&nbsp;* @param image &lt;img id=&quot;image&quot;&gt;<br />
&nbsp;* @param ratio Коэффициент сжатия/растягивания отражения<br />
&nbsp;* @param opacity_start Начальная (ближняя к отражаемому изображению) непрозрачность <br />
&nbsp;* @param opacity_end Конечная непрозрачность<br />
&nbsp;* @param horizontal 0 = вертикальное отражение, 1 = горизонтальное отражение<br />
&nbsp;*/</span><br />
<span class="kw2">function</span> reflect_image<span class="br0">&#40;</span>container<span class="sy0">,</span> image<span class="sy0">,</span> ratio<span class="sy0">,</span> opacity_start<span class="sy0">,</span> opacity_end<span class="sy0">,</span> horizontal<span class="br0">&#41;</span><br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw2">var</span> reflection <span class="sy0">=</span> document.<span class="me1">createElement</span><span class="br0">&#40;</span><span class="st0">'canvas'</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">var</span> context &nbsp; <span class="sy0">=</span> reflection.<span class="me1">getContext</span><span class="br0">&#40;</span><span class="st0">'2d'</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; reflection.<span class="me1">style</span>.<span class="me1">height</span> <span class="sy0">=</span> image.<span class="me1">height</span> <span class="sy0">+</span> <span class="st0">'px'</span><span class="sy0">;</span><br />
&nbsp; &nbsp; reflection.<span class="me1">style</span>.<span class="me1">width</span> &nbsp;<span class="sy0">=</span> image.<span class="me1">width</span> <span class="sy0">+</span> <span class="st0">'px'</span><span class="sy0">;</span><br />
&nbsp; &nbsp; reflection.<span class="me1">height</span> &nbsp; &nbsp; &nbsp; <span class="sy0">=</span> image.<span class="me1">height</span><span class="sy0">;</span><br />
&nbsp; &nbsp; reflection.<span class="me1">width</span> &nbsp; &nbsp; &nbsp; &nbsp;<span class="sy0">=</span> image.<span class="me1">width</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="co1">//Подводный камень: на canvas нельзя рисовать, если она не в DOM-дереве документа</span><br />
&nbsp; &nbsp; container.<span class="me1">appendChild</span><span class="br0">&#40;</span>reflection<span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; context.<span class="me1">save</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw2">var</span> gradient<span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="nu0">0</span> <span class="sy0">==</span> horizontal<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Задаём точку отсчёта, отражаем ось y и создаём вертикальный градиент</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; context.<span class="me1">translate</span><span class="br0">&#40;</span>0<span class="sy0">,</span> image.<span class="me1">height</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; context.<span class="me1">scale</span><span class="br0">&#40;</span>1<span class="sy0">,</span> <span class="sy0">-</span>1<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; gradient <span class="sy0">=</span> context.<span class="me1">createLinearGradient</span><span class="br0">&#40;</span>0<span class="sy0">,</span> 0<span class="sy0">,</span> 0<span class="sy0">,</span> image.<span class="me1">height</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// Задаём точку отсчёта, отражаем ось x и создаём горизонтальный градиент</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; context.<span class="me1">translate</span><span class="br0">&#40;</span>image.<span class="me1">width</span><span class="sy0">,</span> 0<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; context.<span class="me1">scale</span><span class="br0">&#40;</span><span class="sy0">-</span>1<span class="sy0">,</span> 1<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; gradient <span class="sy0">=</span> context.<span class="me1">createLinearGradient</span><span class="br0">&#40;</span>0<span class="sy0">,</span> 0<span class="sy0">,</span> image.<span class="me1">width</span><span class="sy0">,</span> 0<span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<br />
&nbsp; &nbsp; <span class="co1">// Рисуем исходное изображение (оно будет отражено по одной из осей)</span><br />
&nbsp; &nbsp; context.<span class="me1">drawImage</span><span class="br0">&#40;</span>image<span class="sy0">,</span> 0<span class="sy0">,</span> 0<span class="sy0">,</span> image.<span class="me1">width</span><span class="sy0">,</span> image.<span class="me1">height</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; context.<span class="me1">restore</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="co1">// Задаём режим операции</span><br />
&nbsp; &nbsp; context.<span class="me1">globalCompositeOperation</span> <span class="sy0">=</span> <span class="st0">&quot;destination-out&quot;</span><span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="co1">// Параметры градинтной заливки (в параметрах передаётся НЕпрозрачность, нам нужна прозрачность)</span><br />
&nbsp; &nbsp; gradient.<span class="me1">addColorStop</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="sy0">,</span> <span class="st0">&quot;rgba(255, 255, 255, &quot;</span> <span class="sy0">+</span> <span class="br0">&#40;</span><span class="nu0">1</span> <span class="sy0">-</span> opacity_end<span class="br0">&#41;</span> <span class="sy0">+</span> <span class="st0">&quot;)&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; gradient.<span class="me1">addColorStop</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="sy0">,</span> <span class="st0">&quot;rgba(255, 255, 255, &quot;</span> <span class="sy0">+</span> <span class="br0">&#40;</span><span class="nu0">1</span> <span class="sy0">-</span> opacity_start<span class="br0">&#41;</span> <span class="sy0">+</span> <span class="st0">&quot;)&quot;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; context.<span class="me1">fillStyle</span> <span class="sy0">=</span> gradient<span class="sy0">;</span><br />
<br />
&nbsp; &nbsp; <span class="co1">// Заливаем</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">-</span><span class="nu0">1</span> <span class="sy0">!=</span> navigator.<span class="me1">appVersion</span>.<span class="me1">indexOf</span><span class="br0">&#40;</span><span class="st0">'WebKit'</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; context.<span class="me1">fill</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span> <br />
&nbsp; &nbsp; <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; context.<span class="me1">fillRect</span><span class="br0">&#40;</span>0<span class="sy0">,</span> 0<span class="sy0">,</span> image.<span class="me1">width</span><span class="sy0">,</span> image.<span class="me1">height</span><span class="br0">&#41;</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p><strong><a href="http://blog.sjinks.pro/test/reflection/test.html" rel="nofollow">Тестовый пример</a>.</strong></p>
<p><strong><a href="https://developer.mozilla.org/En/Canvas_tutorial" rel="nofollow">Canvas Tutorial в Mozilla Developer Center</a></strong></p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/javascript/356-image-reflection-with-javascript/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/javascript/356-image-reflection-with-javascript/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Пять звёздочек без JavaScript</title>
		<link>http://blog.sjinks.pro/css/173-five-stars-without-javascript/</link>
		<comments>http://blog.sjinks.pro/css/173-five-stars-without-javascript/#comments</comments>
		<pubDate>Fri, 30 May 2008 19:26:35 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[IE6]]></category>
		<category><![CDATA[usability]]></category>
		<category><![CDATA[XHTML]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/?p=173</guid>
		<description><![CDATA[Кросс-браузерный вариант реализации механизма рейтинга без использования JavaScript Прочитал сегодня статью "Пять звёздочек" на Pepelsbey.net. Автор описывает очень интересный подход для реализации механизма рейтингов; основное преимущество описываемого подхода&#160;&#8212;&#160;минимум JavaScript за счет грамотного использования CSS. Решение Вадима основано на использовании CSS&#160;rollovers, плавающих элементах и z-index и выглядит очень красиво. Особенно меня впечатлило то, что его решение [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/css/173-five-stars-without-javascript/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Кросс-браузерный вариант реализации механизма рейтинга без использования <a href="http://blog.sjinks.pro/tag/javascript/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  JavaScript">JavaScript</a></em></h2>
<p>Прочитал сегодня статью "<a href="http://pepelsbey.net/2008/05/five-stars/" rel="nofollow">Пять звёздочек</a>" на <a href="http://pepelsbey.net/" rel="nofollow">Pepelsbey.net</a>. Автор описывает очень интересный подход для реализации механизма рейтингов; основное преимущество описываемого подхода&nbsp;&mdash;&nbsp;минимум JavaScript за счет грамотного использования <a href="http://blog.sjinks.pro/tag/css/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  CSS">CSS</a>.<span id="more-173"></span></p>
<p>Решение Вадима основано на использовании CSS&nbsp;rollovers, плавающих элементах и <code>z-index</code> и выглядит очень красиво. Особенно меня впечатлило то, что его решение будет работать с выключенной загрузкой изображений и отключенным CSS. Весьма приятно, ибо о <a href="http://blog.sjinks.pro/tag/usability/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  usability">usability</a> отечественные разработчики задумываются далеко не всегда.</p>
<p>Среди недостатков отмечу следующие:</p>
<ol>
<li>При использовании <a href="http://blog.sjinks.pro/tag/ie6/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  IE6">IE6</a> с выключенным JavaScript вся красота перестаёт работать (оффтопик: не могу понять, по каким причинам народ до сих пор сидит на <a href="http://blog.sjinks.pro/tag/ie6/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  IE6">IE6</a>?)</li>
<li>Некоторое неудобство при изменении шкалы: например, если изменить код так, чтобы можно было учитывать полбалла, то помимо ширин придется менять и <code>z-index</code> каждого элемента <code>a</code>. Хотя, в принципе, это мелочь.</li>
</ol>
<p>Полгода назад я какое-то работал над проектом myfolio.com, там тоже применялось пятизвёздочное голосование (правда, принцип несколько другой). Считая, что тот подход тоже имеет право жить <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> , привожу его здесь.</p>
<p>Разметка очень проста:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p17323">
        <div class="code html" id="p173code23">
&nbsp; &nbsp; <span class="sc-2">&lt;!--[if lte IE 6]&gt;&lt;a class=&quot;ievote&quot; href=&quot;#&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">ul</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;vote&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;ten&quot;</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#rated=10&quot;</span> <span class="kw3">title</span><span class="sy0">=</span><span class="st0">&quot;5 stars&quot;</span>&gt;</span>5.0<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;nine&quot;</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#rated=9&quot;</span> <span class="kw3">title</span><span class="sy0">=</span><span class="st0">&quot;4.5 stars&quot;</span>&gt;</span>4.5<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;eight&quot;</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#rated=8&quot;</span> <span class="kw3">title</span><span class="sy0">=</span><span class="st0">&quot;4 stars&quot;</span>&gt;</span>4.0<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;seven&quot;</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#rated=7&quot;</span> <span class="kw3">title</span><span class="sy0">=</span><span class="st0">&quot;3.5 stars&quot;</span>&gt;</span>3.5<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;six&quot;</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#rated=6&quot;</span> <span class="kw3">title</span><span class="sy0">=</span><span class="st0">&quot;3 star&quot;</span>&gt;</span>3.0<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;five&quot;</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#rated=5&quot;</span> <span class="kw3">title</span><span class="sy0">=</span><span class="st0">&quot;2.5 stars&quot;</span>&gt;</span>2.5<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;four&quot;</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#rated=4&quot;</span> <span class="kw3">title</span><span class="sy0">=</span><span class="st0">&quot;2 stars&quot;</span>&gt;</span>2.0<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;three rated&quot;</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#rated=3&quot;</span> <span class="kw3">title</span><span class="sy0">=</span><span class="st0">&quot;1.5 stars&quot;</span>&gt;</span>1.5<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;two&quot;</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#rated=2&quot;</span> <span class="kw3">title</span><span class="sy0">=</span><span class="st0">&quot;1 star&quot;</span>&gt;</span>1.0<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;one&quot;</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#rated=1&quot;</span> <span class="kw3">title</span><span class="sy0">=</span><span class="st0">&quot;0.5 stars&quot;</span>&gt;</span>0.5<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc-2">&lt;!--[if lte IE 6]&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;![endif]--&gt;</span>
        </div>
    </div>
</div>

<p>Про условные комментарии вокруг элемента <code>ul</code> можно прочитать в статье "<a href="http://blog.sjinks.pro/css/49-cross-browser-vertical-menu-without-javascript/">Кросс-браузерное одноуровневое вертикальное меню без JavaScript</a>".</p>
<p>Из особенностей&nbsp;&mdash;&nbsp;нумерация идёт в обратном порядке (это связано отказом от <span class="codebox"><code class="css"><span class="kw1">float</span></code></span> и <span class="codebox"><code class="css"><span class="kw1">z-index</span></code></span>, ибо код в myfolio был гораздо сложнее и с <span class="codebox"><code class="css"><span class="kw1">z-index</span></code></span> возникали некоторые проблемы в IE6).</p>
<p>Теперь самое интересное: стили:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p17324">
        <div class="code css" id="p173code24">
<span class="re1">.vote</span><span class="sy0">,</span> <span class="re1">.vote</span> li<span class="re1">.rated</span><span class="sy0">,</span> <span class="re1">.vote</span> li a<span class="re2">:hover </span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">background</span><span class="sy0">:</span> <span class="kw2">url</span><span class="br0">&#40;</span><span class="co2">stars.gif</span><span class="br0">&#41;</span> <span class="kw2">no-repeat</span> 0 <span class="nu0">0</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="coMULTI">/* Небольшая особенность: если задавать цвет, то картинка не должна быть прозрачной.<br />
Задание цвета используется для тех, кто выключил загрузку изображений в настройках браузера.<br />
В этом случае пользователь увидит нечто наподобие progress bar (но это всё же лучше, чем ничего).<br />
*/</span><br />
<span class="re1">.vote</span> li<span class="re1">.rated</span><span class="sy0">,</span> <span class="re1">.vote</span> li a<span class="re2">:hover </span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">background-color</span><span class="sy0">:</span> <span class="kw2">red</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re1">.vote</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">background-position</span><span class="sy0">:</span> 0 <span class="re3">-14px</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re1">.vote</span><span class="re2">:hover </span>li<span class="sy0">,</span> <span class="re1">.ievote</span><span class="re2">:hover </span>li <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">background</span><span class="sy0">:</span> <span class="kw2">none</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re1">.vote</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">80px</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">overflow</span><span class="sy0">:</span> <span class="kw2">hidden</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">relative</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re1">.vote</span><span class="sy0">,</span> <span class="re1">.vote</span> li<span class="sy0">,</span> <span class="re1">.vote</span> li a <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">height</span><span class="sy0">:</span> <span class="re3">14px</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">block</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re1">.vote</span> li <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">absolute</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re1">.vote</span><span class="sy0">,</span> <span class="re1">.vote</span> li <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">left</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">top</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">list-style</span><span class="sy0">:</span> <span class="kw2">none</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re1">.vote</span> li a <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">overflow</span><span class="sy0">:</span> <span class="kw2">hidden</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">text-indent</span><span class="sy0">:</span> <span class="re3">-100px</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">outline</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="coMULTI">/* Задаем ширину каждого балла; каждый последующий балл включает в себя предыдущий*/</span><br />
<span class="re1">.vote</span> li<span class="re1">.one</span> &nbsp; <span class="br0">&#123;</span> <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">7px</span><span class="sy0">;</span> &nbsp;<span class="br0">&#125;</span><br />
<span class="re1">.vote</span> li<span class="re1">.two</span> &nbsp; <span class="br0">&#123;</span> <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">16px</span><span class="sy0">;</span> <span class="br0">&#125;</span><br />
<span class="re1">.vote</span> li<span class="re1">.three</span> <span class="br0">&#123;</span> <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">23px</span><span class="sy0">;</span> <span class="br0">&#125;</span><br />
<span class="re1">.vote</span> li<span class="re1">.four</span> &nbsp;<span class="br0">&#123;</span> <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">32px</span><span class="sy0">;</span> <span class="br0">&#125;</span><br />
<span class="re1">.vote</span> li<span class="re1">.five</span> &nbsp;<span class="br0">&#123;</span> <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">39px</span><span class="sy0">;</span> <span class="br0">&#125;</span><br />
<span class="re1">.vote</span> li<span class="re1">.six</span> &nbsp; <span class="br0">&#123;</span> <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">48px</span><span class="sy0">;</span> <span class="br0">&#125;</span><br />
<span class="re1">.vote</span> li<span class="re1">.seven</span> <span class="br0">&#123;</span> <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">55px</span><span class="sy0">;</span> <span class="br0">&#125;</span><br />
<span class="re1">.vote</span> li<span class="re1">.eight</span> <span class="br0">&#123;</span> <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">64px</span><span class="sy0">;</span> <span class="br0">&#125;</span><br />
<span class="re1">.vote</span> li<span class="re1">.nine</span> &nbsp;<span class="br0">&#123;</span> <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">71px</span><span class="sy0">;</span> <span class="br0">&#125;</span><br />
<span class="re1">.vote</span> li<span class="re1">.ten</span> &nbsp; <span class="br0">&#123;</span> <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">80px</span><span class="sy0">;</span> <span class="br0">&#125;</span><br />
<br />
<span class="coMULTI">/* Для IE6 */</span><br />
<span class="re1">.ievote</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">text-decoration</span><span class="sy0">:</span> <span class="kw2">none</span> !important<span class="sy0">;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p>Наконец, <a href="http://blog.sjinks.pro/test/stars/stars.html">страница с рабочим примером</a>.</p>
<p><strong>Достоинства метода:</strong></p>
<ol>
<li>Метод кросс-браузерный, работает даже при отключенной загрузке изображений и выключенном CSS;</li>
<li>Превосходно работает даже при отключённом JavaScript (в том числе, и в IE6);</li>
<li>Благодаря использованию CSS rollover достаточно всего лишь одного HTTP-запроса (в отличие от реализаций, где используются списки с элементами <code>img</code>).</li>
</ol>
<p><a href="http://www.site-creator.info/html/rate/main.html" rel="nofollow">Еще одно красивое решение от site-creator.info</a>.</p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/css/173-five-stars-without-javascript/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/css/173-five-stars-without-javascript/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Размещение блока неизвестного размера в центре страницы при помощи CSS</title>
		<link>http://blog.sjinks.pro/css/59-placing-object-of-unknown-size-in-the-center-of-the-page/</link>
		<comments>http://blog.sjinks.pro/css/59-placing-object-of-unknown-size-in-the-center-of-the-page/#comments</comments>
		<pubDate>Tue, 01 Apr 2008 06:43:33 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[IE6]]></category>
		<category><![CDATA[IE7]]></category>
		<category><![CDATA[XHTML]]></category>
		<category><![CDATA[макет]]></category>
		<category><![CDATA[ошибка]]></category>
		<category><![CDATA[хак]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/?p=59</guid>
		<description><![CDATA[Как разместить блок неизвестного размера точно в центре страницы Гуляя по Internet, совершенно случайно натолкнулся на статью "Стили CSS - центрируем объекты по центру веб-страницы". Первой мыслью было, что автор начнёт рассказывать про вертикальное центрирование и всем известный margin: 0 auto. Но не тут-то было, всё гораздо интереснее Статья, на которую я наткнулся&#160;&#8212;&#160;это перевод статьи [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/css/59-placing-object-of-unknown-size-in-the-center-of-the-page/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Как разместить блок неизвестного размера точно в центре страницы</em></h2>
<p>Гуляя по Internet, совершенно случайно натолкнулся на статью "<a href="http://www.w3school.ru/blog/css/how-to-center-an-object-exactly-in-the-center.html">Стили CSS - центрируем объекты по центру веб-страницы</a>".</p>
<p>Первой мыслью было, что автор начнёт рассказывать про <a href="http://blog.sjinks.pro/css/24-vertical-align-without-tables/">вертикальное центрирование</a> и всем известный <code>margin: 0 auto</code>. Но не тут-то было, всё гораздо интереснее <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> <span id="more-59"></span></p>
<p>Статья, на которую я наткнулся&nbsp;&mdash;&nbsp;это перевод статьи Криса Койера (Chris Coyier) <a href="http://css-tricks.com/quick-css-trick-how-to-center-an-object-exactly-in-the-center/">Quick CSS Trick: How To Center an Object Exactly In The Center</a>. При этом высота и ширина центрируемого объекта в статье полагаются известными. Что ж, я ожидал чего-то большего.</p>
<p>Я сначала вкратце опишу идею Криса, потом расскажу, почему так не надо делать и затем покажу, что простого решения, удовлетворяющего всем требованиям, нет <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Начнём. Пусть у нас имеется, например, <code>&lt;div&gt;</code> размерами 200&times;100&nbsp;пикселей. Поступаем следующим образом:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p5935">
        <div class="code css" id="p59code35">
<span class="re1">.centered</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">fixed</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">top</span><span class="sy0">:</span> <span class="re3"><span class="nu0">50</span>%</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">left</span><span class="sy0">:</span> <span class="re3"><span class="nu0">50</span>%</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin-top</span><span class="sy0">:</span> <span class="re3">-50px</span><span class="sy0">;</span> <span class="coMULTI">/* 50% высоты */</span><br />
&nbsp; &nbsp; <span class="kw1">margin-left</span><span class="sy0">:</span> <span class="re3">-100px</span><span class="sy0">;</span> &nbsp;<span class="coMULTI">/* 50% ширины */</span><br />
&nbsp; &nbsp; <span class="kw1">height</span><span class="sy0">:</span> <span class="re3">100px</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">200px</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p>Начнём с того, что <a href="http://blog.sjinks.pro/tag/ie6/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  IE6">IE6</a> <code>position: fixed</code> очень плохо понимает. Для него нужно добавить небольшой <a href="http://blog.sjinks.pro/tag/hack/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  хак">хак</a>:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p5936">
        <div class="code css" id="p59code36">
<span class="sy0">*</span> html <span class="re1">.centered</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">absolute</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p>Теперь о минусах:</p>
<ul>
<li>размеры блока должны быть известны;</li>
<li>при уменьшении окна так, чтобы оно перекрывало отцентрированный объект, скроллер хотя и появляется, но прокрутить отцентрированный объект не сможет (из-за <code>position: fixed</code>);</li>
<li>при уменьшении ширины окна можно дойти до такого размера, когда у объекта границы станут отрицательными.</li>
</ul>
<p>Теперь о реализации центрирования в общем виде (считаем, что высота объекта нам неизвестна; ширина же должна быть известной, так как блочный элемент, не имеющий явно заданной ширины автоматически получает <code>width: 100%</code>). Решение основывается на идеях, представленных в следующих статьях:</p>
<ul>
<li><a href="http://blog.sjinks.pro/css/24-vertical-align-without-tables/"><strong>Вертикальное выравнивание без таблиц</strong></a>;</li>
<li><a href="http://blog.sjinks.pro/css/15-footer-in-the-very-bottom/"><strong>Нижний колонтитул&nbsp;&mdash;&nbsp;в нижней части страницы</strong></a>;</li>
<li><a href="http://blog.sjinks.pro/css/55-css-hacks-and-filters-for-different-browsers/"><strong>Подборка CSS-хаков для различных браузеров</strong></a>.</li>
</ul>
<p>Разметка:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p5937">
        <div class="code xhtml" id="p59code37">
<span class="sc2">&lt;<span class="kw2">body</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;outer&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;middle&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;inner&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Ego autem quem timeam lectorem, cum ad te ne Graecis quidem cedentem in philosophia audeam scribere?<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">body</span>&gt;</span>
        </div>
    </div>
</div>

<p>Прочитавшим статью "<a href="http://blog.sjinks.pro/css/24-vertical-align-without-tables/">Вертикальное выравнивание без таблиц</a>" должно быть ясно, откуда "растут ноги" у этой разметки.</p>
<p>Стили будут почти аналогичными приведённым в той статье, но с небольшими изменениями для IE.<br />
Начнём со стилей для нормальных браузеров:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p5938">
        <div class="code css" id="p59code38">
html <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">overflow</span><span class="sy0">:</span> <span class="kw2">auto</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
html<span class="sy0">,</span> body <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">margin</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">height</span><span class="sy0">:</span> <span class="re3"><span class="nu0">100</span>%</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3"><span class="nu0">100</span>%</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#outer</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">height</span><span class="sy0">:</span> <span class="re3"><span class="nu0">100</span>%</span><span class="sy0">;</span> <span class="coMULTI">/* В этом случае нельзя использовать min-height. Для таблиц (элементов с display: table) мир устроен иначе */</span><br />
&nbsp; &nbsp; <span class="kw1">display</span><span class="sy0">:</span> table<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">vertical-align</span><span class="sy0">:</span> <span class="kw2">middle</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">600px</span><span class="sy0">;</span> <span class="coMULTI">/* Если ширина не задана явно, будет 100% */</span><br />
&nbsp; &nbsp; <span class="kw1">margin</span><span class="sy0">:</span> 0 <span class="kw2">auto</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#middle</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">table-row</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">vertical-align</span><span class="sy0">:</span> <span class="kw2">middle</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#inner</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">table-cell</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">vertical-align</span><span class="sy0">:</span> <span class="kw2">middle</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p>Теперь стили для Ишака. Я бы поместил их в условный комментарий, например, так:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p5939">
        <div class="code xhtml" id="p59code39">
<span class="sc-2">&lt;!--[if lte IE 7]&gt;</span><br />
<span class="sc-2"> &nbsp; &nbsp;&lt;style type=&quot;text/css&quot;&gt;...&lt;/style&gt;</span><br />
<span class="sc-2">&lt;![endif]--&gt;</span>
        </div>
    </div>
</div>

<p>Вышеприведённый условный комментарий <strong>не должен</strong> работать для <a href="http://blog.sjinks.pro/tag/ie8/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  IE8">IE8</a>, и это сделано специально: во-первых, <a href="http://blog.sjinks.pro/tag/ie8/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  IE8">IE8</a> поддерживает <code>display: table</code>, <code>display: table-row</code> и <code>display: table-cell</code>; во-вторых, будучи <a href="http://blog.sjinks.pro/css/27-why-microsoft-calls-alpha-beta-or-what-acid-tests-are-for/">бетой</a>, он не поддерживает <code>vertical-align</code> ни в каком виде. В общем, когда Microsoft выпустит полноценный браузер, тогда и будем думать <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Стили для Internet Explorer:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p5940">
        <div class="code css" id="p59code40">
<span class="sy0">*</span> <span class="sy0">&gt;</span> html body <span class="br0">&#123;</span> <span class="coMULTI">/* Выравниваем блок по центру для IE4-IE5.5 */</span><br />
&nbsp; &nbsp; <span class="kw1">text-align</span><span class="sy0">:</span> <span class="kw2">center</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#outer</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">relative</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#middle</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">top</span><span class="sy0">:</span> <span class="re3"><span class="nu0">50</span>%</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">relative</span><span class="sy0">;</span> <span class="coMULTI">/* Не используем абсолютное позиционирование, чтобы избежать проблем с прокруткой */</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3"><span class="nu0">100</span>%</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#inner</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">relative</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">top</span><span class="sy0">:</span> <span class="re3">-<span class="nu0">50</span>%</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p>Если посмотреть на то, что <a href='http://static.sjinks.info/wp-content/uploads/2008/04/center0.html'>получилось</a>, можно заметить, что это один из тех случаев, когда код работает корректно в IE6, но не в <a href="http://blog.sjinks.pro/tag/ie7/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  IE7">IE7</a> (последний будет показывать совершенно ненужный отступ снизу). Если вспомнить статью "<a href="http://blog.sjinks.pro/css/24-vertical-align-without-tables/">Вертикальное выравнивание без таблиц</a>"), то там мы ставили <code>overflow: hidden</code> элементу <code>#outer</code>, чтобы избежать подобного рода неприятностей в IE6/7. И, хотя в IE6 можно обойтись и без этого (перейдя от абсолютного позиционирования к относительному), с IE7 всё не так просто. В качестве быстрого исправления можно предложить такой вариант:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p5941">
        <div class="code css" id="p59code41">
<span class="sy0">*</span><span class="re2">:first-child</span><span class="sy0">+</span>html <span class="re0">#outer</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; overflow-x<span class="sy0">:</span> <span class="kw2">hidden</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p>Что характерно, будет работать хоть <code>overflow-x</code>, хоть <code>overflow-y</code>.</p>
<p>В <a href='http://static.sjinks.info/wp-content/uploads/2008/04/center1.html'>результате</a> получаем код, который работает нормально везде, кроме IE7: в IE7 при уменьшении размера окна по вертикали полоса прокрутки появляться не будет. Сделать <em>нормальную</em> прокрутку непосредственно для элемента <code>#outer</code> также представляется проблематичным&nbsp;&mdash;&nbsp;нижний отступ будет слишком большим. Поэтому остаётся одно решение&nbsp;&mdash;&nbsp;таблица. Причём можно сделать так, что таблицу будет видеть только IE7:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p5942">
        <div class="code xhtml" id="p59code42">
<span class="sc-2">&lt;!--[if IE 7]&gt;&lt;table cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; class=&quot;outer&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; &nbsp;<span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;outer&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;middle&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;inner&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Ego autem quem timeam lectorem, cum ad te ne Graecis quidem cedentem in philosophia audeam scribere? quamquam a te ipso id quidem facio provocatus gratissimo mihi libro, quem ad me de virtute misisti. Sed ex eo credo quibusdam usu venire; ut abhorreant a Latinis, quod inciderint in inculta quaedam et horrida, de malis Graecis Latine scripta deterius. quibus ego assentior, dum modo de isdem rebus ne Graecos quidem legendos putent. res vero bonas verbis electis graviter ornateque dictas quis non legat? nisi qui se plane Graecum dici velit, ut a Scaevola est praetore salutatus Athenis Albucius.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
<span class="sc-2">&lt;!--[if IE 7]&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;![endif]--&gt;</span>
        </div>
    </div>
</div>

<p>По большому счёту, это извращение&nbsp;&mdash;&nbsp;ибо проще всего использовать таблицу для всех браузеров. Но проще не значит лучше, ибо очень часто встречаются ситуации, когда заказчики требуют, чтобы вёрстка была семантической (а когда видят "незапланированную таблицу", начинают громко ругаться). Правда, в этом случае для IE7 семантика теряется, но, как заметил <cite><a href="http://pokrovskii.com/">Максим Покровский</a></cite>, <q cite="http://blog.sjinks.pro/css/53-cross-browser-hybrid-css-menu-without-javascript/#comment-26">для него [IE], вообще, много чего теряется&hellip;</q>.</p>
<p>Итак, для комбинированного решения у нас получаются следующие стили для IE:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p5943">
        <div class="code css" id="p59code43">
<span class="sy0">*</span> <span class="sy0">&gt;</span> html body <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">text-align</span><span class="sy0">:</span> <span class="kw2">center</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="sy0">*</span> html <span class="re0">#outer</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">relative</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="sy0">*</span> html <span class="re0">#middle</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">top</span><span class="sy0">:</span> <span class="re3"><span class="nu0">50</span>%</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">relative</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3"><span class="nu0">100</span>%</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">overflow</span><span class="sy0">:</span> <span class="kw2">auto</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="sy0">*</span> html <span class="re0">#inner</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">relative</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">top</span><span class="sy0">:</span> <span class="re3">-<span class="nu0">50</span>%</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">overflow</span><span class="sy0">:</span> <span class="kw2">auto</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="sy0">*</span><span class="re2">:first-child</span><span class="sy0">+</span>html table<span class="re1">.outer</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">height</span><span class="sy0">:</span> <span class="re3"><span class="nu0">100</span>%</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">600px</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin</span><span class="sy0">:</span> 0 <span class="kw2">auto</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="sy0">*</span><span class="re2">:first-child</span><span class="sy0">+</span>html table<span class="re1">.outer</span> tbody <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">vertical-align</span><span class="sy0">:</span> <span class="kw2">middle</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p>Результат можно посмотреть на <a href='http://static.sjinks.info/wp-content/uploads/2008/04/center.html'>этой странице</a>.</p>
<p>Есть еще один вариант решения, но он полагается на использование <a href="http://blog.sjinks.pro/tag/javascript/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  JavaScript">JavaScript</a> в IE:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p5944">
        <div class="code xhtml" id="p59code44">
<span class="sc0">&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;</span><br />
<span class="sc2">&lt;<span class="kw2">html</span> xmlns<span class="sy0">=</span><span class="st0">&quot;http://www.w3.org/1999/xhtml&quot;</span>&gt;</span><br />
<span class="sc2">&lt;<span class="kw2">head</span>&gt;</span><br />
<span class="sc2">&lt;<span class="kw2">title</span>&gt;</span>Centering<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">title</span>&gt;</span><br />
<span class="sc2">&lt;<span class="kw2">style</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">&quot;text/css&quot;</span>&gt;</span><br />
html, body {<br />
&nbsp; &nbsp; margin: 0;<br />
&nbsp; &nbsp; padding: 0;<br />
&nbsp; &nbsp; height: 100%;<br />
&nbsp; &nbsp; width: 100%;<br />
}<br />
<br />
html {<br />
&nbsp; &nbsp; display: table;<br />
&nbsp; &nbsp; overflow: auto;<br />
}<br />
<br />
body {<br />
&nbsp; &nbsp; display: table-cell;<br />
&nbsp; &nbsp; vertical-align: middle;<br />
}<br />
<br />
.item {<br />
&nbsp; &nbsp; margin: 0 auto;<br />
&nbsp; &nbsp; width: 600px;<br />
}<br />
<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">style</span>&gt;</span><br />
<span class="sc-2">&lt;!--[if lte IE 7]&gt;</span><br />
<span class="sc-2">&lt;style type=&quot;text/css&quot;&gt;</span><br />
<span class="sc-2">* &gt; html body {</span><br />
<span class="sc-2"> &nbsp; &nbsp;text-align: center;</span><br />
<span class="sc-2">}</span><br />
<br />
<span class="sc-2">.item {</span><br />
<span class="sc-2"> &nbsp; &nbsp;margin-top: expression(this.offsetHeight &lt; this.parentNode.offsetHeight ? parseInt((this.parentNode.offsetHeight - this.offsetHeight) / 2) + 'px' : 0);</span><br />
<span class="sc-2">}</span><br />
<span class="sc-2">&lt;/style&gt;</span><br />
<span class="sc-2">&lt;![endif]--&gt;</span><br />
<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">head</span>&gt;</span><br />
<span class="sc2">&lt;<span class="kw2">body</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;item&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Ego autem quem timeam lectorem, cum ad te ne Graecis quidem cedentem in philosophia audeam scribere? quamquam a te ipso id quidem facio provocatus gratissimo mihi libro, quem ad me de virtute misisti. Sed ex eo credo quibusdam usu venire; ut abhorreant a Latinis, quod inciderint in inculta quaedam et horrida, de malis Graecis Latine scripta deterius. quibus ego assentior, dum modo de isdem rebus ne Graecos quidem legendos putent. res vero bonas verbis electis graviter ornateque dictas quis non legat? nisi qui se plane Graecum dici velit, ut a Scaevola est praetore salutatus Athenis Albucius.<br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">body</span>&gt;</span><br />
<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">html</span>&gt;</span>
        </div>
    </div>
</div>

<p>Результат можно посмотреть <a href='http://static.sjinks.info/wp-content/uploads/2008/04/center2.html'>здесь</a>.</p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/css/59-placing-object-of-unknown-size-in-the-center-of-the-page/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/css/59-placing-object-of-unknown-size-in-the-center-of-the-page/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Кросс-браузерное всплывающее гибридное меню на CSS без использования JavaScript</title>
		<link>http://blog.sjinks.pro/css/53-cross-browser-hybrid-css-menu-without-javascript/</link>
		<comments>http://blog.sjinks.pro/css/53-cross-browser-hybrid-css-menu-without-javascript/#comments</comments>
		<pubDate>Sun, 23 Mar 2008 04:33:58 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[IE6]]></category>
		<category><![CDATA[XHTML]]></category>
		<category><![CDATA[кросс-браузерное решение]]></category>
		<category><![CDATA[меню]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/css/53-cross-browser-hybrid-css-menu-without-javascript/</guid>
		<description><![CDATA[Реализация кросс-браузерного горизонтального меню на чистом CSS 3 без использования JavaScript Ранее я уже говорил о причинах, побудивших меня сделать меню на чистом CSS без использования JavaScript. Борясь с IE6, у меня получилась красивая версия вертикального меню &#8212; его реализация оказалась проще. Теперь обещанное горизонтальное меню. Требования, которые я поставил: Нельзя использовать JavaScript; Полученный код [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/css/53-cross-browser-hybrid-css-menu-without-javascript/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Реализация кросс-браузерного горизонтального <a href="http://blog.sjinks.pro/tag/menu/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  меню">меню</a> на чистом <a href="http://blog.sjinks.pro/tag/css/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  CSS">CSS</a> 3 без использования <a href="http://blog.sjinks.pro/tag/javascript/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  JavaScript">JavaScript</a></em></h2>
<p><a href="http://blog.sjinks.pro/css/49-cross-browser-vertical-menu-without-javascript/">Ранее</a> я уже говорил о причинах, побудивших меня сделать меню на чистом CSS без использования JavaScript. Борясь с <a href="http://blog.sjinks.pro/tag/ie6/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  IE6">IE6</a>, у меня получилась красивая версия <a href="http://blog.sjinks.pro/css/49-cross-browser-vertical-menu-without-javascript/">вертикального меню</a> &mdash; его реализация оказалась проще. Теперь обещанное горизонтальное меню.<span id="more-53"></span></p>
<p>Требования, которые я поставил:</p>
<ol>
<li>Нельзя использовать JavaScript;</li>
<li>Полученный код (CSS и <a href="http://blog.sjinks.pro/tag/xhtml/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  XHTML">XHTML</a>) должен успешно проходить валидацию.</li>
</ol>
<p>Разметка для тестового примера была взята из <a href="http://pokrovskii.com/vsplyivayuschee-gibridnoe-menyu-na-css-hybrid-css-dropdowns/">этой статьи</a> (которая и сподвигла меня на написание своего меню). В <a href="http://blog.sjinks.pro/css/49-cross-browser-vertical-menu-without-javascript/">предыдущей статье</a> код пришлось немного переработать (а всё из-за необходимости поддерживать IE6), и именно эту переработанную версию кода мы будем использовать.</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p5349">
        <div class="code xhtml" id="p53code49">
<span class="sc2">&lt;<span class="kw2">ul</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;menu&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Renaissance<span class="sc-2">&lt;!--[if IE 7]&gt;&lt;!--&gt;</span><span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;</span><span class="sc-2">&lt;!--&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc-2">&lt;!--[if lte IE 6]&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Brunelleschi<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Alberti<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Palladio<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Michelangelo<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Bramante<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc-2">&lt;!--[if lte IE 6]&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/a&gt;&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
<br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Art Nouveau<span class="sc-2">&lt;!--[if IE 7]&gt;&lt;!--&gt;</span><span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;</span><span class="sc-2">&lt;!--&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc-2">&lt;!--[if lte IE 6]&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Mackintosh<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Guimard<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Horta<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>van de Velde<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc-2">&lt;!--[if lte IE 6]&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/a&gt;&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
<br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;on&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Modern<span class="sc-2">&lt;!--[if IE 7]&gt;&lt;!--&gt;</span><span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;</span><span class="sc-2">&lt;!--&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc-2">&lt;!--[if lte IE 6]&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Sullivan<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Le Corbusier<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Mies<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Gropius<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Yamasaki<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc-2">&lt;!--[if lte IE 6]&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/a&gt;&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
<br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Postmodern<span class="sc-2">&lt;!--[if IE 7]&gt;&lt;!--&gt;</span><span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;</span><span class="sc-2">&lt;!--&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc-2">&lt;!--[if lte IE 6]&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Venturi<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Eisenman<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Stern<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Graves<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Gehry<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc-2">&lt;!--[if lte IE 6]&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/a&gt;&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
<br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Digital<span class="sc-2">&lt;!--[if IE 7]&gt;&lt;!--&gt;</span><span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;</span><span class="sc-2">&lt;!--&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc-2">&lt;!--[if lte IE 6]&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Xenakis<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Lynn<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Diller+Scofidio<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Zellner<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Hadid<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc-2">&lt;!--[if lte IE 6]&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/a&gt;&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">ul</span>&gt;</span>
        </div>
    </div>
</div>

<p>Таблица стилей для браузеров, поддерживающих CSS&nbsp;2.1:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p5350">
        <div class="code css" id="p53code50">
<span class="re0">#menu</span><span class="sy0">,</span> <span class="re0">#menu</span> li<span class="sy0">,</span> <span class="re0">#menu</span> ul <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">list-style</span><span class="sy0">:</span> <span class="kw2">none</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">block</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3"><span class="nu0">100</span>%</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">relative</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">float</span><span class="sy0">:</span> <span class="kw1">left</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">height</span><span class="sy0">:</span> <span class="re3">2em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">line-height</span><span class="sy0">:</span> <span class="re3">2em</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li a <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">float</span><span class="sy0">:</span> <span class="kw1">left</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">border</span><span class="sy0">:</span> <span class="re3">1px</span> <span class="kw2">solid</span> <span class="kw2">red</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">vertical-align</span><span class="sy0">:</span> <span class="kw2">middle</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding</span><span class="sy0">:</span> 0 <span class="re3">.5em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">100px</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li ul <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">none</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">absolute</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">top</span><span class="sy0">:</span> <span class="re3">2em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">left</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin-top</span><span class="sy0">:</span> <span class="re3">1px</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3"><span class="nu0">100</span>%</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">background</span><span class="sy0">:</span> <span class="re0">#FFF</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">height</span><span class="sy0">:</span> <span class="kw2">auto</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li<span class="re1">.on</span> ul<span class="sy0">,</span> <span class="re0">#menu</span> li<span class="re2">:hover </span>ul <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">block</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">z-index</span><span class="sy0">:</span> <span class="nu0">10</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li<span class="re2">:hover </span>ul <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">z-index</span><span class="sy0">:</span> <span class="nu0">100</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li li a <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">block</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">border</span><span class="sy0">:</span> <span class="re3">1px</span> <span class="kw2">solid</span> <span class="kw2">red</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">vertical-align</span><span class="sy0">:</span> <span class="kw2">middle</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding</span><span class="sy0">:</span> 0 <span class="re3">.5em</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p>Презентационные стили:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p5351">
        <div class="code css" id="p53code51">
<span class="re0">#menu</span> <span class="sy0">&gt;</span> li <span class="sy0">+</span> li <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">margin-left</span><span class="sy0">:</span> <span class="re3">-1px</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li ul li <span class="sy0">+</span> li <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">margin-left</span><span class="sy0">:</span> <span class="re3">-1px</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li a <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">outline</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">text-decoration</span><span class="sy0">:</span> <span class="kw2">none</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li<span class="re1">.on</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">background</span><span class="sy0">:</span> <span class="kw2">yellow</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li<span class="re2">:hover </span>a<span class="sy0">,</span> <span class="re0">#menu</span> li a<span class="re2">:hover</span><span class="sy0">,</span> <span class="re0">#menu</span> li a<span class="re2">:hover </span>a <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">background</span><span class="sy0">:</span> <span class="re0">#EEE</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li ul li<span class="re2">:hover</span><span class="sy0">,</span> <span class="re0">#menu</span> li ul li a<span class="re2">:hover </span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">background</span><span class="sy0">:</span> <span class="re0">#EAFBFC</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p>Более детально это всё объяснено в <a href="http://blog.sjinks.pro/css/49-cross-browser-vertical-menu-without-javascript/">предыдущей статье</a>.</p>
<p>Теперь будем лечить IE6. У меня этот процесс занял несколько часов, но результат стоил того &mdash; <em>оно работает</em>!!!</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p5352">
        <div class="code css" id="p53code52">
<span class="sy0">*</span> html <span class="re0">#menu</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; overflow-x<span class="sy0">:</span> <span class="kw2">hidden</span><span class="sy0">;</span> <span class="coMULTI">/* Скрыть побочный эффект следующего исправления */</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="sy0">*</span> html <span class="re0">#menu</span> li ul <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">block</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">z-index</span><span class="sy0">:</span> <span class="nu0">1</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin-top</span><span class="sy0">:</span> <span class="re3">2px</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">overflow</span><span class="sy0">:</span> <span class="kw2">visible</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="coMULTI">/* Это исправляет неверное определение ширины - абсолютное значение width: 100% без этих строк было бы равно ширине родительского &lt;a&gt; */</span><br />
&nbsp; &nbsp; <span class="kw1">padding-right</span><span class="sy0">:</span> <span class="re3">1000em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin-right</span><span class="sy0">:</span> <span class="re3">-1000em</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="sy0">*</span> html <span class="re0">#menu</span> li<span class="re1">.on</span> a table<span class="sy0">,</span><br />
<span class="sy0">*</span> html <span class="re0">#menu</span> li a<span class="re2">:hover </span>table<br />
<span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">visibility</span><span class="sy0">:</span> <span class="kw2">visible</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="sy0">*</span> html <span class="re0">#menu</span> li<span class="re1">.on</span> a table ul <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">z-index</span><span class="sy0">:</span> -<span class="nu0">1</span><span class="sy0">;</span> <span class="coMULTI">/* Ключевое исправление - без него меню правильно работать не будет. Предназначено для исправления последствий многочисленных багов в реализации z-index. Благодаря этому исправлению, все li a:hover table, находящиеся перед li.on table, будут нормально отображаться (не будут перекрываться li.on table) */</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="sy0">*</span> html <span class="re0">#menu</span> li a<span class="re2">:hover </span>table ul <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">z-index</span><span class="sy0">:</span> <span class="nu0">100</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="sy0">*</span> html <span class="re0">#menu</span> li a<span class="re2">:hover </span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">static</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="coMULTI">/* У таблицы теперь статическая позиция. Абсолютное/относительное позиционирование вносит ужасный бедлам в и без того глючную реализацию z-index в IE6. */</span><br />
<span class="sy0">*</span> html <span class="re0">#menu</span> table <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">border-collapse</span><span class="sy0">:</span> <span class="kw2">collapse</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">visibility</span><span class="sy0">:</span> <span class="kw2">hidden</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p><strong>Замечания по реализации:</strong></p>
<ol>
<li>Из-за плохой поддержки <code>z-index</code> Ишаком возможны проблемы с <code>border-top/bottom</code> у крайних правых элементов меню;</li>
<li>Из-за того, что пришлось использовать overflow-x, CSS не валидируется в рамках спецификации CSS&nbsp;2.1 (но проходит валидацию CSS&nbsp;3).</li>
</ol>
<p>Тестовая страница лежит <a href='http://static.sjinks.info/wp-content/uploads/2008/03/hybrid-horizontal.html' title='hybrid-horizontal.html'>здесь</a>.</p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/css/53-cross-browser-hybrid-css-menu-without-javascript/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/css/53-cross-browser-hybrid-css-menu-without-javascript/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Кросс-браузерное одноуровневое вертикальное меню без JavaScript</title>
		<link>http://blog.sjinks.pro/css/49-cross-browser-vertical-menu-without-javascript/</link>
		<comments>http://blog.sjinks.pro/css/49-cross-browser-vertical-menu-without-javascript/#comments</comments>
		<pubDate>Sun, 23 Mar 2008 01:45:46 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[IE6]]></category>
		<category><![CDATA[whatever:hover]]></category>
		<category><![CDATA[кросс-браузерное решение]]></category>
		<category><![CDATA[меню]]></category>
		<category><![CDATA[ошибка]]></category>
		<category><![CDATA[разметка]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/css/49-cross-browser-vertical-menu-without-javascript/</guid>
		<description><![CDATA[Создание вертикального кросс-браузерного меню без использования JavaScript &#8212; чистый CSS! Так случилось, что срочно понадобилось сделать горизонтальное меню, причем для проекта, который нужно было сдавать вчера Естественно, самому писать не было времени, нужно было взять что-то готовое. Я недавно прочитал статью «Всплывающее гибридное меню на CSS», поэтому взял код именно оттуда. Но не в этом [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/css/49-cross-browser-vertical-menu-without-javascript/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Создание вертикального кросс-браузерного <a href="http://blog.sjinks.pro/tag/menu/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  меню">меню</a> без использования <a href="http://blog.sjinks.pro/tag/javascript/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  JavaScript">JavaScript</a> &mdash; чистый <a href="http://blog.sjinks.pro/tag/css/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  CSS">CSS</a>!</em></h2>
<p>Так случилось, что срочно понадобилось сделать горизонтальное меню, причем для проекта, который нужно было сдавать вчера <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Естественно, самому писать не было времени, нужно было взять что-то готовое. Я недавно прочитал статью «<a href="http://pokrovskii.com/vsplyivayuschee-gibridnoe-menyu-na-css-hybrid-css-dropdowns/">Всплывающее гибридное меню на CSS</a>», поэтому взял код именно оттуда. Но не в этом дело. У подавляющего большинства меню камнем преткновения становится <a href="http://blog.sjinks.pro/tag/ie6/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  IE6">IE6</a> — а всё из-за того, что он понимает <code>:hover</code> только для тэга <span class="codebox"><code class="html"><span class="sc2">&lt;<span class="kw2">a</span>&gt;</span></code></span>. Когда-то у меня был заказчик, требовавший, чтобы всё одинаково работало с выключенным JavaScript'ом; вспомнив его, я решил попробовать сделать меню, работающее безо всякого JavaScript. Так получилось, что попутно я нашел еще один очень интересный глюк в IE6 (о нём далее), в борьбе с которым у меня получилось вертикальное меню.<span id="more-49"></span><br />
<script type="text/javascript">odl.register(initLightbox);</script><br />
Друг заметил, что смысла уродоваться не было, ибо есть <a href="http://www.xs4all.nl/~peterned/csshover.html">whatever:hover</a>, который применяется многими разработчиками. Для всех, кто такого же мнения, отмечу, что <a href="http://blog.sjinks.pro/tag/whateverhover/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  whatever:hover">whatever:hover</a> — это HTC-компонент, суть JavaScript, вследствие чего при выключенном JavaScript работать не будет. Помимо этого, <a href="http://blog.sjinks.pro/tag/whateverhover/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  whatever:hover">whatever:hover</a> <em>не будет</em> работать при динамическом построении меню. И еще его использование негативно сказывается на отклик IE при начальном рендеринге (в смысле, когда весь <a href="http://blog.sjinks.pro/tag/dom/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  DOM">DOM</a> уже загружен, и наступило время выполнять deferred-скрипты и грузить картинки).</p>
<p>Приступим.<br />
Разметку я взял все из той же <a href="http://pokrovskii.com/vsplyivayuschee-gibridnoe-menyu-na-css-hybrid-css-dropdowns/">статьи</a>, она (<a href="http://blog.sjinks.pro/tag/markup/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  разметка">разметка</a>) имеет следующий вид:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p4959">
        <div class="code xhtml" id="p49code59">
<span class="sc2">&lt;<span class="kw2">ul</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;menu&quot;</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Renaissance<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Brunelleschi<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Alberti<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Palladio<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Michelangelo<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Bramante<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
<br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Art Nouveau<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Mackintosh<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Guimard<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Horta<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>van de Velde<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
<br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Modern<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Sullivan<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Le Corbusier<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Mies<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Gropius<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Yamasaki<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
<br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Postmodern<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Venturi<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Eisenman<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Stern<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Graves<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Gehry<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
<br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Digital<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Xenakis<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Lynn<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Diller+Scofidio<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Zellner<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Hadid<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">ul</span>&gt;</span>
        </div>
    </div>
</div>

<p>Начнём с браузеров, поддерживающих CSS 2.1. Таблица стилей для них будет иметь следующий вид:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p4960">
        <div class="code css" id="p49code60">
<span class="re0">#menu</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">height</span><span class="sy0">:</span> <span class="re3">2em</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span><span class="sy0">,</span> <span class="re0">#menu</span> ul<span class="sy0">,</span> <span class="re0">#menu</span> ul li <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">list-style</span><span class="sy0">:</span> <span class="kw2">none</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">block</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">float</span><span class="sy0">:</span> <span class="kw1">left</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">height</span><span class="sy0">:</span> <span class="re3">2em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">line-height</span><span class="sy0">:</span> <span class="re3">2em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">relative</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li a <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">block</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">border</span><span class="sy0">:</span> <span class="re3">1px</span> <span class="kw2">solid</span> <span class="kw2">red</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">vertical-align</span><span class="sy0">:</span> <span class="kw2">middle</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding</span><span class="sy0">:</span> 0 <span class="re3">.5em</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li ul <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">none</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">absolute</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">top</span><span class="sy0">:</span> <span class="re3">2em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">left</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin</span><span class="sy0">:</span> <span class="re3">1px</span> 0 0 <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">background</span><span class="sy0">:</span> <span class="re0">#FFF</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">100px</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li<span class="re2">:hover </span>ul <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">block</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li ul li <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">float</span><span class="sy0">:</span> <span class="kw2">none</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3"><span class="nu0">100</span>%</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li ul li a <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">border</span><span class="sy0">:</span> <span class="re3">1px</span> <span class="kw2">solid</span> <span class="kw2">red</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">vertical-align</span><span class="sy0">:</span> <span class="kw2">middle</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding</span><span class="sy0">:</span> 0 <span class="re3">.5em</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p>Вся магия содержится в двух правилах:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p4961">
        <div class="code css" id="p49code61">
<span class="re0">#menu</span> li ul <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">none</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">absolute</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">top</span><span class="sy0">:</span> <span class="re3">2em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">left</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin</span><span class="sy0">:</span> <span class="re3">1px</span> 0 0 <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">background</span><span class="sy0">:</span> <span class="re0">#FFF</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">100px</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li<span class="re2">:hover </span>ul <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">block</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p>Первое задаёт размеры/позицию выпадающего меню; позиция вычисляется относительно родительского элемента <span class="codebox"><code class="css">&lt;li<span class="sy0">&gt;</span></code></span>. Второе же правило показывает выпадающее меню при наведении курсора мыши на заголовок. Ничего сложного.</p>
<p>Презентационные стили:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p4962">
        <div class="code css" id="p49code62">
<span class="re0">#menu</span> <span class="sy0">&gt;</span> li <span class="sy0">+</span> li <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">margin-left</span><span class="sy0">:</span> <span class="re3">-1px</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li ul li <span class="sy0">+</span> li <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">margin-top</span><span class="sy0">:</span> <span class="re3">-1px</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li a <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">outline</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">text-decoration</span><span class="sy0">:</span> <span class="kw2">none</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li<span class="re2">:hover </span>a<span class="sy0">,</span> <span class="re0">#menu</span> li a<span class="re2">:hover </span>a <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">background</span><span class="sy0">:</span> <span class="re0">#EEE</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li li a<span class="sy0">,</span> <span class="re0">#menu</span> li<span class="re2">:hover </span>li a<span class="sy0">,</span> <span class="re0">#menu</span> li a<span class="re2">:hover </span>li a <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">background</span><span class="sy0">:</span> <span class="re0">#FFF</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#menu</span> li ul li<span class="re2">:hover </span>a<span class="sy0">,</span> <span class="re0">#menu</span> li ul li a<span class="re2">:hover </span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">background</span><span class="sy0">:</span> <span class="re0">#EAFBFC</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p>Первые два правила позиционируют элементы списков так, чтобы <code>border-right</code> (<code>border-bottom</code>) предыдущего элемента совпадал с <code>border-left</code> (<code>border-top</code>) следующего.</p>
<p>Теперь переходим к IE6. В нём не работает второе магическое правило (<code>#menu li:hover ul</code>), так как IE6 воспринимает <code>:hover</code> только на элементах <code>&lt;a&gt;</code>.</p>
<p>Первая мысль — закрывать для IE6 <span class="codebox"><code class="html"><span class="sc2">&lt;<span class="kw2">a</span>&gt;</span></code></span> не до списка, а после. Мысль хорошая, но просмотр дерева в IE Developer Toolbar показал, что IE как-то «криво» понимает код (в принципе, здесь Ишак прав: невалидный код каждый волен понимать так, как может). Следовательно, надо список «обернуть» во что-нибудь, но так, чтобы <span class="codebox"><code class="html"><span class="sc2">&lt;<span class="kw2">a</span>&gt;</span></code></span> нормально работал. И совершенно случайно <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  я вспомнил один случай, когда разгребал одну ужасную табличную вёрстку (а уровень вложенности таблиц переваливал там за 16), и открытый тэг <span class="codebox"><code class="html"><span class="sc2">&lt;<span class="kw2">a</span>&gt;</span></code></span> превратил всю таблицу в сплошную гиперссылку. Чем чёрт не шутит, я решил попробовать.</p>
<p>Код стал таким:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p4963">
        <div class="code xhtml" id="p49code63">
<span class="sc2">&lt;<span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Renaissance<span class="sc-2">&lt;!--[if IE 7]&gt;&lt;!--&gt;</span><span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;</span><span class="sc-2">&lt;!--&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; <span class="sc-2">&lt;!--[if lte IE 6]&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;![endif]--&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Brunelleschi<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Alberti<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Palladio<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Michelangelo<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">li</span>&gt;&lt;<span class="kw2">a</span> <span class="kw3">href</span><span class="sy0">=</span><span class="st0">&quot;#&quot;</span>&gt;</span>Bramante<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">a</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">ul</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc-2">&lt;!--[if lte IE 6]&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/a&gt;&lt;![endif]--&gt;</span><br />
<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">li</span>&gt;</span>
        </div>
    </div>
</div>

<p>Получилось! Ишак нормально распарсил код и сгенерировал нормальное дерево:<br/><br />
<a href='http://static.sjinks.info/wp-content/uploads/2008/03/2008-03-23_031712.png' title='XML-дерево, сгенерированное IE' rel="lightbox"><img src='http://static.sjinks.info/wp-content/uploads/2008/03/2008-03-23_031712.thumbnail.png' alt='XML-дерево, сгенерированное IE' /></a></p>
<p>Теперь нужно немного поколдовать, чтобы заставить всё работать как надо.<br />
Первое, что приходит в голову — это такие вот стили:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p4964">
        <div class="code css" id="p49code64">
<span class="sy0">*</span> html <span class="re0">#menu</span> li ul <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">block</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="sy0">*</span> html <span class="re0">#menu</span> li a<span class="re2">:hover </span><span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">static</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="sy0">*</span> html <span class="re0">#menu</span> li a<span class="re2">:hover </span>table <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">block</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="sy0">*</span> html <span class="re0">#menu</span> table <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">absolute</span><span class="sy0">;</span> <br />
&nbsp; &nbsp; <span class="kw1">border-collapse</span><span class="sy0">:</span> <span class="kw2">collapse</span><span class="sy0">;</span> <br />
&nbsp; &nbsp; <span class="kw1">top</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">left</span><span class="sy0">:</span> <span class="re3">-1px</span><span class="sy0">;</span> <br />
&nbsp; &nbsp; <span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">none</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p>Иными словами, мы всю магию перенесли на уровень выше (так как теперь у нас <span class="codebox"><code class="html"><span class="sc2">&lt;<span class="kw2">ul</span>&gt;</span></code></span> обёрнут <span class="codebox"><code class="html"><span class="sc2">&lt;<span class="kw2">table</span>&gt;</span></code></span>). Правило <span class="codebox"><code class="css"><span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">static</span></code></span> в <span class="codebox"><code class="css"><span class="sy0">*</span> html <span class="re0">#menu</span> li a<span class="sy0">:</span>hover</code></span> — это вуду, без этого не работает <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  (как вариант, можно задать <span class="codebox"><code class="css"><span class="kw1">background</span></code></span> с цветом, отличным от <span class="codebox"><code class="css"><span class="kw2">transparent</span></code></span>).</p>
<p>И тут начинаются проблемы. Я, конечно, всегда подозревал, что IE написан очень криво, но чтобы <em>так криво</em>… После нескольких наведений на меню получается такая картина:</p>
<p><a href='http://static.sjinks.info/wp-content/uploads/2008/03/2008-03-23_033307.png' title='Ошибка IE6' rel="lightbox"><img src='http://static.sjinks.info/wp-content/uploads/2008/03/2008-03-23_033307.thumbnail.png' alt='Ошибка IE6' /></a></p>
<p>То есть таблицы как бы нет (<span class="codebox"><code class="css"><span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">none</span></code></span>), но место в потоке она занимает, и при этом хотя текста дочерних элементов не видно, но <span class="codebox"><code class="css"><span class="kw1">border</span></code></span> остался. Нет таблицы, и в то же время есть. Чудеса.</p>
<p>От таких чудес невольно опускаются руки. Потратив пару часов на эксперименты, я чудом нашел рабочую комбинацию: вместо <span class="codebox"><code class="css"><span class="kw1">display</span><span class="sy0">:</span> <span class="kw2">none</span>/<span class="kw2">block</span></code></span> нужно использовать <span class="codebox"><code class="css"><span class="kw1">visibility</span><span class="sy0">:</span> <span class="kw2">visible</span>/<span class="kw2">hidden</span></code></span>. Не знаю, почему, но оно работает. Но всё же мне интересно, что курили разработчики, писавшие Ишака?</p>
<p>Страница с рабочим кросс-браузерным меню находится <a href='http://static.sjinks.info/wp-content/uploads/2008/03/vertical-one-level.html' title='vertical-one-level.html'>здесь</a>. Никакого JavaScript, только CSS!</p>
<p><strong><ins datetime="2008-07-02T21:53:38+00:00">Update:</ins></strong> <a href="http://www.alexilin.ru/vypadayushhee-menyu-bez-javascript/" rel="external nofollow">еще одна версия</a> вертикального меню.</p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/css/49-cross-browser-vertical-menu-without-javascript/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/css/49-cross-browser-vertical-menu-without-javascript/feed/</wfw:commentRss>
		<slash:comments>32</slash:comments>
		</item>
		<item>
		<title>Резиновый трехколоночный макет с правосторонними сайдбарами</title>
		<link>http://blog.sjinks.pro/css/48-liquid-three-column-layout-with-right-sidebars/</link>
		<comments>http://blog.sjinks.pro/css/48-liquid-three-column-layout-with-right-sidebars/#comments</comments>
		<pubDate>Sat, 22 Mar 2008 01:24:37 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[IE8]]></category>
		<category><![CDATA[XHTML]]></category>
		<category><![CDATA[макет]]></category>
		<category><![CDATA[резиновый макет]]></category>
		<category><![CDATA[трёхколоночный макет]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/css/48-liquid-three-column-layout-with-right-sidebars/</guid>
		<description><![CDATA[Кросс-браузерный семантически корректный резиновый макет с тремя колонками (сайдбары справа) Очередной раз попав не туда, куда надо из Google, я натолкнулся на статью "Трехколоночный макет на CSS с одинаковой высотой колонок". Да, трехколоночные макеты (да еще и резиновые!) очень популярны, я смотрю Но, несмотря на популярность таких макетов, многие верстальщики почему-то не хотят учиться и [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/css/48-liquid-three-column-layout-with-right-sidebars/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Кросс-браузерный семантически корректный резиновый <a href="http://blog.sjinks.pro/tag/layout/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  макет">макет</a> с тремя колонками (сайдбары справа)</em></h2>
<p>Очередной раз попав не туда, куда надо из Google, я натолкнулся на статью "<a href="http://dimox.name/3-column-css-layout-right-sidebars/">Трехколоночный макет на CSS с одинаковой высотой колонок</a>". Да, трехколоночные макеты (да еще и резиновые!) очень популярны, я смотрю <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Но, несмотря на популярность таких макетов, многие верстальщики почему-то <del datetime="2008-06-19T08:30:52+00:00">не хотят учиться и</del> городят целый огород на div'ах.<span id="more-48"></span></p>
<p>В указанной статье приводится следующая <a href="http://blog.sjinks.pro/tag/markup/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  разметка">разметка</a> (я убрал пустые строки и изменил форматирование):</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p4869">
        <div class="code xhtml" id="p48code69">
<span class="sc2">&lt;<span class="kw2">body</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;wrapper&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;header&quot;</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;container&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;sub-container&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;wrpr&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;content&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;text&quot;</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;left&quot;</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;right&quot;</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;footer&quot;</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">body</span>&gt;</span>
        </div>
    </div>
</div>

<p>Что мы видим: пример, как верстать <strong>не надо</strong>. Может быть, сказано слишком резко, но на мой взгляд, суп из div'ов (с глубиной вложенности 6) ничем не лучше табличной вёрстки (табличная вёрстка будет даже компактнее). Кроме того, б<em>о</em>льшая часть этого супа не несёт семантической нагрузки. И вообще, при верстке нужно руководствоваться принципом <abbr title="Keep It Simple, Student">KISS</abbr>, но это моё сугубо личное мнение.</p>
<p>Попробуем переделать.<br />
Начнём с разметки:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p4870">
        <div class="code xhtml" id="p48code70">
<span class="sc2">&lt;<span class="kw2">body</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;header&quot;</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
<br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;container&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;content&quot;</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;column&quot;</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;col1&quot;</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;column&quot;</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;col2&quot;</span> <span class="kw3">class</span><span class="sy0">=</span><span class="st0">&quot;column&quot;</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
<br />
&nbsp; &nbsp; <span class="sc2">&lt;<span class="kw2">div</span> <span class="kw3">id</span><span class="sy0">=</span><span class="st0">&quot;footer&quot;</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">div</span>&gt;</span><br />
<span class="sc2">&lt;<span class="sy0">/</span><span class="kw2">body</span>&gt;</span>
        </div>
    </div>
</div>

<p>Как я уже отмечал в предыдущих статьях, названиям классов и атрибутам <code>id</code> нужно давать семантически значимые имена, но в качестве тестового примера пойдут и такие.</p>
<p>Простая разметка&nbsp;&mdash;&nbsp;простые стили:</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p4871">
        <div class="code css" id="p48code71">
html<span class="sy0">,</span> body <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">margin</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">border</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3"><span class="nu0">100</span>%</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
html <span class="br0">&#123;</span> <span class="coMULTI">/* Для IE6 и IE7 */</span><br />
&nbsp; &nbsp; <span class="kw1">overflow</span><span class="sy0">:</span> <span class="kw2">auto</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
body <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">min-width</span><span class="sy0">:</span> <span class="re3">50em</span><span class="sy0">;</span> <span class="coMULTI">/* #container.paddingRight + #col1.offsetWidth + #col2.offsetWidth */</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#container</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">overflow</span><span class="sy0">:</span> <span class="kw2">hidden</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding-right</span><span class="sy0">:</span> <span class="re3">25em</span><span class="sy0">;</span> <span class="coMULTI">/* #col1.offsetWidth + #col2.offsetWidth */</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">relative</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="coMULTI">/*\*/</span><br />
<span class="sy0">*</span> html <span class="re0">#container</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">height</span><span class="sy0">:</span> <span class="re3"><span class="nu0">1</span>%</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<span class="coMULTI">/**/</span><br />
<br />
<span class="re1">.column</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">relative</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">float</span><span class="sy0">:</span> <span class="kw1">left</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding-bottom</span><span class="sy0">:</span> <span class="re3">1002em</span> !important<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin-bottom</span><span class="sy0">:</span> <span class="re3">-1000em</span> !important<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">overflow</span><span class="sy0">:</span> <span class="kw2">hidden</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#content</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3"><span class="nu0">100</span>%</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#col1</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">10em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin-right</span><span class="sy0">:</span> <span class="re3">-<span class="nu0">100</span>%</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#col2</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">15em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin-right</span><span class="sy0">:</span> <span class="re3">-<span class="nu0">100</span>%</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin-left</span><span class="sy0">:</span> <span class="re3">10em</span><span class="sy0">;</span> <span class="coMULTI">/* #col1.offsetWidth */</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#footer</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">clear</span><span class="sy0">:</span> <span class="kw2">both</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p>Для краткости презентационные стили (aka расцветка) опущены.</p>
<p>Тестовая страница доступна <a href="http://blog.sjinks.pro/test/3col/3col_simple.html">здесь</a>. Кстати, разметка получилась даже проще, чем <a href="http://trifler.ru/blog/i/users/ushablon.htm">здесь</a> <img src='http://static.sjinks.info/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Но макет не был бы так хорош, если бы не позволял с лёгкостью добавлять отступы, границы и бордюры. В статье "<a href="http://blog.sjinks.pro/css/31-ie-and-general-case-of-two-column-liquid-layouts/"><strong>IE7/8 и общий случай двухколоночной резиновой вёрстки</strong></a>" я показывал, как получаются формулы для вычисления значений границ и иже с ними (вспоминаем про эквивалентность преобразований), поэтому здесь приведу только конечный результат:</p>
<table cellpadding="2" cellspacing="1" class="bordered">
<thead align="left">
<tr>
<th>Элемент</th>
<th>Свойство</th>
<th>Формула</th>
</tr>
</thead>
<tbody>
<tr>
<td>body</td>
<td>min-width</td>
<td><code>(#container.offsetWidth - #container.width) + (#content.offsetWidth - #content.width) + #col1.offsetWidth + #col2.offsetWidth</code></td>
</tr>
<tr>
<td>#container</td>
<td>padding-right</td>
<td><code>(#content.offsetWidth - #content.width) + #col1.offsetWidth + #col2.offsetWidth</code></td>
</tr>
<tr>
<td>#content</td>
<td>margin-left</td>
<td><code>=#container.paddingLeft</code></td>
</tr>
<tr>
<td>#col1</td>
<td>margin-left</td>
<td><code>=#content.marginRight</code></td>
</tr>
<tr>
<td>#col2</td>
<td>margin-left</td>
<td><code>#col1.offsetWidth + #col2.желаемый_marginLeft</code></td>
</tr>
<tr>
<td>#col1, #col2</td>
<td>margin-right</td>
<td><code>-100%</code></td>
</tr>
</tbody>
</table>
<p>В <code>#container.paddingRight</code> входит желаемый <code>#col2.marginRight</code> (но у Opera есть некоторые проблемы с его отображением).</p>
<p>Из-за того, что все колонки имеют равную высоту, отобразить <code>border-bottom</code> у них не представилось возможным.</p>
<p>Для <a href="http://blog.sjinks.pro/tag/ie8/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  IE8">IE8</a> добавляются следующие изменения:</p>
<ul>
<li><code>#col1.marginLeft</code> устанавливается в сумму горизонтальных отступов, границ и бордюров элемента <code>#content</code>;</li>
<li><code>#col2.marginLeft</code> увеличивается на величину <code>#col1.marginLeft</code>.</li>
</ul>
<p>Тестовая страница для экспериментов находится <a href="http://blog.sjinks.pro/test/3col/3col.html">здесь</a>.</p>
          
<div class="codebox">
    <div class="the_code" style="" id="p4872">
        <div class="code css" id="p48code72">
html<span class="sy0">,</span> body <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">margin</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">border</span><span class="sy0">:</span> <span class="nu0">0</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">font</span><span class="sy0">:</span> <span class="re3">12px</span> Verdana<span class="sy0">,</span> Tahoma<span class="sy0">,</span> Arial<span class="sy0">,</span> Helvetica<span class="sy0">,</span> <span class="kw2">sans-serif</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3"><span class="nu0">100</span>%</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
html <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">overflow</span><span class="sy0">:</span> <span class="kw2">auto</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
body <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">min-width</span><span class="sy0">:</span> <span class="re3">81em</span><span class="sy0">;</span> <span class="coMULTI">/* (38.5 + 0.5 + 2*1 + 2*1) + (2*1 + 2*1 + 0.5) + (10 + 2*1 + 2*1) + (15 + 0.5 + 2*1 + 2*1) = 43 + 4.5 + 14 + 19.5 = 57 + 24 */</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#container</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">overflow</span><span class="sy0">:</span> <span class="kw2">hidden</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding-right</span><span class="sy0">:</span> <span class="re3">38.5em</span><span class="sy0">;</span> <span class="coMULTI">/* (2*1 + 2*1 + 0.5) + (10 + 2*1 + 2*1) + (15 + 0.5 + 2*1 + 2*1) + желаемый margin-right для #col2 (0.5em) */</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">relative</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding-left</span><span class="sy0">:</span> <span class="re3">.5em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding-top</span><span class="sy0">:</span> <span class="re3">.5em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding-bottom</span><span class="sy0">:</span> <span class="re3">.5em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin</span><span class="sy0">:</span> <span class="re3">1em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">border</span><span class="sy0">:</span> <span class="re3">1em</span> <span class="kw2">solid</span> <span class="kw1">black</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="coMULTI">/*\*/</span><br />
<span class="sy0">*</span> html <span class="re0">#container</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">height</span><span class="sy0">:</span> <span class="re3"><span class="nu0">1</span>%</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<span class="coMULTI">/**/</span><br />
<br />
<span class="re1">.column</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">position</span><span class="sy0">:</span> <span class="kw2">relative</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">float</span><span class="sy0">:</span> <span class="kw1">left</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding-bottom</span><span class="sy0">:</span> <span class="re3">1002em</span> !important<span class="sy0">;</span> <span class="coMULTI">/* Фактически, padding-bottom = 2em */</span><br />
&nbsp; &nbsp; <span class="kw1">margin-bottom</span><span class="sy0">:</span> <span class="re3">-1000em</span> !important<span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">overflow</span><span class="sy0">:</span> <span class="kw2">hidden</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#content</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3"><span class="nu0">100</span>%</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">border</span><span class="sy0">:</span> <span class="re3">1em</span> <span class="kw2">solid</span> <span class="kw2">green</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding</span><span class="sy0">:</span> <span class="re3">1em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin-right</span><span class="sy0">:</span> <span class="re3">.5em</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#col1</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">10em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin-right</span><span class="sy0">:</span> <span class="re3">-<span class="nu0">100</span>%</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">padding</span><span class="sy0">:</span> <span class="re3">1em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">border</span><span class="sy0">:</span> <span class="re3">1em</span> <span class="kw2">solid</span> <span class="kw2">red</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="sy0">*</span><span class="re2">:first-</span>child<span class="coMULTI">/**/</span><span class="sy0">+</span>html <span class="re0">#col1</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">margin-left</span><span class="sy0">:</span> <span class="re3">4.5em</span><span class="sy0">;</span> <span class="coMULTI">/* #col1.paddingLeft + #col1.paddingRight + #col1.borderLeft + #col1.borderRight + #col2.желаемый_marginLeft */</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#col2</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">width</span><span class="sy0">:</span> <span class="re3">15em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin-right</span><span class="sy0">:</span> <span class="re3">-<span class="nu0">100</span>%</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">margin-left</span><span class="sy0">:</span> <span class="re3">14.5em</span><span class="sy0">;</span> <span class="coMULTI">/* #col1.paddingLeft + #col1.paddingRight + #col1.borderLeft + #col1.borderRight + #col2.желаемый_marginLeft + #col1.width */</span><br />
&nbsp; &nbsp; <span class="kw1">padding</span><span class="sy0">:</span> <span class="re3">1em</span><span class="sy0">;</span><br />
&nbsp; &nbsp; <span class="kw1">border</span><span class="sy0">:</span> <span class="re3">1em</span> <span class="kw2">solid</span> <span class="kw1">blue</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="sy0">*</span><span class="re2">:first-</span>child<span class="coMULTI">/**/</span><span class="sy0">+</span>html <span class="re0">#col2</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">margin-left</span><span class="sy0">:</span> <span class="re3">19em</span><span class="sy0">;</span> <span class="coMULTI">/* #col2.marginLeft + #col1.marginLeft */</span><br />
<span class="br0">&#125;</span><br />
<br />
<span class="re0">#footer</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="kw1">clear</span><span class="sy0">:</span> <span class="kw2">both</span><span class="sy0">;</span><br />
<span class="br0">&#125;</span>
        </div>
    </div>
</div>

<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/css/48-liquid-three-column-layout-with-right-sidebars/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/css/48-liquid-three-column-layout-with-right-sidebars/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>WassUp for WordPress и Windows</title>
		<link>http://blog.sjinks.pro/wordpress/45-wordpress-wassup-and-windows/</link>
		<comments>http://blog.sjinks.pro/wordpress/45-wordpress-wassup-and-windows/#comments</comments>
		<pubDate>Fri, 21 Mar 2008 00:25:16 +0000</pubDate>
		<dc:creator>Vladimir</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Wassup]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[XHTML]]></category>
		<category><![CDATA[ошибка]]></category>
		<category><![CDATA[патч]]></category>

		<guid isPermaLink="false">http://blog.sjinks.pro/php/45-wordpress-wassup-and-windows-2/</guid>
		<description><![CDATA[Как заставить Wassup работать под Windows Для WordPress есть замечательный плагин &#8212; Wassup. Хороший плагин, но вот беда: не дружит с Windows. Не дружит из-за того, что переменные хардкодить нельзя. Это в Unix/Linux каталоги разделяются &#8216;/&#8217;, а в Windows используется &#8216;\&#8217;. И вот из-за невнимательности автора плагин не работает в Windows. К счастью, всё лечится [...]<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/wordpress/45-wordpress-wassup-and-windows/">источник</a> обязательно.</p>]]></description>
			<content:encoded><![CDATA[<h2><em>Как заставить <a href="http://blog.sjinks.pro/tag/wassup/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  Wassup">Wassup</a> работать под <a href="http://blog.sjinks.pro/tag/windows/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  Windows">Windows</a></em></h2>
<p>Для <a href="http://blog.sjinks.pro/tag/wordpress/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  WordPress">WordPress</a> есть замечательный плагин &mdash; <a href="http://wordpress.org/extend/plugins/wassup/">Wassup</a>. Хороший плагин, но вот беда: не дружит с Windows. Не дружит из-за того, что переменные хардкодить нельзя. Это в Unix/Linux каталоги разделяются &#8216;/&#8217;, а в Windows используется &#8216;\&#8217;. И вот из-за невнимательности автора плагин не работает в Windows. К счастью, всё лечится очень просто.</p>
<p><a href="http://blog.sjinks.pro/tag/patch/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  патч">Патч</a> лежит <a href='http://static.sjinks.info/wp-content/uploads/2008/03/actionphp.diff' title='Патч для Wassup'>здесь</a>. Патч нужно применить к файлу <code>/wp-content/plugins/wassup/lib/action.<a href="http://blog.sjinks.pro/tag/php/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  PHP">php</a></code>.</p>
<p>Помимо исправления ошибки с разделителями каталогов, патч исправляет небольшую ошибку, связанную с невалидностью (инвалидностью?) генерируемого (X)<a href="http://blog.sjinks.pro/tag/html/" class="st_tag internal_tag" rel="tag" title="Записи, помеченные с  HTML">HTML</a>-кода.</p>
<p>© 2012 <a href="http://blog.sjinks.pro">Ars Longa, Vita Brevis</a>. Все права защищены. Перепубликация материалов без разрешения автора запрещена.</p>
<p>При использовании материалов блога наличие активной не закрытой от индексирования ссылки на <a href="http://blog.sjinks.pro/wordpress/45-wordpress-wassup-and-windows/">источник</a> обязательно.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.sjinks.pro/wordpress/45-wordpress-wassup-and-windows/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

