<?xml version='1.0' encoding='utf-8'?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<description>Webthings by Pete Boere</description>
<link>http://the-echoplex.net</link>
<atom:link href="http://http://the-echoplex.net/rss.php" rel="self" type="application/rss+xml" />
<title>The Echoplex</title>
<item>
<title>Png-6 &#8211; Png transparency support for legacy versions of Internet Explorer</title>
<description><![CDATA[<img style="margin:-9px 17px 0pt 8px;float:right;" src="http://www.the-echoplex.net/_assets/images/log/2010/png-6.png" width="232" height="110" />
<p>Not satisfied with existing solutions for Png transparency support in Internet Explorer 6 and 5.5, I decided to have a crack at it myself.</p> 
<p><strong>Png-6</strong> is a standalone (Java)script that converts inline png-24 images into &lsquo;png-6&rsquo; elements. Features include:</p>

<ul>
<li>Full CSS box-model support ( padding, border, width/height and margin )</li>
<li>Integration with third-party selector engines and/or standard dom methods for more precise image conversion</li>
<li>Requires no placeholder images to work</li>
</ul>

<p>In case you were wondering the &lsquo;6&rsquo; part is a homage to the popular browser. You can download a copy of the script or hot-link it from its <a href="http://code.google.com/p/png-6/">google code project page</a>.</p>]]></description>
<link><![CDATA[http://www.the-echoplex.net/log/png-6-png-transparency-support-for-legacy-versions-of-internet-explorer]]></link>
<guid><![CDATA[http://www.the-echoplex.net/log/png-6-png-transparency-support-for-legacy-versions-of-internet-explorer]]></guid>
<pubDate>Thu, 07 Jan 2010 23:03:46 +0000</pubDate>
</item>
<item>
<title>Enhancing Usability with Pseudo Protocols</title>
<description><![CDATA[<img alt="Status bar screenshot with the text &#39;javascript:;&#39;" class="fr" style="margin-left:10px;" src="http://www.the-echoplex.net/_assets/images/log/2009/pseudo-protocol-1.png"/>

<p class="lead">Often, when enhancing web pages with scripted behaviours, you find yourself creating anchor (link) tags as convenient event triggers. As these links usually have no meaningful <code>href</code> attribute, they provide little or confusing feedback to the user.</p>

<p>Take, for example, a typical web page with a scripted dynamic show/hide collapsing box. Adding a trigger link statically to the markup for this would be inappropriate, as it would exist solely for the purpose of a scripted event when JavaScript to handle the event may or may not be available.</p>

<p>The usual solution for this is to insert the link via JavaScript and give it some benign <code>href</code> attribute so that it looks and behaves like a normal link, perhaps empty, or with an empty statement using the JavaScript pseudo protocol:</p>

<div class="code code-html"><div><pre><code>&#60;a href="#"&#62;Toggle Panel&#60;/a&#62;
&#60;a href="javascript:;"&#62;Expand List&#60;/a&#62;</code></pre></div></div><!--/ code block -->

<img src="http://www.the-echoplex.net/_assets/images/log/2009/pseudo-protocol-1.png" alt="Status bar screenshot with the text &#39;javascript:;&#39;" class="fl" />

<p>The problem with this is that the status bar now gives no meaningful feedback as to what will happen when the link is clicked.</p>

<!--/split/--><span id="follow-on"></span>

<p>Screen readers can also struggle with fudged <code>href</code> links; in some configurations the link text is read in combination with the <code>href</code> attribute. So having a random or absent <code>href</code> value in this scenario could make the links quite confusing (<a href="http://yuiblog.com/blog/2008/01/23/empty-links/">see YUI blog article on empty links</a>).</p>

<h2>Alternative solution: use a <em>pseudo protocol</em></h2>

<p>By using an intuitively named pseudo protocol in the link <code>href</code>, we can provide useful tailored information for the user.</p>

<p>Pseudo protocol names take the format of any word followed by a colon. However, be careful to not clash with any other existing native protocols (mailto:, data:, :javascript, http: etc.) or user defined protocols on your site. This would be rare but is possible in more recent Gecko browers.</p>

<p>For demonstration, I&rsquo;ve created a generic pseudo protocol named &lsquo;action&rsquo; for all scripted event triggers; the following examples illustrate how this would look:</p>

<div class="code code-html"><div><pre><code>&#60;a href="action: Toggle panel"&#62;Would you like to see more?&#60;/a&#62;

&#60;a href="action: Show slide 2"&#62;2&#60;/a&#62;

&#60;a href="action: Click to process your request, 
   then we&#39;ll then redirect you to www.amazon.co.uk"&#62;Place order&#60;/a&#62;
</code></pre></div></div><!--/ code block -->

<p><a href="/demos/log/2009/pseudo-protocol/">View demo page</a>.</p>

<p>The status bar now displays helpful information when links are hovered or focused with the keyboard:</p>

<p class="tc" style="padding-bottom:0;margin:0 0 -30px -7px"><img src="http://www.the-echoplex.net/_assets/images/log/2009/pseudo-protocol-2.png" alt="Status bar screenshot with the text &#39;action: Toggle panel&#39;" /></p>


<h2>Drawbacks</h2>

<p>Using pseudo protocols in this way means you&rsquo;ll have to cancel the browsers&rsquo; default action when links are clicked, or the browser will get confused because you&rsquo;re asking it to use a protocol it doesn&rsquo;t understand. This shouldn&rsquo;t be a problem in this case, though, as these pseudo protocol links should exist purely as scripted event triggers.</p>]]></description>
<link><![CDATA[http://www.the-echoplex.net/log/enhancing-usability-with-pseudo-protocols]]></link>
<guid><![CDATA[http://www.the-echoplex.net/log/enhancing-usability-with-pseudo-protocols]]></guid>
<pubDate>Sun, 22 Nov 2009 22:13:42 +0000</pubDate>
</item>
<item>
<title>Hello HTML5!</title>
<description><![CDATA[<p class="tc"><img style="margin:-29px 0 -15px -10px" width="308" height="149" src="http://www.the-echoplex.net/_assets/images/log/2009/html-5.jpg" alt="" /></p>

<p class="lead">Here I&rsquo;d like to outline (for myself as much as anything) why I think the web should be using <abbr title="HyperText Markup Language 5th  Edition">HTML5</abbr> right now.</p>

<p>For the web standardista community <abbr title="Xtensible HyperText Markup Language">XHTML</abbr> has long been the benchmark for high quality front-end markup. But its promise &ndash; a future web of lean, semantic and multi-purpose <abbr title="Xtensible Markup Language">XML</abbr> &ndash; has not come to be.</p>

<p>I think XHTML is too pure in its ideals to fit with the sprawling &lsquo;do it yourself&rsquo; nature of web authoring, let alone lack of support by major browsers. It still has its place in the world, but for now it looks to go down as a transitional phase in the history of mainstream HTML. Which is ironic as the most practical version of XHTML for use on the web has been the transitional variant (I should note that using any transitional doctype is a compromise; it is intended to support legacy code until conversion to a <em>strict</em> doctype is practical).</p>

<p>For good reasons it&rsquo;s clear that XHTML has failed for 99% of what people are doing on the web right now.</p>

<p>Things that do not support XHTML 1 (of any variety):</p>

<ul>
<li>Microsoft Internet Explorer (cannot accept mime type application/xml)</li>
<li>Most <abbr title="What You See Is What You Get">WYSIWYG</abbr> editor generated markup</li>
<li>Most mashup generated markup</li>
<li>Most third party JavaScript widgets</li>
</ul>


<p>Things that XHTML 1 (of any variety) does not support:</p>

<ul>
<li>A rich set of semantic elements to choose from</li>
<li><code>Element.innerHTML</code> (core to every JavaScript library)</li>
<li>Inline JavaScript without ugly escaping</li>
<li>The target attribute on hyperlinks (which is not as bad as some would say, hence its inclusion in HTML5)</li>
</ul>

<!--/split/--><span id="follow-on"></span>


<h2>It&rsquo;s not all bad</h2>

<p>One of the reasons XHTML has been so enthusiastically adopted in the past is that it enforces a clean consistent markup style. Tag soup and font tags were awful, so the reaction in wanting to make the web strict XML was actually very beneficial; it has created an online community of designers and developers who appreciate and can author clean, maintainable and high quality markup.</p>

<h2>And now... HTML<em>5</em></h2>

<p>HTML5 for me represents a complete rethinking of the HTML specification based on the way the web has evolved. While I won&rsquo;t try to cover all the detail here (<a href="http://diveintohtml5.org/">as it has been done very well elsewhere</a>), I would like to pick a few details that capture how HTML5 has taken the web forward without breaking anything.</p>

<p>First look at the HTML5 doctype:</p>

<div class="code code-html"><div><pre><code>&#60;!DOCTYPE html&#62;</code></pre></div></div><!--/ code block -->

<p>Nice and simple isn&rsquo;t it. The good part is that it&rsquo;s not just a pretty face; it invokes full standards rendering mode in all browsers. This is more than be said for transitional doctypes that invoke the maddeningly named &lsquo;almost standards&rsquo; rendering mode in some browsers and &lsquo;standards&rsquo; mode in others. Like we need more cross-browser incompatibility.</p>

<p>With HTML5 you can even type it from memory, and know you&rsquo;re running your code in strict mode in all browsers.</p>

<p>Have you ever wondered why the type attribute is necessary in your style and script tags when there is only one styling language and one scripting language used with HTML? In HTML5 type attributes for these elements are now optional. An elegant move forward whilst remaining fully backwards compatible.</p>

<p>Forms get a substantial overhaul in HTML5. Form validation that is now handled by JavaScript on the client becomes native to the browser in HTML5. Form inputs now have a fairly extensive set of type options; and because the default input type is text, browsers that don&rsquo;t recognise the new input types can degrade gracefully.</p>

<p>The new semantic HTML5 elements, such as <code>nav</code>, <code>section</code>, <code>time</code> etc. can all be used now, with the caveat that <abbr title="The blessed Microsoft Internet Explorer">IE</abbr> does not style elements that it does not recognise. This can be easily fixed with <a href="http://html5shiv.googlecode.com/svn/trunk/html5.js">a little JavaScript bootstrapping</a>. 

<p>But for me a JavaScript dependency on this level does make the use of these new elements somewhat hard to justify, at least until the most recent version of IE can support the styling of these elements for users without JavaScript. It has been suggested that you could serve two versions of your markup with a little regular expression hackery &ndash; one for IE, one for everyone else &ndash; but that seems like overkill to me.</p>

<h2>Keeping it clean</h2>

<p>The only drawback I can think of with using the backwards compatible HTML5 features, over an XML type markup language, is the syntax rules. Because in HTML5 there is no requirement for lowercase tags and attributes or closing tags for all elements, it does lead to the probability of inconsistent and less readable markup. All these examples are valid HTML5:</p>

<div class="code code-html"><div><pre><code>&#60;DIV TITLE=shout&#62;&#60;/DIV&#62;
&#60;div title=&#8221;talk&#8221;&#62;&#60;/div&#62;

&#60;p&#62;Paragraph with no closing tag
&#60;p&#62;Paragraph with a closing tag&#60;/p&#62;

&#60;img src=&#8221;myimg.jpg&#8221; alt=&#8221;Where&#8217;s my close&#8221;&#62;
&#60;img src=&#8221;myimg.jpg&#8221; alt=&#8221;Here&#8221; /&#62; 

&#60;br&#62;
&#60;br /&#62;</code></pre></div></div><!--/ code block -->

<p>I personally don&rsquo;t think mixing the open/closed tag styles is doing anyone any favours. It just looks wrong if the author is making arbitrary decisions about when to close tags. The problem is the inconsistency; readable markup is consistent. Because HTML requires some tags to be closed it is better if they all open and close as they do in the XHTML standard.</p>]]></description>
<link><![CDATA[http://www.the-echoplex.net/log/hello-html5]]></link>
<guid><![CDATA[http://www.the-echoplex.net/log/hello-html5]]></guid>
<pubDate>Sun, 08 Nov 2009 16:11:22 +0000</pubDate>
</item>
<item>
<title>DOM branching</title>
<description><![CDATA[<p class="lead">As an interface, the <abbr title="Document Object Model">DOM</abbr> attracts a fair amount of critisism for its verbosity and some of the unintuitive mechanisms it provides.</p>


<img src="http://www.the-echoplex.net/_assets/images/log/2009-08/dom.png" class="fl" alt="" />

<p>It&rsquo;s also often derided for its omissions. I mean, why is there no <code>insertBefore</code> method, when an <code>insertAfter</code> method exists in the spec? Thankfully some changes are coming through; features like <code>getElementsByClassName</code> and <code>querySelectorAll</code> have quickly become standardised.</p>

<p>While much of the rather clunky DOM interface persists, library authors have been quite successful in creating abstractions for dealing with the DOM in a more intuitive way. Although even with library abstractions, one area that still causes me pain is the creation of nested DOM fragments.</p>

<p>In some situations you can use <code>innerHTML</code>. However, it&rsquo;s usually a hack for when you can&rsquo;t be bothered to do things the DOM way. Which, besides being a pain, is actually a lot more versatile and elegant from a code point of view.</p>

<p>So, in efforts to find a better solution, I&rsquo;ve created a few functions as part of <a href="http://code.google.com/p/jelly-javascript/">my library</a> that make creating elements and fragments using the DOM interface a lot more convenient. One utility for creating elements, named <code>createElement</code> (logically enough), and a related utility, named <code>createBranch</code>, for merging nodes into nested DOM fragments.</p>

<p>For a simple example, say you want to create some simple wrapper <abbr title="HyperText Markup Language">HTML</abbr> like below, and retain a reference to the inner element:</p>

<div class="code code-html"><div><pre><code>&#60;div id="widget-foo"&#62;
  &#60;div class="content"&#62;
  &#60;/div&#62;
&#60;/div&#62;
</code></pre></div></div>

<p>Using the default DOM interface you might do this:</p>

<div class="code code-js"><div><pre><code><span class="code-keywd">var</span> wrapper = document.createElement( <span class="code-str">&#39;div&#39;</span> );
wrapper.setAttribute( <span class="code-str">&#39;id&#39;</span>, <span class="code-str">&#39;widget-foo&#39;</span> );

<span class="code-keywd">var</span> inner = document.createElement( <span class="code-str">&#39;div&#39;</span> );
inner.className = <span class="code-str">&#39;content&#39;</span>;

wrapper.appendChild( inner );
</code></pre></div></div><!--/ code block -->


<p>Fairly long-winded compared to an <code>innerHTML</code> approach. But using the <code>createElement</code> utility (which I should note does not conflict with the document namesake) you can cut out some of the fat, while retaining the advantage of keeping the DOM references accessible.</p>

<!--/split/--><span id="follow-on"></span>

<div class="code code-js"><div><pre><code><span class="code-keywd">var</span> wrapper = createElement( <span class="code-str">&#39;#widget-foo&#39;</span> );
<span class="code-keywd">var</span> inner = createElement( <span class="code-str">&#39;.content&#39;</span> );

wrapper.appendChild( inner );</code></pre></div></div><!--/ code block -->

<p>You&rsquo;ll notice the argument passed in is a simple <abbr title="Cascading Style Sheets">CSS</abbr> selector. The default element type if not specified is a <code>div</code> otherwise you could write &lsquo;div.content&rsquo; explicitly, or &lsquo;p.content&rsquo; for a different element.</p>

<p>Taking things a step further, the <code>createBranch</code> utility merges elements defined with same syntax that are passed in as arguments.</p>

<div class="code code-js"><div><pre><code><span class="code-keywd">var</span> branch = createBranch( 
    <span class="code-str">&#39;#widget-foo&#39;</span>,  
        <span class="code-str">&#39;.content @:content&#39;</span> 
   );</code></pre></div></div><!--/ code block -->

<p>This creates the HTML structure, but instead of returning an element reference you get an object of references:</p>

<div class="code code-js"><div><pre><code>{
  root   : #widget-foo,
  div    : [ #widget-foo, .content ],
  content: [ .content ]
}</code></pre></div></div><!--/ code block -->

<p>The function collects references to all the created elements in a way similar to <code>getElementsByTagName</code>. The &#39;@:content&rsquo; declaration simply creates a direct named reference so we don&rsquo;t have to go digging when we need it later. 
Using the created branch is now as simple as this:</p>

<div class="code code-js"><div><pre><code>branch.content.innerHTML = <span class="code-str">&#39;Hello world&#39;</span>
document.body.appendChild( branch.root )</code></pre></div></div><!--/ code block -->

<p>More complicated structures can be achieved by passing in arrays as sibling groups:</p>

<div class="code code-js"><div><pre><code><span class="code-keywd">var</span> branch = createBranch( 
    <span class="code-str">&#39;#widget-foo&#39;</span>,  
        <span class="code-str">&#39;.content&#39;</span>, [ 
            <span class="code-str">&#39;h1 setText: "Introduction"&#39;</span>, 
            <span class="code-str">&#39;p setText: "DOM stands for Document Object Model."&#39;</span>    
        ]);</code></pre></div></div><!--/ code block -->


<p>Which would create the following DOM fragment:</p>

<div class="code code-js"><div><pre><code>&#60;div id="widget-foo"&#62;
  &#60;div class="content"&#62;
    &#60;h1&#62;Introduction&#60;/h1&#62;
    &#60;p&#62;DOM stands for Document Object Model.&#60;/p&#62;
  &#60;/div&#62;
&#60;/div&#62;</code></pre></div></div>



<p>Branches can also be nested, so creating something like an HTML table is manageable:</p>

<div class="code code-js"><div><pre><code><span class="code-keywd">var</span> thead = createBranch( <span class="code-str">&#39;thead&#39;</span>, <span class="code-str">&#39;tr&#39;</span>, 
   [ 
     <span class="code-str">&#39;th setText: "Pros"&#39;</span>, 
     <span class="code-str">&#39;th setText: "Cons"&#39;</span> 
   ]);
   
<span class="code-keywd">var</span> tbody = createBranch( <span class="code-str">&#39;tbody @:tbody&#39;</span>, 
   [
   createBranch( <span class="code-str">&#39;tr&#39;</span>,
      [ 
        <span class="code-str">&#39;td setText: "Fast"&#39;</span>, 
        <span class="code-str">&#39;td setText: "Expensive"&#39;</span> 
      ]),
   createBranch( <span class="code-str">&#39;tr&#39;</span>,
      [ 
        <span class="code-str">&#39;td setText: "Looks good"&#39;</span>, 
        <span class="code-str">&#39;td setText: "High Maintenence"&#39;</span> 
      ])
   ]);

<span class="code-keywd">var</span> table = createBranch( <span class="code-str">&#39;table.results&#39;</span>, [ thead, tbody ] );</code></pre></div></div><!--/ code block -->

<p>I have been using these utilities for a while now, and though they may not be perfect, they are definitely more practical to use than bare-bones DOM construction. I also find myself more inclined to use real DOM fragments rather than hacking away with <code>innerHTML</code>, which can only be a good thing.</p>

<p>The source for these utilities is freely available, under the conditions of an MIT license, over on the <a href="http://code.google.com/p/jelly-javascript/source/browse/trunk/src/core/elements.js">Jelly JavaScript project site</a>.</p>]]></description>
<link><![CDATA[http://www.the-echoplex.net/log/dom-branching]]></link>
<guid><![CDATA[http://www.the-echoplex.net/log/dom-branching]]></guid>
<pubDate>Fri, 28 Aug 2009 11:25:59 +0000</pubDate>
</item>
<item>
<title>How To: Style a HTML file upload control using CSS and JavaScript</title>
<description><![CDATA[<img src="http://www.the-echoplex.net/_assets/images/log/2009-08/upload-file-after.png" alt="Screenshot of the demo" class="fr" /><p class="lead">If you&rsquo;ve ever tried, you&rsquo;ll know that styling an html file upload control is like flogging a dead horse.</p>

<p>Due to the security issues of enabling any user to upload files directly to a server, html file upload controls have evolved to be pretty robust. You cannot write the value attribute of them with <abbr title="JavaScript">JS</abbr>; you can imagine what a malicious script could do with that! You cannot change the button text which is defined and locked down by the browser.</p>

<p>Because of the efforts of browsers to minimize the attack surface, most of the CSS properties we usually use to style form controls don&rsquo;t have any effect. This leads us, inevitably, to hybrid frontend workarounds if we want to manipulate the way these controls look on our page.</p>

<img src="http://www.the-echoplex.net/_assets/images/log/2009-08/upload-file-before.png" alt="Screenshot comparison of different browser handling of file upload controls" class="fl" />
<p>As you can see from this image, there is a fair amount of variation in the way browsers deal with the file upload control. Webkit differs the most by not showing the path to the file name you select, and since we can only reliably read the the actual file name with JS, we&rsquo;ll follow this pattern (I think the Webkit approach is the most elegant anyway).</p>

<!--/split/--><span id="follow-on"></span>

<h2>The spec</h2>

<p>What we&rsquo;re aiming for is a nice fat button where we can have full control over the button style and text. We want a solution that will behave nicely and consistently in all the browsers, and be versatile enough to cope with modifications and variations.</p>

<h2>The demo</h2>

<p>Check out the <a target="_blank" href="/demos/upload-file/">working demo here</a>.</p>

<h2>The details</h2>

<p>The html markup is pretty simple, we just want to create a button-like unit which can be placed anywhere in a form:</p>

<div class="code code-js"><div><pre><code>&#60;div class="file-upload-btn"&#62;
	&#60;label for="file-upload-1"&#62;Upload file&#60;/label&#62;
	&#60;input id="file-upload-1" type="file" name="uploaded" /&#62;
&#60;/div&#62;</code></pre></div></div>

<p>The main trick is in the CSS. What we&rsquo;ve done is place the upload field in an element with <code>display</code> set to <code>inline-block</code> and <code>overflow</code> set to <code>hidden</code>. We position the label over the field to create the button text. By making the upload field <code>font-size</code> very large we essentially create a large hit area that will give us the basic button functionality.</p>

<p>To customise the appearance, first we set the upload field opacity to 0 (a different property is needed for Internet Explorer as you can see in the source). Now we can add background images and border effects to create the look and feel. View the <a href="/demos/upload-file/file-upload.css" target="_blank">commented CSS</a> for the full treatment.</p>

<p>Using JS we have lazy-loaded the CSS file. One advantage of this is that we maintain a clean separation between our general site CSS and the UI element specific CSS; just tagging chunks of CSS onto a main file for every UI widget is an approach that will not scale for websites that have a growing number of JS dependant widgets. Another advantage is that the styles will only be applied if JS is available, so we can have graceful degredation with minimal effort.</p>

<p>I should note that the <a target="_blank" href="http://code.google.com/p/jelly-javascript/">Jelly Javascript</a> library is being used for this demo. However, you should be able to port the code to a library of your choice if you know your JS and chosen library well.</p>

<p>To create the uploaded file label, we bind a handler to the file upload <code>onchange</code> event which dynamically inserts (or removes) an element after the file upload element. Some other display issues are also addressed; view the <a target="_blank" href="/demos/upload-file/file-upload.js">commented JS</a> for the full details.</p>]]></description>
<link><![CDATA[http://www.the-echoplex.net/log/how-to-style-a-html-file-upload-control-using-css-and-javascript]]></link>
<guid><![CDATA[http://www.the-echoplex.net/log/how-to-style-a-html-file-upload-control-using-css-and-javascript]]></guid>
<pubDate>Thu, 20 Aug 2009 16:00:27 +0000</pubDate>
</item>
<item>
<title>Display woes, and community generated solutions</title>
<description><![CDATA[<p>A bizarre (and uncharacteristic) bug on the usually brilliant Firefox caused a stir over at <a href="http://www.zeldman.com/">Zeldman.com</a> yesterday.</p>

<p>To start with, some kind of guillotining bug on long content &ndash; more characteristic of a certain popular browser &ndash; was spoiling the display of long pages, truncating them by up to 50%.</p>

<p>An important fix to this spawned another problem, with the introduction of an unsightly flash of page background colour, making the page rendering somewhat less than slick.</p>

<p>A <a href="http://www.zeldman.com/2009/07/08/firefox-forces-red-background-flash/#9julyupdate">workaround</a>, although less than ideal, seems to fix the worst of the problem.</p>

<p>To my surprise <a href="http://www.zeldman.com/2009/07/08/firefox-forces-red-background-flash/#comment-44441">I had something to do with it</a>. What&rsquo;s more, Mr Zeldman <a href="http://www.zeldman.com/2009/07/08/firefox-forces-red-background-flash/#comment-44459">kindly offered</a> a copy of his excellent <a href="http://www.amazon.co.uk/gp/product/0321385551/ref=s9_simb_gw_xu_s0_p14_t1?pf_rd_m=A3P5ROKL5A1OLE&amp;pf_rd_s=center-1&amp;pf_rd_r=18Y4TKRF3MW4D44G0QMB&amp;pf_rd_t=101&amp;pf_rd_p=467198433&amp;pf_rd_i=468294">designing with web standards</a> (third edition) as a gift!</p>

<p>I love a happy ending.</p>]]></description>
<link><![CDATA[http://www.the-echoplex.net/log/display-woes-and-community-generated-solutions]]></link>
<guid><![CDATA[http://www.the-echoplex.net/log/display-woes-and-community-generated-solutions]]></guid>
<pubDate>Thu, 09 Jul 2009 23:02:20 +0000</pubDate>
</item>
<item>
<title>Man in the Mirror</title>
<description><![CDATA[<p>With the recent Jacko fervour, his tune <em>Man in the Mirror</em> has been getting a fresh lease of life.</p>

<p>It&rsquo;s never been a favourite tune of mine &ndash; actually I&rsquo;m not much of a Michael Jackson fan &ndash; but this <a href="http://www.youtube.com/watch?v=rUynZLfW134">stripped down cover version by Gary Mitchell</a> is a lot more soulful to me than the full on production of Jackson&rsquo;s version.</p>   

<p>The sound quality isn&rsquo;t that good (and unfortunately it cuts a little short) but musically it hits the sweet spot.</p>]]></description>
<link><![CDATA[http://www.the-echoplex.net/log/man-in-the-mirror]]></link>
<guid><![CDATA[http://www.the-echoplex.net/log/man-in-the-mirror]]></guid>
<pubDate>Mon, 06 Jul 2009 23:39:44 +0000</pubDate>
</item>
<item>
<title>Libby</title>
<description><![CDATA[<p>Our new arrival!</p>

<div class="flickr-slideshow"><!--[if IE]><object width="440" height="293" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"><param name="movie" value="http://www.flickr.com/apps/slideshow/show.swf?v=71649" /><param name="allowFullScreen" value="true" /><param name="flashvars" value="offsite=true&amp;lang=en-us&amp;page_show_url=%2Fsearch%2Fshow%2F%3Fq%3Dlibby%2B2009%252F06%26w%3D99004967%2540N00&amp;page_show_back_url=%2Fsearch%2F%3Fq%3Dlibby%2B2009%252F06%26w%3D99004967%2540N00&amp;method=flickr.photos.search&amp;api_params_str=&amp;api_text=libby+2009%2F06&amp;api_tag_mode=bool&amp;api_user_id=99004967%40N00&amp;api_safe_search=3&amp;api_content_type=7&amp;api_media=all&amp;api_sort=relevance&amp;jump_to=&amp;start_index=0" /><a href="http://www.adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></object><![endif]--><!--[if !IE]>--><object type="application/x-shockwave-flash" data="http://www.flickr.com/apps/slideshow/show.swf?v=71649" width="440" height="293" class="flash-object"><param name="allowFullScreen" value="true" /><param name="flashvars" value="offsite=true&amp;lang=en-us&amp;page_show_url=%2Fsearch%2Fshow%2F%3Fq%3Dlibby%2B2009%252F06%26w%3D99004967%2540N00&amp;page_show_back_url=%2Fsearch%2F%3Fq%3Dlibby%2B2009%252F06%26w%3D99004967%2540N00&amp;method=flickr.photos.search&amp;api_params_str=&amp;api_text=libby+2009%2F06&amp;api_tag_mode=bool&amp;api_user_id=99004967%40N00&amp;api_safe_search=3&amp;api_content_type=7&amp;api_media=all&amp;api_sort=relevance&amp;jump_to=&amp;start_index=0" /><a href="http://www.adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></object><!--<![endif]-->
</div><!--/ flickr-slideshow -->]]></description>
<link><![CDATA[http://www.the-echoplex.net/log/libby]]></link>
<guid><![CDATA[http://www.the-echoplex.net/log/libby]]></guid>
<pubDate>Tue, 30 Jun 2009 11:31:01 +0000</pubDate>
</item>
<item>
<title>Climb Afghanistan with Mountain Unity International</title>
<description><![CDATA[<p>Some friends of ours are involved in an organization called <a href="http://www.mountainunity.org/">Mountain Unity International</a>, which aims to promote tourism in North Eastern Afghanistan.</p>

<p>This could be of special interest if you, or anyone you know, has a passion for mountaineering. Regardless, it&rsquo;s worth checking out as it shows how much more there is to this country than the headlines would have us believe.</p>

<div class="youtube-video"><!--[if IE]><object width="440" height="275" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"><param name="movie" value="http://www.youtube.com/v/5ky_Qxm62rA&amp;hl=en&amp;fs=1&amp;rel=0&amp;showsearch=0&amp;showinfo=0" /><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><a href="http://www.adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></object><![endif]--><!--[if !IE]>--><object type="application/x-shockwave-flash" data="http://www.youtube.com/v/5ky_Qxm62rA&amp;hl=en&amp;fs=1&amp;rel=0&amp;showsearch=0&amp;showinfo=0" width="440" height="275" class="flash-object"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><a href="http://www.adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></object><!--<![endif]-->
</div><!--/ youtube-video -->]]></description>
<link><![CDATA[http://www.the-echoplex.net/log/climb-afghanistan-with-mountain-unity-international]]></link>
<guid><![CDATA[http://www.the-echoplex.net/log/climb-afghanistan-with-mountain-unity-international]]></guid>
<pubDate>Mon, 01 Jun 2009 22:33:22 +0000</pubDate>
</item>
<item>
<title>SWFObject for PHP</title>
<description><![CDATA[<p class="lead">A simple PHP class for embedding Flash objects statically into your pages.</p>

<p>Static embedding has several advantages over the JavaScript injection technique:</p>

<ul>
<li>Works when JavaScript is unavailable
</li><li>Is more robust; unreliance on JavaScript means if an earlier script error halts the  interpreter, the SWFObject doesn&rsquo;t die as well
</li><li>Search engines can access statically embedded Flash content (text and links)  more effectively
</li><li>Static embedding makes Flash possible in RSS feeds 
</li></ul>

<!--/split/--><span id="follow-on"></span>


<p>I also like the way this method avoids the mess of printing out client script variables, when feeding in from a server-side data source for example.</p>

<p>As you can see it&rsquo;s fairly simple, but gives you a lot of control over what parameters and attributes are applied. It generates the same &lsquo;flash satay&rsquo; as the <a href="http://code.google.com/p/swfobject/wiki/documentation#STEP_1:_Embed_both_Flash_content_and_alternative_content_using_s">SWFObject 2.0 static publishing method</a>.</p>


<div class="code code-js"><div><pre><code><span class="code-keywd">class</span> FlashObject {
   
   <span class="code-keywd">public</span> $attributes = <span class="code-meth">array</span>();
   <span class="code-keywd">public</span> $params = <span class="code-meth">array</span>();
   <span class="code-keywd">public</span> $variables = <span class="code-meth">array</span>();
   <span class="code-keywd">public</span> $path;
   <span class="code-keywd">public</span> $width;
   <span class="code-keywd">public</span> $height;
   <span class="code-keywd">public</span> $id;
   <span class="code-keywd">public</span> static $default_alt_content = <span class="code-str">&#39;&#60;a href="http://www.adobe.com/go/getflashplayer"&#62;&#60;img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /&#62;&#60;/a&#62;&#39;</span>;
     
   <span class="code-keywd">function</span> __construct ($path = <span class="code-str">&#39;#&#39;</span>, $width = <span class="code-num">100</span>, $height = <span class="code-num">100</span>, $alt_content = <span class="code-str">&#39;&#39;</span>, $id = <span class="code-str">&#39;&#39;</span>) {
      <span class="code-keywd">$this</span>-<span class="code-gram">&#62;</span>path = $path;
      <span class="code-keywd">$this</span>-<span class="code-gram">&#62;</span>width = $width;
      <span class="code-keywd">$this</span>-<span class="code-gram">&#62;</span>height = $height; 
      <span class="code-keywd">$this</span>-<span class="code-gram">&#62;</span>alt_content = !empty($alt_content) ? $alt_content : <span class="code-keywd">$this</span>-<span class="code-gram">&#62;</span>default_alt_content; 
      <span class="code-keywd">$this</span>-<span class="code-gram">&#62;</span>id = !empty($id) ? <span class="code-str">&#39; id="&#39;</span> . $id . <span class="code-str">&#39;"&#39;</span> : <span class="code-str">&#39;&#39;</span>;
   }
   
   <span class="code-keywd">function</span> setAltContent ($str) {   
      <span class="code-keywd">$this</span>-<span class="code-gram">&#62;</span>alt_content = $str;
   }   
   <span class="code-keywd">function</span> setVariables ($arr) {
      <span class="code-keywd">$this</span>-<span class="code-gram">&#62;</span>variables = $arr;
   }
   <span class="code-keywd">function</span> setParams ($arr) {
      <span class="code-keywd">$this</span>-<span class="code-gram">&#62;</span>params = $arr;
   }
   <span class="code-keywd">function</span> setAttributes ($arr) {
      <span class="code-keywd">$this</span>-<span class="code-gram">&#62;</span>attributes = $arr;
   }
   <span class="code-keywd">function</span> setId ($id) {
      <span class="code-keywd">$this</span>-<span class="code-gram">&#62;</span>id = $id;
   }
   
   <span class="code-keywd">function</span> get () {
      $attributes = <span class="code-str">&#39;&#39;</span>;
      $params = <span class="code-str">&#39;&#39;</span>;
      $variables = <span class="code-meth">array</span>();
      <span class="code-keywd">foreach</span> (<span class="code-keywd">$this</span>-<span class="code-gram">&#62;</span>attributes as $key=<span class="code-gram">&#62;</span>$val) {
         <span class="code-keywd">if</span> ($key !== <span class="code-str">&#39;id&#39;</span>) { $attributes .= <span class="code-str">&#39; &#39;</span> . $key . <span class="code-str">&#39;=&#39;</span> . <span class="code-str">&#39;"&#39;</span> . $val . <span class="code-str">&#39;"&#39;</span>; }
      }
      <span class="code-keywd">foreach</span> (<span class="code-keywd">$this</span>-<span class="code-gram">&#62;</span>params as $key=<span class="code-gram">&#62;</span>$val) {
         $params .= <span class="code-str">"&#60;param name=&#92;"{$key}&#92;" value=&#92;"{$val}&#92;" /&#62;";</span>   
      }
      <span class="code-keywd">foreach</span> (<span class="code-keywd">$this</span>-<span class="code-gram">&#62;</span>variables as $key=<span class="code-gram">&#62;</span>$val) {
         $variables[] = $key . <span class="code-str">&#39;=&#39;</span> . urlencode($val);
      }
      <span class="code-keywd">if</span> ( count($variables) ) {
         $params .= <span class="code-str">"&#60;param name=&#92;"flashvars&#92;" value=&#92;""</span> . implode(<span class="code-str">&#39;&amp;&#39;</span>, $variables) . <span class="code-str">"&#92;" /&#62;"</span>;
      }
      $str = <span class="code-str">"&#60;object classid=&#92;"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000&#92;" width=&#92;"{<span class="code-keywd">$this</span>->width}&#92;" height=&#92;"{<span class="code-keywd">$this</span>->height}&#92;"{<span class="code-keywd">$this</span>->id}{$attributes}&#62;"</span>;
      $str .= <span class="code-str">"&#60;param name=&#92;"movie&#92;" value=&#92;"{<span class="code-keywd">$this</span>-&#62;path}&#92;" /&#62;"</span>;
      $str .= $params;
      $str .= <span class="code-str">&#39;&#60;!--[if !IE]&#62;--&#62;&#39;</span>;
      $str .= <span class="code-str">"&#60;object type=&#92;"application/x-shockwave-flash&#92;" data=&#92;"{<span class="code-keywd">$this</span>->path}&#92;" width=&#92;"{<span class="code-keywd">$this</span>->width}&#92;" height=&#92;"{<span class="code-keywd">$this</span>->height}&#92;"{$attributes}&#62;"</span>;
      $str .= $params;
      $str .= <span class="code-str">&#39;&#60;!--&#60;![endif]--&#62;&#39;</span>;
      $str .= <span class="code-keywd">$this</span>-&#62;alt_content;
      $str .= <span class="code-str">&#39;&#60;!--[if !IE]&#62;--&#62;&#39;</span>;
      $str .= <span class="code-str">&#39;&#60;/object&#62;&#39;</span>;
      $str .= <span class="code-str">&#39;&#60;!--&#60;![endif]--&#62;&#39;</span>;      
      $str .= <span class="code-str">&#39;&#60;/object&#62;&#39;</span>;            
      <span class="code-keywd">return</span> $str;
   }
   
   <span class="code-keywd">function</span> render () {
      echo <span class="code-keywd">$this</span>-<span class="code-gram">&#62;</span>get();
   }
}</code></pre></div></div><!--/ code block -->

<p>Example use:</p>

<div class="code code-js"><div><pre><code>$swiff = <span class="code-keywd">new</span> FlashObject(<span class="code-str">&#39;path/to/file.swf&#39;</span>, <span class="code-num">200</span>, <span class="code-num">300</span>, <span class="code-str">&#39;Alternative Content here&#39;</span>, <span class="code-str">&#39;Myid&#39;</span>); 

$swiff-<span class="code-gram">&#62;</span>setVariables(<span class="code-meth">array</span>( 
    <span class="code-str">&#39;hello&#39;</span> =<span class="code-gram">&#62;</span> <span class="code-str">&#39;world&#39;</span>, 
    <span class="code-str">&#39;myVar&#39;</span> =<span class="code-gram">&#62;</span> <span class="code-str">&#39;200&#39;</span>  
   )); 


$swiff-<span class="code-gram">&#62;</span>setParams(<span class="code-meth">array</span>( 
    <span class="code-str">&#39;wmode&#39;</span> =<span class="code-gram">&#62;</span> <span class="code-str">&#39;transparent&#39;</span>  
   )); 

<span class="code-comm">// Print out directly
</span>$swiff-<span class="code-gram">&#62;</span>render();  

<span class="code-comm">// Or assign for later use
</span>$mySwiff = $swiff-<span class="code-gram">&#62;</span>get();</code></pre></div></div><!--/ code block -->]]></description>
<link><![CDATA[http://www.the-echoplex.net/log/swfobject-for-php]]></link>
<guid><![CDATA[http://www.the-echoplex.net/log/swfobject-for-php]]></guid>
<pubDate>Thu, 12 Mar 2009 22:55:50 +0000</pubDate>
</item>
<item>
<title>Tooltips that matter</title>
<description><![CDATA[<p class="lead">It is almost a convention now that developers are repeating link text as tooltips in main navigation areas; this is probably based on a misunderstanding that tooltips will <em>always</em> aid usability.</p>

<p>If a link tooltip merely repeats the link text it will actually hurt usability by creating more information &lsquo;noise&rsquo; for the user to deal with.</p>

<p>Tooltips, when used correctly, can be an excellent and necessary augmentation to text links or icons; providing further description on demand, and removing any potential ambiguity. In some situations they are a necessity, such as in desktop software or web applications that rely heavily on icons to streamline the user interface. When writing content for the web, though, they should be used sparingly and only in certain contexts.</p>

<!--/split/-->

<p class="indent"><strong class="highlight">Acronyms and abbreviations</strong> should be marked up with <code>acronym</code> and <code>abbr</code> tags respectively, and have tooltips displaying what they stand for in expanded form. In my opinion, this should be done at the first occurrence on every page and not repeated for every occurrence on every page, as it looks messy and cluttered if there are multiple instances on a page.</p>
<p class="indent"><strong class="highlight">Text links</strong> should be written in an intuitive way as possible so users know where they are going if they click through. Sometimes, however, it may not be possible to do this elegantly, or the link may require some supplementary information relating to browser behaviour (e.g. link opens in a new window). In this case tooltips can help if they are well written, and actually contribute useful information rather than merely repeating the link text.</p>
<p class="indent"><strong class="highlight">Images</strong> can benefit from tooltips as a way of providing caption text (well demonstrated by Google with their search page masthead). However, it is usually preferable, for ease of use, to have caption text visible on the page rather than hidden in a tooltip.</p>

<p>Internet Explorer plays some havoc with tooltip behaviour by turning image alternative text into tooltips; to circumnavigate this add an empty title attribute to your image tags.</p>]]></description>
<link><![CDATA[http://www.the-echoplex.net/log/tooltips-that-matter]]></link>
<guid><![CDATA[http://www.the-echoplex.net/log/tooltips-that-matter]]></guid>
<pubDate>Sat, 24 Jan 2009 10:36:38 +0000</pubDate>
</item>
<item>
<title>&#8216;Q&#8217; &#8211; A CSS Selector Engine</title>
<description><![CDATA[<p class="lead">One of the best things to happen to JavaScript in recent times is the rise of <abbr title="Cascading Style Sheets">CSS</abbr> style selector engines.</p>

<p><span class="dc">T</span>he power of using an already familiar CSS syntax to gather elements is very satisfying,  especially if previously you have been used to using bare-bones <abbr title="Document Object Model">DOM</abbr> methods. Their obvious appeal has made them central to most of the major frameworks in use today, and although they have been around for <a href="http://paulirish.com/2008/javascript-css-selector-engine-timeline/">some time</a>, a battle still continues within the developer community over which implementation is the fastest and most complete.</p>

<!--/split/--><span id="follow-on"></span>

<p>The days for this ongoing contest are numbered now though &ndash; with the advent of the <a href="http://www.w3.org/TR/selectors-api/">Selectors <abbr title="Application Programming Interface">API</abbr></a>, <code>querySelector</code> and <code>querySelectorAll</code> will soon be available in all major browsers. But, alas, the older browsers linger well beyond their welcome, so the non-native selector engines will endure, for a while at least.</p>

<p>Since I&rsquo;ve been working on a <a href="/projects">library</a> for my projects, and had been lacking a descent selector engine, I decided to have a shot at building one to suit my needs, and fit within the existing library code.</p>

<h2>Introducing Q</h2>

<p>Ideally I wanted the engine to follow as closely as possible the behaviour of <code>querySelector(All)</code> so its functionality would be consistent whether the native API is supported or not. This meant cutting out a few features that are fairly common in other selector engines, such as the non-standard <code>[attribute!=value]</code> (instead you can write <code>:not([attribute=value])</code>) and the <code>:contains</code> pseudo class which has since been removed from the specification. Otherwise the selector support is as complete as is possible, or sensible, using JavaScript:</p>

<div class="ca" style="padding:5px 0 10px;">
<ul class="fl">
<li>*</li>
<li>div</li>
<li>div p</li>
<li>div > p</li>
<li>div + p</li>
<li>div ~ p</li>
<li>*[class]</li>
<li>*[class=foo]</li>
<li>*[class~=foo]</li>
<li>*[class^=foo]</li>
<li>*[class$=foo]</li>
<li>*[class*=foo]</li>
<li>*[hreflang|=en]</li>
</ul>
<ul class="fl">
<li>*:nth-child(n)</li>
<li>*:nth-last-child(n)</li>
<li>*:nth-of-type(n)</li>
<li>*:nth-last-of-type(n)</li>
<li>*:first-child</li>
<li>*:last-child</li>
<li>*:first-of-type</li>
<li>*:last-of-type</li>
<li>*:only-child</li>
<li>*:only-of-type</li>
<li>*:root</li>
<li>*:target</li>
<li>*:empty</li>
</ul>
<ul class="fl">
<li>*:enabled</li>
<li>*:disabled</li>
<li>*:checked</li>
<li>*:not(div)</li>
</ul>
</div>
<p>Some example usage:</p>
<div class="code code-js"><div><pre><code><span class="code-comm">// Function returns a static array of nodes
</span><span class="code-keywd">var</span> collection <span class="code-gram">=</span> Q<span class="code-gram">(</span><span class="code-str">&#39;#myid div.myclass&#39;</span><span class="code-gram">)</span>;  

<span class="code-comm">// Get first element in the list
</span><span class="code-keywd">var</span> first <span class="code-gram">=</span> collection<span class="code-gram">[</span><span class="code-num">0</span><span class="code-gram">]</span>;  

<span class="code-comm">// Loop using array methods
</span>collection.<span class="code-meth">each</span><span class="code-gram">(</span><span class="code-keywd">function</span> <span class="code-gram">(</span>el<span class="code-gram">) {</span>   
   <span class="code-comm">// processing...
</span><span class="code-gram">})</span>;

<span class="code-comm">// Specify an initial context node (document is used by default)
</span><span class="code-keywd">var</span> node <span class="code-gram">=</span> document.<span class="code-meth">getElementById</span><span class="code-gram">(</span><span class="code-str">&#39;myid&#39;</span><span class="code-gram">)</span>;
<span class="code-keywd">var</span> collection <span class="code-gram">=</span> Q<span class="code-gram">(</span>node, <span class="code-str">&#39;a&#39;</span><span class="code-gram">)</span>; 

<span class="code-comm">// Complicated selector
</span><span class="code-keywd">var</span> collection <span class="code-gram">=</span> Q<span class="code-gram">(</span><span class="code-str">&#39;div+div+div>li:not(:last-child)&#39;</span><span class="code-gram">)</span>;</code></pre></div></div><!--/ code block -->

<h2>How does it perform?</h2>
<p>Q is <a href="/demos/slickspeed">pretty fast</a> when run through the <a href="http://mootools.net/slickspeed/">Slickspeed</a> test. It also has good  accuracy in returned result sets (more on this below).</p>
<p>From my tests, <a href="http://code.google.com/p/base2/">base2</a> and <a href="http://code.google.com/p/domassistant/">DOMAssistant</a> usually come out top in terms of speed across a large range of selectors, but if you run the same test through your machine you will probably get different results depending on what computer, browser and platform combination you are using.</p>

<h2>Lessons learned</h2>
<p>Using the slickspeed test suite and testing engines in different browsers and machines has revealed some surprising results. Engines faster in one combination perform slower and/or turn up different results in other combinations. This makes the question of which one is &lsquo;best&rsquo; a little slippery, even if basing judgement on speed alone.</p>
<p>The most crucial aspect, apart from speed, when judging an engine&rsquo;s performance should be the accuracy with which it can return results across different browsers. You could argue that incomplete support for a selector that will rarely get used is not significant, but personally, I think it is. Technology should do what it promises; <code>p:nth-last-of-type(-2n+3)</code> may never get used, but knowing it&rsquo;s avaliable makes a difference to how confidently I can use the API. At least there is then the opportunity to discover, through experience, where the real-world uses are for the more esoteric selectors.</p>

<h2>Download</h2>
<p>If you want to try the Q selector engine in your own projects, you can download it in standalone form on <a href="http://code.google.com/p/q-selector-engine/downloads/detail?name=Q-min.js&amp;can=2&amp;q=#makechanges">Google Code</a>, licensing is <a href="http://www.opensource.org/licenses/mit-license.php">MIT style</a>.</p>]]></description>
<link><![CDATA[http://www.the-echoplex.net/log/q-a-css-selector-engine]]></link>
<guid><![CDATA[http://www.the-echoplex.net/log/q-a-css-selector-engine]]></guid>
<pubDate>Tue, 13 Jan 2009 11:04:55 +0000</pubDate>
</item>
<item>
<title>CSS isn&#8217;t dead</title>
<description><![CDATA[<p class="lead"><abbr title="Cascading Style Sheets">CSS</abbr> has been getting some flak lately: accused of being an ineffective technology, some are suggesting it should be remodelled or <a href="http://blog.360.yahoo.com/blog-TBPekxc1dLNy5DOloPfzVvFIVOWMB0li?p=944">replaced entirely</a>.</p>
<p>Some of the recent arguments against CSS are:</p>
<ul>
<li>You always have to add excessive markup &lsquo;cruft&rsquo; to get the job done</li>
<li>Selectors can&rsquo;t target ancestors or previous siblings (as you can in JavaScript)</li>
<li>It&rsquo;s an ineffective tool for laying out pages</li>
</ul>

<!--/split/--><span id="follow-on"></span>

<h3>You always have to add excessive markup &lsquo;cruft&rsquo; to get the job done</h3>
<p>The problem at the root of this complaint is more to do with bad browser CSS implementations than with CSS itself; basically, web authors have been using a crippled subset of CSS for so long that most have forgotten, or never learned how to use a more complete implementation. IE6, dominating the browser market for such a long time, has meant developers have had no choice but to avoid using child selectors, adjacent sibling selectors, attribute selectors and class chaining. But the potential in these &lsquo;missing parts&rsquo; is enormous when you take advantage of them.</p>
<p class="indent"><strong><a href="http://www.w3.org/TR/CSS21/selector.html#child-selectors">Child selectors</a></strong> alone greatly decrease the need for markup cruft, and make stylesheet declarations more compact, precise and expressive.</p>
<p class="indent"><strong><a href="http://www.w3.org/TR/CSS21/selector.html#attribute-selectors">Attribute selectors</a></strong> can be used to target attribute prefixes e.g <code>div[class^="column-"]</code> would target div elements that have a class-name beginning with &lsquo;column-&rsquo;.You could apply styles to all your column-<em><strong>n</strong></em> classed elements without having to add extra styling hooks. Other uses include regular attribute targeting, which saves us having to add more markup e.g. <code>input[type="text"]</code>.</p>
<p class="indent"><strong><a href="http://www.w3.org/TR/CSS21/selector.html#class-html">Class chaining</a></strong> enables us to create more sophisticated inheritance patterns in our code, again saving us time and markup while making our stylesheets more intelligent.</p>
<p>That&rsquo;s just the simple stuff, currently supported in all non-IE6 browsers. CSS still has much more:</p>
<ul>
<li>Generated content</li>
<li>CSS3 selectors nth-child etc.</li>
<li>:not(.foo)</li>
<li>:first-child / :last-child</li>
</ul>
<p>This makes a pretty powerful toolset; all we need is browsers that support these standards.</p>
<h3>Selectors can&rsquo;t target ancestors or previous siblings</h3>
<p>Given the power of CSS selectors, if you need to select nodes in all directions, you&rsquo;re probably doing something wrong. CSS works pretty hard to display the page in response to every mouse event and actions that cause page re-flow, so I expect the limitation is largely due to performance, which is pretty reasonable.</p>
<h3>It&rsquo;s an ineffective tool for laying out pages</h3>
<p>For me, this argument is the only one that holds some weight. But again, with browsers that implement the standards correctly, CSS layout isn&rsquo;t that hard, just a little awkward sometimes.</p>
<h3>To wrap up</h3>
<p>I still think CSS is ok, it&rsquo;s outdated browsers that are the problem.
What I&rsquo;d like to know is how to get users and IT departments to upgrade more often :)</p>]]></description>
<link><![CDATA[http://www.the-echoplex.net/log/css-isnt-dead]]></link>
<guid><![CDATA[http://www.the-echoplex.net/log/css-isnt-dead]]></guid>
<pubDate>Sat, 03 Jan 2009 12:32:20 +0000</pubDate>
</item>
<item>
<title>Hello Interweb</title>
<description><![CDATA[<p>This is a first post for the-echoplex.net!</p>
<p>It&rsquo;s a little sparse around here, but it will grow.</p>]]></description>
<link><![CDATA[http://www.the-echoplex.net/log/hello-interweb]]></link>
<guid><![CDATA[http://www.the-echoplex.net/log/hello-interweb]]></guid>
<pubDate>Mon, 29 Dec 2008 16:00:08 +0000</pubDate>
</item>
</channel>
</rss>