<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Lea Verou</title>
	
	<link>http://leaverou.me</link>
	<description>Thoughts on web design, web development and usability</description>
	<lastBuildDate>Sun, 22 Aug 2010 22:19:22 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/leaverou" /><feedburner:info uri="leaverou" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Automatic login via notification emails?</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/6DLVBkoZHps/</link>
		<comments>http://leaverou.me/2010/08/automatic-login-via-notification-emails/#comments</comments>
		<pubDate>Sat, 14 Aug 2010 04:06:58 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Thoughts]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[usability]]></category>
		<category><![CDATA[usability vs security]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=641</guid>
		<description><![CDATA[A couple hours ago, I received a notification email from Goodreads and unlike usually, I decided to actually visit the site (by the way, I believe that Goodreads, i.e. a last.fm for books, is an awesome idea but poorly implemented).When I did, I was quite annoyed to find out that I wasn&#8217;t already logged in, so [...]]]></description>
			<content:encoded><![CDATA[
<p><img class="alignleft size-full wp-image-642" title="Email notification example (via Twitter)" src="http://leaverou.me/wp-content/uploads/2010/08/twitter-notification.png" alt="Screenshot of a Twitter email notification" width="300" height="197" />A couple hours ago, I received a notification email from <a href="http://www.goodreads.com/" target="_blank">Goodreads</a> and unlike usually, I decided to actually visit the site (by the way, I believe that Goodreads, i.e. a last.fm for books, is an awesome idea but poorly implemented).When I did, I was quite annoyed to find out that I wasn&#8217;t already logged in, so I had to remember which one of my many passwords I had used for it and try them one by one. This is not a Goodreads fail, but a fairly common nuisance, since most (if not all) social websites behave that way.</p>
<p><em>&#8220;What if there was some magic involved?&#8221;</em> Bill Scott &amp; Theresa Neil advise interaction designers to ask themselves in <a href="http://designingwebinterfaces.com/" target="_blank">a book I&#8217;m currently reading</a> (highly recommended by the way). Well, I guess, if there <em>was </em>some magic involved, <strong>the site would &#8220;understand&#8221; that my click was initiated from an email and would automatically log me in and let me view whatever I was trying to</strong>.<span id="more-641"></span></p>
<p>What&#8217;s the point of asking for a password if the user can prove they have access to the associated email account? Such access is usually all that&#8217;s needed for someone to break into an account, theirs or not (via the forgotten password feature). So, it doesn&#8217;t help security much, just makes it slightly more time-consuming for potential impostors, while turning legitimate users with a weak memory (like yours truly) away from the site.</p>
<p>I&#8217;m not sure whether it&#8217;s a good or a stupid idea, I&#8217;m not really suggesting it, just expressing a thought. <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
I have some concerns myself too:</p>
<ol>
<li>It&#8217;s definitely <strong>harder to implement</strong>.</li>
<li>All links sent in notification emails must contain some special token, like reset password links do (I&#8217;ve never seen it implemented otherwise). The tokens in reset password links expire after a while, so probably these should too, for security reasons. And what happens after that? A regular login is required? Doesn&#8217;t this render the whole idea a bit pointless, since notification emails are frequently read 1+ days after they&#8217;re sent?</li>
<li>Usually a frequent user receives a bunch of email notifications per day. <strong>Isn&#8217;t it a bit too risky to have dozens of such powerful emails floating around in your inbox?</strong> On the other hand, it doesn&#8217;t seem more dangerous than using the &#8220;remember me&#8221; feature while logging in: Anyone that manages to get ahold of your laptop for a minute is able to use your account in most SN sites, one way or another. <strong>However, the &#8220;remember me&#8221; feature is a classic case where usability triumphed security</strong>, at least in cases where the computer isn&#8217;t shared.</li>
<li>Thinking of the &#8220;remember me&#8221; feature gives me another idea: It could be <strong>optional and active by default</strong>. Perhaps with a link to easily deactivate the feature in every such email. On the other hand, more options = more confusion.</li>
<li>Also, to avoid the issues stated in #3, this feature could be activated <strong>only if the user in question was inactive</strong> for a while. <strong>Frequent users don&#8217;t need it</strong> that much and even if they did, they don&#8217;t run away so easily, so it&#8217;s not as crucial.</li>
</ol>
<p><strong>What do you think? Mostly useful or mostly evil? </strong></p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/6DLVBkoZHps" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2010/08/automatic-login-via-notification-emails/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://leaverou.me/2010/08/automatic-login-via-notification-emails/</feedburner:origLink></item>
		<item>
		<title>Lea Verou @ Front-Trends 2010</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/dRzZBdztsJQ/</link>
		<comments>http://leaverou.me/2010/08/lea-verou-at-front-trends-2010/#comments</comments>
		<pubDate>Tue, 03 Aug 2010 12:10:58 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[conferences]]></category>
		<category><![CDATA[CSS3]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=627</guid>
		<description><![CDATA[Just a quick note to let you know that I&#8217;m speaking in this year&#8217;s Front-Trends conference, which will take place in Warsaw, Poland on October 21-22. Front-Trends is a new conference (starting this year) but the organizers have managed to put together an impressive line-up (Crockford, PPK, Paul Bakaus, Dmitry Baranovskiy, Tantek Çelik, Robert Nyman and [...]]]></description>
			<content:encoded><![CDATA[
<p>Just a quick note to let you know that <a href="http://front-trends.com/speakers#lea-verou" target="_blank">I&#8217;m speaking</a> in this year&#8217;s <a href="http://front-trends.com" target="_blank">Front-Trends</a> conference, which will take place in Warsaw, Poland on October 21-22. Front-Trends is a new conference (starting this year) but the organizers have managed to put together an impressive line-up (<a href="http://front-trends.com/speakers#douglas-crockford" target="_blank">Crockford</a>, <a href="http://front-trends.com/speakers#peter-paul-koch" target="_blank">PPK</a>, <a href="http://front-trends.com/speakers#paul-bakaus">Paul Bakaus</a>, <a href="http://front-trends.com/speakers#dmitry-baranovskiy" target="_blank">Dmitry Baranovskiy</a>, <a href="http://front-trends.com/speakers#tantek-celik" target="_blank">Tantek Çelik</a>, <a href="http://front-trends.com/speakers#robert-nyman" target="_blank">Robert Nyman</a> and more).</p>
<p>My talk will introduce many aspects of CSS3, some of them in good depth (eg. selectors). Here is the official abstract:</p>
<h4>Pragmatic CSS3</h4>
<p>With browsers constantly adding support for CSS3, especially now that even IE jumped in the game, it&#8217;s quickly becoming a necessary tool of the trade. CSS3 offers exciting possibilities and changes the way that we design and develop websites.</p>
<p>In this 2-hour practical session, full of real world use cases, you will learn:</p>
<ul>
<li>Everything you ever wanted to know about CSS3 selectors</li>
<li>Transparency and new color formats, including RGBA</li>
<li>New ways to work with backgrounds, including CSS gradients, multiple background images and natively supported CSS sprites</li>
<li>Rounded corners and border images</li>
<li>Box and text shadows</li>
<li>Transforms, transitions and their potential downsides</li>
<li>New values, including calc(), attr() and new units</li>
<li>Browser support information and techniques to take advantage of the exciting new stuff with respect to browsers of the past, to create experiences that are enjoyable for everyone</li>
</ul>
<p>Tickets are very cheap (Just <strong>€198</strong>) but they&#8217;re selling quite fast, so if you want to come, <a href="http://front-trends.com/registration" target="_blank">hurry up</a>!</p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/dRzZBdztsJQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2010/08/lea-verou-at-front-trends-2010/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://leaverou.me/2010/08/lea-verou-at-front-trends-2010/</feedburner:origLink></item>
		<item>
		<title>Organizing a university course on modern Web development</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/o2sD92D4k1U/</link>
		<comments>http://leaverou.me/2010/07/organizing-a-university-course-on-modern-web-development/#comments</comments>
		<pubDate>Mon, 26 Jul 2010 12:03:27 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Original]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[CSS3]]></category>
		<category><![CDATA[education]]></category>
		<category><![CDATA[ES5]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[SVG]]></category>
		<category><![CDATA[teaching]]></category>
		<category><![CDATA[XPath]]></category>
		<category><![CDATA[XSLT]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=576</guid>
		<description><![CDATA[About a year ago, prof. Vasilis Vassalos of Athens University of Economics and Business approached me and asked for my help in a new course they were preparing for their Computer Science department, which would introduce 4th year undergrads to various web development aspects. Since I was always complaining about how outdated higher education is when [...]]]></description>
			<content:encoded><![CDATA[
<p>About a year ago, prof. <a href="http://twitter.com/vassalos" target="_blank">Vasilis Vassalos</a> of <a title="The university official website (yeah, I know...)" href="http://aueb.gr" target="_blank">Athens University of Economics and Business</a> approached me and asked for my help in a new course they were preparing for their <a href="http://www.cs.aueb.gr" target="_blank">Computer Science department</a>, which would introduce 4th year undergrads to various web development aspects. Since I was always complaining about how outdated higher education is when it comes to web development, I saw it as my chance to help things change for the better, so I agreed without a second thought.</p>
<p>This is one of the main reasons I didn&#8217;t have time to write many blog posts for the past months: This activity took up all my spare time. However, it proved to be an interesting and enlightening experience, in more than one ways. In this blog post I&#8217;ll describe the dilemmas we faced, the decisions we made and the insights I gained throughout these 6 months, with the hope that they&#8217;ll prove to be useful for anyone involved in something similar.</p>
<h3>Table of contents</h3>
<ol>
<li><a href="#course-content">Content</a></li>
<li><a href="#homework">Homework</a></li>
<li><a href="#labs">Labs</a></li>
<li><a href="#aftermath">Personal aftermath</a></li>
</ol>
<p><span id="more-576"></span></p>
<h3 id="course-content">Content</h3>
<p>The goals of a university course differ from the ones of a professional seminar or conference session in many ways, the key one being that most of its students will (professionally) utilize the things they learned in the future and not right after they walk away from class. So, the stuff being taught must be useful even after a couple years have passed. Also, issues of the present might not be issues of the future and what isn&#8217;t possible today (due to browser support issues) will probably be tomorrow.  These observations led us to decide <strong>against teaching proprietary stuff. Instead, we only included  things which come with a specification that has reached a fairly stable state</strong> (with the exception of <strong>very </strong>widespread non-standard stuff, such as <code>innerHTML</code>). We also decided <strong>not to address workarounds and browser incompatibilities at all</strong>, since these would probably be out of date in a few years. Also because, if we teach everything else right, they should be able to learn these by themselves, if needed (we did teach feature detection techniques though, those are timeless <img src='http://leaverou.me/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> ). We also included <strong>many cutting edge topics (CSS3, HTML5, ES5, SVG&#8230;) since we believe that they will be necessary tools of the trade tomorrow</strong>. To be pragmatic however, <strong>we did not teach stuff that no browser has implemented yet</strong>, besides perhaps a brief mention.</p>
<p>To make things easier for the students, we used <strong>Firefox 3.6</strong> for everything. We tested their assignments there, we used it to present something in the labs etc. Why Firefox?</p>
<ul>
<li>It&#8217;s at a quite good level of standards compliance and implements many modern technologies &amp; features</li>
<li>Fewer bugs (Webkit implements stuff faster, but in more buggy ways)</li>
<li>It has the best development tools (Firebug)</li>
<li>With Brendan Eich being Mozilla&#8217;s CTO, we all know how progressive Firefox is when it comes to JavaScript.</li>
</ul>
<p>Of course, this doesn&#8217;t mean it&#8217;s the only right choice. Google Chrome for example would be another good pick.</p>
<p>Another useful observation was that 4th year Computer Science students already know programming quite well, especially Java. So, <strong>we did not need to go through the basics of programming syntax</strong> like introductory books or seminars frequently do. Consequently, <strong>we skipped explaining how control structures or operators work</strong> in JavaScript or PHP and just <strong>focused on their differences</strong> from Java and other languages.</p>
<p>Another dilemma we faced was whether we should teach stuff on popular frameworks and whether we should allow them in the homeworks. We decided <strong>against allowing them in the homeworks</strong> because I believe that someone must not use a framework just to skip learning about the intricacies of a language. They should be used after the basics have been consolidated, in order to save time. Also because if everyone skips learning and just uses an abstraction to do the heavy lifting from the very beginning, who will write the abstractions after all? Another reason was that a large portion of every JavaScript framework is about handling cross-browser differences. However, these had no place in our course, so a JS framework wasn&#8217;t as necessary as it is in day to day web development. Regarding teaching them, <strong>we thought it would be a good idea to introduce students to the popular JS &amp; PHP frameworks in the last lectures</strong>, but there was no time left. Maybe next year.</p>
<p>To sum up, the course content ended up being (I&#8217;m listing client-side matters more extensively, since they are also the focus of this blog):</p>
<ul>
<li>General stuff about web application architecture and how the HTTP protocol works</li>
<li>We presented a small web application example (an AJAX shopping cart) in order for the students to get an idea about how everything clicks together</li>
<li>Markup languages
<ul>
<li>SGML</li>
<li>DTDs</li>
<li>HTML and XHTML
<ul>
<li>Basic structure of an (X)HTML document</li>
<li>Content model, block vs inline elements</li>
<li>Basic HTML elements
<ul>
<li>headings &amp; paragraphs</li>
<li>lists (ordered, unordered, definition lists)</li>
<li>tables</li>
<li>grouping elements (div &amp; span)</li>
</ul>
</li>
<li>Doctypes, the HTML5 doctype</li>
<li>The incentives behind XHTML &amp; the future ((X)HTML 5)</li>
<li>(X)HTML Validation</li>
<li>HTML forms
<ul>
<li>How forms work, GET vs POST</li>
<li>Form controls, shared attributes</li>
<li>The various input types (+ the new ones HTML5 brings)</li>
<li>Other form controls (buttons, &lt;select&gt; lists, textareas)</li>
<li>Basic form accessibility (labels &amp; fieldsets)</li>
</ul>
</li>
<li>Working with Multimedia (old methods, HTML5 video &amp; audio elements, comparison)</li>
</ul>
</li>
<li>XML and XPath, XQuery, XSLT</li>
</ul>
</li>
<li>CSS
<ul>
<li>CSS standards</li>
<li>CSS rules</li>
<li>Validation</li>
<li>Adding CSS to a page (linking/embedding methods)</li>
<li>Media targeting (The media attribute, @media rules, media queries)</li>
<li>CSS selectors
<ul>
<li>Introduction to the DOM</li>
<li>Basic selectors (Universal selector, Type selector, Class selector, Id selector)</li>
<li>Classes vs Ids</li>
<li>Attribute selectors (all 6)</li>
<li>Pseudo-classes (including most of the CSS3 ones)</li>
<li>Pseudo-elements</li>
<li>Simple selectors &amp; simple selector sequences</li>
<li>Combinators (all 4)</li>
<li>Selector grouping</li>
<li>XML namespaces &amp; CSS</li>
</ul>
</li>
<li>Cascading &amp; Inheritance
<ul>
<li>The problem: Conflicts</li>
<li>Specificity</li>
<li>Origin</li>
<li>!important</li>
<li>Inheritance</li>
<li>The special value <em>inherit</em></li>
</ul>
</li>
<li>Properties &amp; values
<ul>
<li>Keywords</li>
<li>Numerical values &amp; units</li>
<li>Colors (including CSS3 colors)</li>
<li>How shorthands work</li>
<li>Unsupported values &amp; providing fallbacks</li>
</ul>
</li>
<li>Box model
<ul>
<li>width &amp; height</li>
<li>Block level &amp; inline level elements (reminder from the HTML lectures)</li>
<li>The <em>display </em>property</li>
<li>border</li>
<li>padding</li>
<li>margin</li>
</ul>
</li>
<li>Positioning
<ul>
<li>The <em>position </em>property</li>
<li>Positioning types (absolute, relative, fixed)</li>
<li>z-index</li>
<li>float</li>
<li>Problems with floats, the <em>clear </em>property</li>
</ul>
</li>
<li>Generated content
<ul>
<li>::before and ::after</li>
<li>Static generated content</li>
<li>Dynamic generated content (attributes &amp; counters)</li>
</ul>
</li>
</ul>
</li>
<li>JavaScript
<ul>
<li>Adding JS to a document</li>
<li>Separation of concerns</li>
<li>A first, annotated, example (a simple script that generates tables of content from &lt;h2&gt; headings)</li>
<li>Basic syntax rules (including semicolons &amp; semicolon insertion)</li>
<li>Variables</li>
<li>Operators (including typeof, the comma operator, strict operators, differences of &amp;&amp;/|| in JS)</li>
<li>Primitives (String, Number, Boolean, null, undefined)</li>
<li>Conversion across primitives</li>
<li>Objects</li>
<li>The <em>in</em> &amp; <em>delete</em> operators</li>
<li>for&#8230;in loops</li>
<li>Native objects for primitives (eg the literal 5 vs new Number(5))</li>
<li>The global object</li>
<li>Functions (including function expressions vs function declarations)</li>
<li><em>this</em> &amp; changing execution context</li>
<li>Arrays (including .forEach() traversal)</li>
<li>Regular expressions in JavaScript</li>
<li>OOP in JavaScript
<ul>
<li>OOP concepts in JS</li>
<li>Constructors</li>
<li>Inheritance</li>
<li>Encapsulation (private, priviledged &amp; public properties)</li>
<li>Method overloading</li>
<li>JavaScript shortcomings when it comes to OOP</li>
<li>for&#8230;in loops, inherited properties &amp; [[Enumerable]], .hasOwnProperty()</li>
<li>Type detection based on [[Class]] detection (using Object.prototype.toString())</li>
</ul>
</li>
<li>DOM
<ul>
<li>Traversal</li>
<li>Node types</li>
<li>Selecting elements (getElementById, getElementsByClassName, getElementsByName, querySelector, using XPath to select elements)</li>
<li>DOM Manipulation</li>
<li>innerHTML, advantages &amp; criticism</li>
</ul>
</li>
<li>Events
<ul>
<li>Binding &amp; Removing event handlers</li>
<li>Traditional event binding</li>
<li>Capturing &amp; bubbling</li>
<li>Event objects</li>
<li>Event delegation</li>
<li>Firing events</li>
<li>Custom events</li>
<li>What if there&#8217;s no mouse?</li>
</ul>
</li>
<li>Client side storage
<ul>
<li>Cookies via HTTP headers, cookies in JavaScript</li>
<li>Problems with cookies</li>
<li>Web storage (localStorage, sessionStorage)</li>
<li>Client-side databases</li>
</ul>
</li>
<li>BOM
<ul>
<li>The window object, window names</li>
<li>Opening new windows</li>
<li>Cross-window communication</li>
<li>Closing windows, Focusing on windows</li>
<li>Cross-origin window communication</li>
<li><em>location</em> &amp; it&#8217;s components</li>
<li>The <em>history</em>, <em>screen</em> &amp; <em>navigator</em> objects</li>
<li>User Agent strings</li>
<li>Why you shouldn&#8217;t use browser detection</li>
<li>Built-in modal windows (alert, confirm, prompt)</li>
</ul>
</li>
<li>JavaScript &amp; CSS
<ul>
<li>CSS modification (className &amp; classList, inline styles)</li>
<li><em>CSSStyleDeclaration</em> objects</li>
<li>The document.styleSheets collection</li>
<li>Switching stylesheets</li>
<li><em>StyleSheet</em> objects</li>
<li><em>CSSStyleRule</em> objects</li>
<li>Computed style, getting the computed style</li>
</ul>
</li>
<li>Asynchronous execution
<ul>
<li>Timeouts &amp; Intervals</li>
<li>Background workers</li>
</ul>
</li>
<li>Graphics creation (canvas)</li>
<li>A brief mention of WebGL (we also showed the video of Google&#8217;s web based DOOM game)</li>
<li>Best practices
<ul>
<li>When JS is disabled</li>
<li>Feature detection</li>
</ul>
</li>
</ul>
</li>
<li>Regular expressions</li>
<li>Ajax (including data interchange formats, like JSON, other async data transmission techniques, including dynamic script loading &amp; JSONP, usability concerns)</li>
<li>SVG</li>
<li>Server side web development
<ul>
<li>PHP (also covering OOP in PHP extensively)</li>
<li>Database driven websites</li>
<li>State &amp; session management</li>
<li>REST</li>
<li>SOAP</li>
</ul>
</li>
<li>Web application security</li>
</ul>
<p><strong><em>Note:</em></strong><em> For brevity reasons, the lists above do not include introductory stuff such as:</em></p>
<ul>
<li><em>What&#8217;s X?</em></li>
<li><em>A brief history of X</em></li>
<li><em>Why use X?</em></li>
<li><em>etc</em></li>
</ul>
<h4>Lessons learned</h4>
<p>It&#8217;s very hard to momentarily change your mindset and try to imagine that you live in a modern, fully standards-based web development world, where old browsers, proprietary stuff, hacks and compatibility workarounds have no place. A world where IE doesn&#8217;t exist. However, it&#8217;s the world that all our material assumed, for the reasons stated above. And it&#8217;s beautiful, so much that it becomes addictive and makes you hate all these bugs &amp; incompatibilities that we have to face today even more.</p>
<h3 id="homework">Homework</h3>
<p>The students were given 3 assignments throughout the semester, each covering:</p>
<ul>
<li>1st assignment: HTML, CSS, XPath, XSLT</li>
<li>2nd assignment: JavaScript, Ajax, SVG</li>
<li>3rd assignment: Server side web dev + CSS, JavaScript, Ajax</li>
</ul>
<p>These homeworks accounted for 30% of their final grade (10% each), which probably should have been more.</p>
<p>We searched for exercises on these topics from other universities but couldn&#8217;t find anything, so we made our own. I&#8217;ve translated them, in case someone finds them useful, given that there&#8217;s a great shortage of such material in the intertubes. You can get them through the links below, along with their complementary files.</p>
<h4>1st assignment [<a href="http://leaverou.me/wdclass/assignment1_en.pdf" target="_blank">pdf</a>] [<a href="http://leaverou.me/wdclass/assignment1_en.zip" target="_blank">files</a>]</h4>
<ul>
<li> I think 1.A and 1.B are excellent exercises to make the students fully understand how CSS selectors work and avoid them resulting to only use the 4-5 basic ones just because they don&#8217;t understand the rest (like many web developers do). It&#8217;s a pity that many of them resulted to online scripts for the conversion (but luckily it was easy to spot: These answers were way more verbose than the corresponding &#8220;handmade&#8221; ones, and in some cases even incorrect!)</li>
<li>I also think 1.C is an excellent exercise for cascading &amp; inheritance practice. Some of the cases were even quite tricky (for instance, the way specificity works for :not() or how grouping works if one of the selectors is invalid) and treated almost all factors that someone should know to predict which rule &#8230;overrules. It&#8217;s important however that the student justifies the answer, because otherwise they can just test it in a browser and write down the result, without understanding why.</li>
<li>I&#8217;m not sure yet if freeform questions were a good idea, but (hopefully) they got them to practice their critical thinking and do some research (we hadn&#8217;t presented :checked and :lang() in class). We didn&#8217;t expect many to get the 3rd one right, but we were pleasantly surprised.</li>
<li>What I like in 3.A is that I believe it enforces the Separation of Concerns guideline, since they cannot alter the HTML file (something even professionals commonly do to get something done, the quick &amp; dirty way&#8230;) so they <strong>have</strong> to move all presentation to the CSS file. It also contained a quite tricky part: Maintaining state without JavaScript, by utilizing the <strong>:checked</strong> pseudo-class and some combinators (a technique made popular quite recently by <a href="http://www.thecssninja.com/">Ryan Seddon</a>). Obviously, this is not a good way to change views in a photo gallery (too much wasted bandwidth), but it was perfect as a CSS exercise. To my surprise, more than half of the students got it right, which indicates that we probably did a good job explaining CSS Selectors <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
</ul>
<h4>2nd assignment [<a href="http://leaverou.me/wdclass/assignment2_en.pdf" target="_blank">pdf</a>] [<a href="http://leaverou.me/wdclass/assignment2_en.zip" target="_blank">files</a>]</h4>
<ul>
<li>I like exercise 1 because it teaches them how they can take somebody else&#8217;s work, extend it and make it more generic and useful. This is something that&#8217;s frequently done in web development. By the way, the deviation in the solutions was quite interesting. Others had implemented a recursive algorithm, others approached it in an Object Oriented manner and others took the classic iterative route.</li>
<li>Exercise 2 lets them practice event delegation, unobtrusive progressive enhancement via JavaScript, decisions to improve performance (and still, it&#8217;s unbelievable how many students made choices that were obviously terrible performance-wise. I still remember one script that created another DOM element <strong>on every mouseover</strong>!)</li>
<li>Exercise 3 combines many of the technologies they learned in the previous lectures. It also lets them practice their critical thinking by comparing the methods afterwards. Most students picked the CSS method, which would also be my choice, for such a simple bar chart (however, anything rational got full points, I don&#8217;t think there&#8217;s a correct answer here, it depends on many factors).</li>
<li>I like exercise 4 because it introduces them to the concept of writing JavaScript that is intended to be used by other developers, and not just in a particular project (along with 2 perhaps). However, none of the students fully understood what it was about. All of them fired the HTTP request when ajaxForm() was called and most of them also implemented callback() and errorCallback(), which wasn&#8217;t supposed to be their job.</li>
<li>Exercise 5, besides serving well as regular JavaScript practice, it also lets them learn more about cutting edge technologies such as <strong>localStorage</strong>, <strong>Web databases</strong> or <strong>offline web apps</strong>.</li>
</ul>
<h4>3rd assignment [<a href="http://leaverou.me/wdclass/assignment3_en.pdf" target="_blank">pdf</a>] [<a href="http://leaverou.me/wdclass/assignment3_en.zip" target="_blank">files</a>]</h4>
<p>In this assignment, the students practiced in PHP, combined everything else they&#8217;ve learned and understood better how everything clicks together to bring a fully-fledged web application to life. We didn&#8217;t get many submissions, since most students were busy with other assignments these days but most of the ones we got were awesome, I had an extremely hard time picking the best one.</p>
<h4>Lessons learned</h4>
<ul>
<li>Most mistakes are not very original: They tend to appear over and over again in unrelated assignments. Most of them are caused either by ambiguities in the description or because the student didn&#8217;t bother to read all of it. Also, the most frequent excuse for not doing something right is &#8220;it wasn&#8217;t in the description!&#8221;. So, they have to be as detailed as possible, including even stuff that&#8217;s obvious to someone more experienced.</li>
<li>Plagiarism is not a myth, but a real and frequent problem. Students copy from other students, from scripts posted online and from any source they can get their hands on. <img src='http://leaverou.me/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' />  However, only teaching the standards makes it much easier to spot (at least when it comes to copying from the internet) since most scripts posted online have to account for browser incompatibilities.</li>
</ul>
<h3 id="labs">Labs</h3>
<p>We only held 3 hands-on lectures (2 hours each), due to time availability issues of everyone involved in the course. I taught the first 2 and another TA was responsible for the 3rd one. Details below:</p>
<h4>1st lab [<a href="http://leaverou.me/wdclass/lab1/">final result</a>]</h4>
<p>The students had to write an HTML file for the single page personal website of some fictional web developer and then use CSS to style it in a certain way. The process was guided, in order to keep all of them on the same track. The site was carefully designed to demonstrate many key CSS concepts &amp; features at once.</p>
<h4>2nd lab [<a href="http://leaverou.me/wdclass/rating-widget/" target="_blank">final result</a>] [<a href="http://leaverou.me/wdclass/rating-widget/rating-widget.js">JS code</a>] [<a href="http://leaverou.me/wdclass/rating-widget/rating-widget-incomplete.js" target="_blank">incomplete JS code</a>]</h4>
<p>The students were given an HTML and a CSS file and they had to fill in a .js file that had some parts missing (replaced by TODO comments as placeholders) to complete a very simple ajax rating widget.</p>
<h4>Lessons learned</h4>
<ul>
<li>Never provide downloadable slides with the things the students must write by themselves prior to the lecture. They&#8217;ll just copy-paste everything from the pdf, even if they have to fix spacing afterwards. If you absolutely have to, make sure the text is not selectable.</li>
<li>It takes students far more time to write code than you planned for</li>
<li>When the students don&#8217;t understand something, most of them won&#8217;t ask. <img src='http://leaverou.me/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' />  It&#8217;s best if you personally explain things to anyone having difficulties, but there&#8217;s usually not enough time for that</li>
</ul>
<h3 id="aftermath">Personal aftermath</h3>
<ul>
<li>I found out that I <strong>love</strong> teaching. Successfully helping a student with a problem they had or something they did not understand was sometimes enough to make my day. Preparing material for the course &#8211;although exhausting&#8211; was one of the most interesting and creative things I have ever done. Even the actual teaching is thrilling. It&#8217;s very challenging to try to keep the students&#8217; interest, since most of them will resort to chatting with their buddies instead of paying attention way more easily than professionals would during a conference talk. However, if you manage to do so, it can be quite rewarding.</li>
<li>I <strong>hate</strong> grading. It&#8217;s boring, time-consuming, carries a lot of responsibility and you have to ensure every point you deduct is justified, because you might have to defend your judgement in case a student complains. Sometimes it can also freak you out completely (&#8220;OMGWTF, how could they understand it so wrong?? Why didn&#8217;t they ask?&#8221;) These strips sum it up perfectly (and with a good dose of humor):</li>
</ul>
<p><a href="http://www.phdcomics.com/comics.php?f=1319"><img class="alignnone" title="Grading Rubric" src="http://www.phdcomics.com/comics/archive/phd051910s.gif" alt="Grading Rubric" width="600" height="500" /></a></p>
<p><a href="http://www.phdcomics.com/comics.php?f=1320"><img class="alignnone" title="If only" src="http://www.phdcomics.com/comics/archive/phd052110s.gif" alt="If only" width="600" height="260" /></a></p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/o2sD92D4k1U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2010/07/organizing-a-university-course-on-modern-web-development/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://leaverou.me/2010/07/organizing-a-university-course-on-modern-web-development/</feedburner:origLink></item>
		<item>
		<title>“Wow, Mona Lisa with pure CSS!”</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/QX6qL42SntE/</link>
		<comments>http://leaverou.me/2010/05/wow-mona-lisa-with-pure-css/#comments</comments>
		<pubDate>Tue, 25 May 2010 07:05:45 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Rants]]></category>
		<category><![CDATA[Thoughts]]></category>
		<category><![CDATA[CSS3]]></category>
		<category><![CDATA[SVG]]></category>
		<category><![CDATA[theoretical]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=563</guid>
		<description><![CDATA[There has been a recent flood of CSS experiments that utilize CSS3 features to convert some meaningless markup to spectacular pictures. It all started when David Desandro used CSS3 to draw the Opera logo. This seemed to inspire lots of other folks who created similar demos: Pure CSS icons Create Social Media Icons in pure [...]]]></description>
			<content:encoded><![CDATA[
<p>There has been a recent flood of CSS experiments that utilize CSS3 features to convert some meaningless markup to spectacular pictures. It all started when <a href="http://desandro.com/articles/opera-logo-css/" target="_blank">David Desandro used CSS3 to draw the Opera logo</a>. This seemed to inspire lots of other folks who created similar demos:</p>
<ul>
<li><a href="http://rathersplendid.net/home/pure-css-icons" target="_blank">Pure CSS icons</a></li>
<li><a href="http://blog.insicdesigns.com/2010/03/create-social-media-icons-in-pure-css/" target="_blank">Create Social Media Icons in pure CSS</a></li>
<li><a href="http://www.romancortes.com/blog/css3-flower/">CSS flower</a></li>
<li><a href="http://desandro.com/resources/curtis-css-typeface/" target="_blank">Curtis CSS typeface</a></li>
<li><a href="http://gabri.me/htmlcss/2010/css3-gradients-coffee-cup/" target="_blank">CSS3 Gradients coffee cup</a></li>
</ul>
<p>I can certainly share their enthusiasm and I am also amazed by their results. Besides that, I think that pushing CSS3 to the edge like that, helps us understand the spec better, which leads us to find and file browser bugs or write comments regarding the spec itself. Filing bugs is crucial at this stage, with all browser vendors gradually adding experimental &#8211;and frequently buggy&#8211; CSS3 support to their products. Also, don&#8217;t get me wrong: I can easily see the benefits of reducing the number of images in a web application interface (far quicker/easier modifications, less HTTP requests and most of the time, less bandwidth).</p>
<p>However, I&#8217;m afraid we&#8217;re losing sight of the big picture. These aren&#8217;t demos that are or will ever be legitimate CSS use cases. Even after universal CSS3 browser support is achieved, they would (and should) still be considered &#8220;hacks&#8221;. Almost all the arguments pro their usage also apply to more suitable ways of including images in web applications:</p>
<ul>
<li><strong>Fewer HTTP requests</strong>: Same with any kind of embedded image (data URIs, inline SVG and so on)</li>
<li><strong>Scalable</strong>: Same with SVG and symbols embedded in custom fonts</li>
<li><strong>Easier to modify:</strong> Same with SVG</li>
<li><strong>Less bandwidth (in some cases):</strong> Same with SVG (and it can be cached too, when not inline)</li>
</ul>
<div>And apart from these, these illustrations require non-semantic crap to be included in the markup which, besides issues of theoretical purity, makes it harder for other people to use them.</div>
<div>As for the <strong>graceful degradation</strong> argument, yes, this does only apply to CSS &#8220;images&#8221;. But in this case, is it really an advantage? I seriously doubt it. People won&#8217;t notice rounded corners if they&#8217;re missing from an interface, but they&#8217;re definitely going to notice a blocky Opera logo. And they&#8217;re not used in thinking that their browser has something to do with how an image renders, so they&#8217;ll just blame the website.</div>
<p>CSS is supposed to enhance the presentation of a document or interface, not to be (ab)used for the creation of illustrations from scratch. It&#8217;s supposed to separate presentation from structure, not generate stuff. There are other technologies that are far more suitable for this (*cough*SVG*cough*). I think we should use our energy and creativity to make CSS3 demos that people will actually use in the future when all this is fully supported, not stuff doomed to be eternally considered hackery.</p>
<p>&#8220;Where should we draw the line?&#8221; one might ask. For example, is a <a href="http://oddvalue.co.uk/blog/2010/02/css3_clock/" target="_blank">Pure CSS analog clock</a> a CSS <strong>ab</strong>use case? Or even my own <a href="http://leaverou.me/2010/02/iphone-keyboard-with-css3-no-images/" target="_blank">CSS iPhone keyboard</a>? Now <strong><em>that&#8217;s</em></strong> a good question! A rule of thumb seems to be <em>&#8220;if it inherently (=not due to browser support issues) involves a bunch of empty (or with meaningless content) HTML elements, then that&#8217;s a bad sign&#8221;</em> but that might be overly strict. What&#8217;s your take on it?</p>
<p><strong><em>Disclaimer:</em></strong><em> Yes, I&#8217;m fully aware that most of the time, such experiments are created just for fun by their (very talented) authors, which are perfectly aware of all the things mentioned above. However, I&#8217;ve also grown tired of reading comments by people that seem to to think that &#8220;This is the future of the web!&#8221;. Let&#8217;s hope it&#8217;s not.</em></p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/QX6qL42SntE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2010/05/wow-mona-lisa-with-pure-css/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://leaverou.me/2010/05/wow-mona-lisa-with-pure-css/</feedburner:origLink></item>
		<item>
		<title>On CSS counters plus a CSS3 Reversi UI</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/3SoHraS_itM/</link>
		<comments>http://leaverou.me/2010/04/on-css-counters-plus-a-css3-reversi-ui/#comments</comments>
		<pubDate>Thu, 01 Apr 2010 07:44:02 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Original]]></category>
		<category><![CDATA[CSS Counters]]></category>
		<category><![CDATA[CSS3]]></category>
		<category><![CDATA[User Interfaces in CSS]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=540</guid>
		<description><![CDATA[CSS Counters have a lot more potential than most web developers seem to think. The common use case consists of something like: somecontainer { counter-reset: foocount; } Ε { counter-increment: foocount; } Ε::before { content: counter(foocount) ". "; } commonly used to add numbering to section headings or re-create an &#60;ol&#62;&#8217;s counters in order to [...]]]></description>
			<content:encoded><![CDATA[
<p>CSS Counters have a lot more potential than most web developers seem to think. The common use case consists of something like:</p>
<pre>somecontainer { counter-reset: foocount; }
Ε { counter-increment: foocount; }
Ε::before { content: counter(foocount) ". "; }</pre>
<p>commonly used to add numbering to section headings or re-create an &lt;ol&gt;&#8217;s counters in order to style them (since browser support for ::marker is ridiculous).</p>
<p>Have you ever thought of applying the counter to <strong>different </strong>elements than the ones being counted? This way we&#8217;re able to count elements and display their total count somewhere with CSS alone! (and with the variety of selectors in CSS3, I see great potential here&#8230;). I&#8217;m referring to something like:</p>
<pre>ul { counter-reset:foo; }
li { counter-increment:foo; }
p::after { content:counter(foo); }</pre>
<p>From my tests, this works flawlessly in Firefox, Safari, Opera and Chrome (I&#8217;ve only checked the latest stable though), <strong>as long as the element that displays the count comes after the elements being counted (in the markup)</strong>.</p>
<p>Another underutilized aspect of CSS counters (well, far less underused than the above, but still) is how we can combine multiple in the same pseudoelement. For instance, to count rows and cells of a table and display the count inside each cell:</p>
<pre>table {
	counter-reset:row;
}

tr {
	counter-increment:row;
	counter-reset:cell;
}

td {
	counter-increment:cell;
}

td::after {
	content:counter(row, upper-alpha) counter(cell);
}</pre>
<p>Which displays counters like A1, A2, A3, B1, B2, B3, etc in the cells. When the content property is more properly implemented, you wouldn&#8217;t even need the last rule.</p>
<p>Last but not least, a <a style="font-size: larger;" href="http://leaverou.me/demos/Reversi/">CSS3 Reversi UI</a> (no images used!) I created a while ago that demonstrates the above (and various other things, like &#8211;finally&#8211; a use case for <strong>:empty</strong> <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  ). <em>Looks</em> fine only in Firefox and Opera 10.5, due to lack of support for inset box shadows in Safari and <a href="https://bugs.webkit.org/show_bug.cgi?id=36939" target="_blank">buggy</a> support in Chrome. <em>Works</em> fine in all 4 of them (IE is out of the question anyway).</p>
<p><a href="http://leaverou.me/demos/Reversi/"><img class="alignnone" title="Screenshot from Firefox 3.6" src="http://leaverou.me/demos/Reversi/screenshot.png" alt="Screenshot of the UI" width="512" height="575" /></a></p>
<p>The displayed counts of each player&#8217;s pieces (top right corner) are just CSS counters. Same goes for every cell&#8217;s name. This is mostly a proof of concept, since it&#8217;s impossible to determine if someone won by CSS alone, so we would have to count the pieces in JS too.</p>
<p>As a game it&#8217;s not finalized, you are basically only able to play against yourself and it doesn&#8217;t know when somebody won, so it&#8217;s not very useful or enjoyable. If someone wants to take it up and develop it further be my guest.</p>
<p><strong>Note to avoid confusion: </strong>CSS Counters are <strong>not </strong>CSS 3. They are perfectly valid <strong>CSS 2.1</strong>. The &#8220;CSS3&#8243; in the title (&#8220;CSS3 Reversi&#8221;) is due to other techniques used in it&#8217;s UI.</p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/3SoHraS_itM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2010/04/on-css-counters-plus-a-css3-reversi-ui/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://leaverou.me/2010/04/on-css-counters-plus-a-css3-reversi-ui/</feedburner:origLink></item>
		<item>
		<title>MySQL: Are you actually utilizing your indexes?</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/iv92hfWy4J4/</link>
		<comments>http://leaverou.me/2010/03/mysql-are-you-actually-utilizing-your-indexes/#comments</comments>
		<pubDate>Thu, 25 Mar 2010 03:14:56 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=527</guid>
		<description><![CDATA[This might seem elementary to those of you that are DBAs or something similar, but it was fascinating to find out (not to mention it greatly helped what I had to do), so I decided to post it, in case it helps someone else too. A few moments ago I found out that whereas a [...]]]></description>
			<content:encoded><![CDATA[
<p><em>This might seem elementary to those of you that are DBAs or something similar, but it was fascinating to find out (not to mention it greatly helped what I had to do), so I decided to post it, in case it helps someone else too.</em> A few moments ago I found out that whereas a query along the lines of&#8230;</p>
<pre>SELECT title, COUNT(1) as replies
FROM post INNER JOIN thread USING(threadid)
WHERE <strong>UNIX_TIMESTAMP(NOW()) - post.dateline &lt; 86400</strong>
GROUP BY threadid
ORDER BY replies DESC
LIMIT 5</pre>
<p>took a whopping <strong>~10 seconds</strong> on a post table of around 2,000,000 rows and a thread table of around 40,000 rows, the following:</p>
<pre>SELECT title, COUNT(1) as replies
FROM post INNER JOIN thread USING(threadid)
WHERE <strong>post.dateline &gt; UNIX_TIMESTAMP(NOW()) - 86400</strong>
GROUP BY threadid
ORDER BY replies DESC
LIMIT 5</pre>
<p>took a mere <strong>0.03 seconds</strong>!</p>
<p>Probably, MySQL wasn&#8217;t able to utilize the B+ tree index of the dateline column in the first query, whereas in the second, things were a bit more obvious to it. This can also be observed by examining the information about the execution plan that EXPLAIN provides:</p>
<pre>mysql&gt; explain select t.threadid, t.title, count(1) as replies from vb3_post as p inner join vb3_thread as t using(threadid) where unix_timestamp(now()) - p.dateline &lt; 86400 group by p.threadid order by replies desc limit 5;
+----+-------------+-------+------+---------------+----------+---------+------------+-------+---------------------------------+
| id | select_type | table | type | possible_keys | key      | key_len | re         | rows  | Extra                           |
+----+-------------+-------+------+---------------+----------+---------+------------+-------+---------------------------------+
|  1 | SIMPLE      | t     | ALL  | PRIMARY       | NULL     | NULL    | NULL       | 39859 | Using temporary; Using filesort |
|  1 | SIMPLE      | p     | ref  | threadid      | threadid | 4       | t.threadid |    49 | Using where                     |
+----+-------------+-------+------+---------------+----------+---------+------------+-------+---------------------------------+
2 rows in set (0.01 sec)

mysql&gt; explain select t.threadid, t.title, count(1) as replies from vb3_post as p inner join vb3_thread as t using(threadid) where p.dateline &gt; UNIX_TIMESTAMP(NOW()) - 86400 group by p.threadid order by replies desc limit 5;
+----+-------------+-------+--------+-------------------+----------+---------+------------+------+----------------------------------------------+
| id | select_type | table | type   | possible_keys     | key      | key_len | ref        | rows | Extra                                        |
+----+-------------+-------+--------+-------------------+----------+---------+------------+------+----------------------------------------------+
|  1 | SIMPLE      | p     | range  | threadid,dateline | dateline | 4       | NULL       | 1171 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | t     | eq_ref | PRIMARY           | PRIMARY  | 4       | p.threadid |    1 |                                              |
+----+-------------+-------+--------+-------------------+----------+---------+------------+------+----------------------------------------------+
2 rows in set (0.00 sec)</pre>
<p>So, don&#8217;t rest assured that MySQL will use your indexes every time it should. It seems that sometimes you have to explicitly point it out.</p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/iv92hfWy4J4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2010/03/mysql-are-you-actually-utilizing-your-indexes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://leaverou.me/2010/03/mysql-are-you-actually-utilizing-your-indexes/</feedburner:origLink></item>
		<item>
		<title>CSS3 structural pseudo-class selector tester</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/8njgTN4M8JE/</link>
		<comments>http://leaverou.me/2010/03/css3-structural-pseudo-class-selector-tester/#comments</comments>
		<pubDate>Sun, 14 Mar 2010 05:50:22 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Original]]></category>
		<category><![CDATA[CSS3 selectors]]></category>
		<category><![CDATA[educational]]></category>
		<category><![CDATA[nth-child]]></category>
		<category><![CDATA[nth-last-child]]></category>
		<category><![CDATA[nth-last-of-type]]></category>
		<category><![CDATA[nth-of-type]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=521</guid>
		<description><![CDATA[I was doing some research today about how people explain the CSS3 structural* pseudo classes and I stumbled upon this demo by CSS tricks: http://css-tricks.com/examples/nth-child-tester/ I thought the idea is awesome, but lacks a few features: It doesn&#8217;t use the native browser algorithm for selecting the elements. Granted, it&#8217;s not that tough to code your [...]]]></description>
			<content:encoded><![CDATA[
<p>I was doing some research today about how people explain the CSS3 structural* pseudo classes and I stumbled upon this demo by CSS tricks: <a href="http://css-tricks.com/examples/nth-child-tester/">http://css-tricks.com/examples/nth-child-tester/</a></p>
<p>I thought the idea is <strong>awesome</strong>, but lacks a few features:</p>
<ul>
<li>It doesn&#8217;t use the native browser algorithm for selecting the elements. Granted, it&#8217;s not that tough to code your own properly, but I trust a browser implementation more (IE doesn&#8217;t support these altogether, so it&#8217;s out of the question anyway).</li>
<li>Doesn&#8217;t allow you to test for nth-last-child, nth-of-type, nth-last-of-type (and especially the last two are a lot harder to understand for most people)</li>
<li>Doesn&#8217;t allow you to add/remove list items to see the effects of the selector with different numbers of elements (especially needed if nth-last-child, nth-of-type, nth-last-of-type were involved)</li>
</ul>
<p>So, I decided to code my own. It allows you to test for all 4 nth-something selectors, supports adding/removing elements (the selected elements update instantly) and uses the native browser implementation to select them (so it won&#8217;t work on IE and old browsers).</p>
<p>Enjoy: <a href="http://leaverou.me/demos/nth.html"><strong style="font-size:x-large">CSS3 structural pseudo-class selector tester</strong></a> <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>*Yes, :root and :empty also belong to those, but are rarely used. All other structural pseudoclasses are actually shortcuts to some particular case of the aforementioned 4 <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/8njgTN4M8JE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2010/03/css3-structural-pseudo-class-selector-tester/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://leaverou.me/2010/03/css3-structural-pseudo-class-selector-tester/</feedburner:origLink></item>
		<item>
		<title>CSSNinja’s custom forms revisited to work with CSS sprites</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/ZJ8T4VKy70U/</link>
		<comments>http://leaverou.me/2010/02/cssninjas-custom-forms-revisited-to-work-with-css-sprites/#comments</comments>
		<pubDate>Fri, 19 Feb 2010 09:07:02 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Replies]]></category>
		<category><![CDATA[CSS3 selectors]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=512</guid>
		<description><![CDATA[I read today CSS Ninja&#8216;s (Ryan Sheddon&#8217;s) brilliant new technique about the creation of custom checkboxes and radio buttons with CSS alone. The only thing that bugged me about it was something he pointed himself out as well: This technique has only 1 drawback I can think of, IE support is not a drawback for [...]]]></description>
			<content:encoded><![CDATA[
<p>I read today <a href="http://www.thecssninja.com/" target="_blank">CSS Ninja</a>&#8216;s (Ryan Sheddon&#8217;s) <a href="http://www.thecssninja.com/css/custom-inputs-using-css">brilliant new technique about the creation of custom checkboxes and radio buttons with CSS alone</a>.</p>
<p>The only thing that bugged me about it was something he pointed himself out as well:</p>
<blockquote><p>This technique has only 1 drawback I can think of, IE support is not a drawback for me, you can’t use a big sprite image to save all the radio and checkbox states, they need to be individual images. Using CSS generated content to insert an image doesn’t give you control of the image position like a background image does.</p></blockquote>
<p>And then I wondered &#8220;but hey, <strong>why</strong> can&#8217;t we use background images?&#8221;. It seemed pretty obvious to me that we could combine a transparent text color with normal css sprites and a display of inline-block in the ::before pseudo-element to achieve the exact same effect. I verified that my initial assertion was actually correct, and tested it in Firefox, Chrome, Safari and Opera (the latest only, no time for testing in older ones at the moment) and it seems to work fine.</p>
<p>Here it is: <a href="http://leaverou.me/demos/cssninja-custom-forms/">demo</a> | <a href="http://leaverou.me/demos/cssninja-custom-forms/source.zip">source files (including .psd file of the sprite)</a></p>
<p>I&#8217;m afraid there&#8217;s some blatantly obvious drawback in my approach that made Ryan prefer his method over this, but I&#8217;m posting it just in case&#8230;</p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/ZJ8T4VKy70U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2010/02/cssninjas-custom-forms-revisited-to-work-with-css-sprites/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://leaverou.me/2010/02/cssninjas-custom-forms-revisited-to-work-with-css-sprites/</feedburner:origLink></item>
		<item>
		<title>iPhone keyboard with CSS3 — no images</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/t6GVTcVlVCU/</link>
		<comments>http://leaverou.me/2010/02/iphone-keyboard-with-css3-no-images/#comments</comments>
		<pubDate>Thu, 18 Feb 2010 04:25:00 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Original]]></category>
		<category><![CDATA[@font-face]]></category>
		<category><![CDATA[box-shadow]]></category>
		<category><![CDATA[CSS gradients]]></category>
		<category><![CDATA[CSS3]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[media queries]]></category>
		<category><![CDATA[text-shadow]]></category>
		<category><![CDATA[User Interfaces in CSS]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=490</guid>
		<description><![CDATA[Yeap, this is yet another of those things that make no practical sense but are fun to make just to see whether it can actually be done. It&#8217;s also a proof of the fact that when I have too many things to do, I tend to procrastinate more. Here it is (resize the window to [...]]]></description>
			<content:encoded><![CDATA[
<p>Yeap, this is yet another of those things that make no practical sense but are fun to make just to see whether it can actually be done. It&#8217;s also a proof of the fact that when I have too many things to do, I tend to procrastinate more. <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p>Here it is (resize the window to get the narrow version <img src='http://leaverou.me/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ):</p>
<p><a style="font-size: larger;" href="http://leaverou.me/demos/iphone-keyboard/" target="_blank">http://leaverou.me/demos/iphone-keyboard/</a></p>
<p>It should look correct in <strong>Firefox 3.6, Chrome 4 and Safari 4</strong>. It looks best on Firefox 3.6 due to it&#8217;s ability to render subpixel distances, whereas other browsers just round everything to the closest pixel. It also looks best in computers with <strong>Helvetica </strong>installed (it&#8217;s installed by default on macs btw) but it should look sufficiently OK with Arial too, since it&#8217;s a rip-off of Helvetica <img src='http://leaverou.me/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  (the only problem with Arial is that the line-height of the buttons with the symbols will be slightly different since the custom font&#8217;s measurements are based on Helvetica Bold) Also, ironically, it doesn&#8217;t look ok in the iPhone!</p>
<p>For those of you that don&#8217;t use one of the aforementioned browsers as your primary and are way too bored to switch (or don&#8217;t even have them installed (!)), here are two screenshots from Firefox 3.6 (nicely cropped to only contain the keyboard):</p>
<div class="wp-caption aligncenter" style="width: 490px"><img title="Screenshot of the wide version" src="http://leaverou.me/demos/iphone-keyboard/css_wide_keyboard.png" alt="" width="480" height="162" /><p class="wp-caption-text">Screenshot of the wide version</p></div>
<div class="wp-caption aligncenter" style="width: 330px"><img title="Screenshot of the narrow version" src="http://leaverou.me/demos/iphone-keyboard/css_narrow_keyboard.png" alt="" width="320" height="215" /><p class="wp-caption-text">Screenshot of the narrow version</p></div>
<p><span id="more-490"></span>As for how it&#8217;s done, as you can easily see, most of it is run-of-the-mill for someone with a decent grasp on CSS3: media queries, CSS gradients, shadows, border-radiuses and RGBA. The only tricky part is the symbols for <kbd>shift</kbd>, <kbd>backspace</kbd> and <kbd>international</kbd>. I have to admit I cheated a bit here: I didn&#8217;t use images, but I used @font-face with a custom font that just contains these 3 symbols. The reasons behind that are that this way I wouldn&#8217;t have to create 2 versions of the symbols (light and dark, for pressed and normal states respectively) and that they are vector, so they scale (try zooming in).</p>
<p>Please note that there&#8217;s no functionality attached to it. It&#8217;s just an interface. I wasn&#8217;t interested at making an on-screen keyboard in general, I was just interested to see if a keyboard visually identical to iPhone&#8217;s is possible with CSS alone. If someone wants to actually use it and/or develop it further, you&#8217;re free to do so, as long as you keep the comment at the start of the css file. <img src='http://leaverou.me/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>An interesting discussion about this could be &#8220;What would be the ideal markup to semantically style a keyboard?&#8221;. Personally, I just paid attention to the more pragmatic objectives of making the keys focusable, and keeping the complexity of the DOM tree to a minimum, so you might find it semantically wrong (I used a &lt;ul&gt; for the container, &lt;li&gt;s for the rows and &lt;button&gt;s for the keys) &#8212; but what is right actually in this case? Is a keyboard a list or a table of keys? I don&#8217;t think so&#8230;</p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/t6GVTcVlVCU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2010/02/iphone-keyboard-with-css3-no-images/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://leaverou.me/2010/02/iphone-keyboard-with-css3-no-images/</feedburner:origLink></item>
		<item>
		<title>Redesign</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/uoCfmqDIZwU/</link>
		<comments>http://leaverou.me/2010/02/redesign/#comments</comments>
		<pubDate>Sat, 13 Feb 2010 04:39:53 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[leaverou.me]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=482</guid>
		<description><![CDATA[Was about time, wasn&#8217;t it? I wanted a simpler, more minimalistic (and wider!) theme for a while now. The other one was too restrictive. I had designed it when I had absolutely no content, and few changes were made to it afterwards. So, today that I was too sad and furious to do anything productive, [...]]]></description>
			<content:encoded><![CDATA[
<p>Was about time, wasn&#8217;t it?</p>
<p>I wanted a simpler, more minimalistic (and wider!) theme for a while now. The other one was too restrictive. I had designed it when I had absolutely no content, and few changes were made to it afterwards.</p>
<p>So, today that I was too sad and furious to do anything productive, I spent a few hours redesigning the blog (creative venting&#8230;). Please note that it&#8217;s just a few hours&#8217; work (with no mockup), so it&#8217;s bound to be a bit rough around the edges. I will refine it more as time goes by.</p>
<p>(and just like the previous one, it&#8217;s best viewed in more CSS3-supporting browsers, like Firefox, Chrome or Safari. If we can&#8217;t use the latest bells n&#8217; whistles in our <strong>personal</strong> blogs, where can we? <img src='http://leaverou.me/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> )</p>
<p>Here&#8217;s a screenshot from the previous theme:</p>
<p><img class="alignnone" title="The old leaverou.me theme" src="http://leaverou.me/wp-content/themes/leaverou/screenshot.png" alt="Screenshot of the old leaverou.me theme" width="300" height="224" /></p>
<p>R.I.P. my first wordpress theme.</p>
<p>PS: Yeah, I know I haven&#8217;t posted in a while. I have started lots of posts, but didn&#8217;t finish any. I hope I&#8217;ll have something complete to post soon.</p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/uoCfmqDIZwU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2010/02/redesign/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://leaverou.me/2010/02/redesign/</feedburner:origLink></item>
		<item>
		<title>Quickly find the Gravatar that cor­res­ponds to a given email</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/QVNrWZ04bf4/</link>
		<comments>http://leaverou.me/2009/12/quickly-find-the-gravatar-that-corresponds-to-a-given-email/#comments</comments>
		<pubDate>Mon, 07 Dec 2009 21:34:23 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Original]]></category>
		<category><![CDATA[Gravatar]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=470</guid>
		<description><![CDATA[Today I needed to quickly find the Gravatars that corresponded to a bunch of email addresses for some reason (don&#8217;t ask). After a bit of googling and wandering around in Gravatar&#8217;s official site and others, I firgured out it&#8217;s probably much quicker to write a short PHP script for that myself, than keep looking. Here [...]]]></description>
			<content:encoded><![CDATA[
<p>Today I needed to quickly find the Gravatars that corresponded to a bunch of email addresses for some reason (don&#8217;t ask). After a bit of googling and wandering around in <a href="http://gravatar.com" target="_blank">Gravatar&#8217;s official site</a> and others, I firgured out it&#8217;s probably much quicker to write a short PHP script for that myself, than keep looking.</p>
<p>Here it is, in case someone ever needs to do something similar: (click on the screenshot)</p>
<p><a href="http://leaverou.me/demos/gravatar.php"><img class="aligncenter size-full wp-image-471" title="Quickly find the Gravatar that cor­res­ponds to a given email" src="http://leaverou.me/wp-content/uploads/2009/12/gravatar.png" alt="Quickly find the Gravatar that cor­res­ponds to a given email" width="450" height="315" /></a></p>
<p>(has anyone noticed my latest love affair with Helvetica/Arial? <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  )</p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/QVNrWZ04bf4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/12/quickly-find-the-gravatar-that-corresponds-to-a-given-email/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/12/quickly-find-the-gravatar-that-corresponds-to-a-given-email/</feedburner:origLink></item>
		<item>
		<title>Reading cookies the regular expression way</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/XYW6gVSUjPg/</link>
		<comments>http://leaverou.me/2009/12/reading-cookies-the-regular-expression-way/#comments</comments>
		<pubDate>Thu, 03 Dec 2009 22:21:17 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Tips]]></category>
		<category><![CDATA[cookies]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[regular expressions]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=460</guid>
		<description><![CDATA[While taking a look on the 2nd 24ways article for 2009, I was really surprised to read that &#8220;The Web Storage API is basically cookies on steroids, a unhealthy dosage of steroids. Cookies are always a pain to work with. First of all you have the problem of setting, changing and deleting them. Typically solved [...]]]></description>
			<content:encoded><![CDATA[
<p>While taking a look on <a href="http://24ways.org/2009/breaking-out-the-edges-of-the-browser">the 2nd 24ways article for 2009</a>, I was really surprised to read that <em>&#8220;The Web Storage API is basically cookies on steroids, a unhealthy dosage of steroids. Cookies are always a pain to work with. First of all you have the problem of setting, changing and deleting them. <strong>Typically solved by Googling and blindly relying on PPK’s solution.</strong>&#8220;</em> (bold is mine)</p>
<p>Of course, there&#8217;s nothing wrong with <a href="http://www.quirksmode.org/js/cookies.html#script">PPK&#8217;s solution</a>. It works just fine. However, I always thought his readCookie() function was too verbose and complicated for no reason. It&#8217;s a very common example of someone desperately trying to avoid using a regular expression. I googled for &#8220;<a href="http://www.google.com/search?q=javascript+read+cookie">javascript read cookie</a>&#8221; and to my surprise, all examples found in the first results were very similar. I never understood why even experienced developers are so scared of regular expressions. Anyway, if anyone wants a shorter function to read a cookie, here&#8217;s what I use:</p>
<pre>function readCookie(name) {
    // Escape regexp special characters (thanks kangax!)
    name = name.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');

    var regex = new RegExp('(?:^|;)\\s?' + name + '=(.*?)(?:;|$)','i'),
        match = document.cookie.match(regex);

    return match &amp;&amp; unescape(match[1]); // thanks James!
}</pre>
<p><span style="color: #ff0000;"><strong>Update:</strong></span><strong> Function updated, see comments below</strong>.</p>
<p>I&#8217;ve been using it for years and it hasn&#8217;t let me down. <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Probably lots of other people have come up and posted something similar before me (I was actually very surprised that something like this isn&#8217;t mainstream), but I&#8217;m posting it just in case. <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/XYW6gVSUjPg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/12/reading-cookies-the-regular-expression-way/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/12/reading-cookies-the-regular-expression-way/</feedburner:origLink></item>
		<item>
		<title>Yet another email hiding technique?</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/T-FMOi9cmaI/</link>
		<comments>http://leaverou.me/2009/11/yet-another-email-hiding-technique/#comments</comments>
		<pubDate>Sun, 29 Nov 2009 06:36:26 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Original]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[spam]]></category>
		<category><![CDATA[Unicode]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=443</guid>
		<description><![CDATA[While exploring browser-supported Unicode characters, I noticed that apart from the usual @ and . (dot), there was another character that resembled an @ sign (0xFF20 or ＠) and various characters that resembled a period (I think 0&#215;2024 or ․ is closer, but feel free to argue). I&#8217;m wondering, if one could use this as [...]]]></description>
			<content:encoded><![CDATA[
<p>While <a href="http://leaverou.me/2009/11/exploring-browser-supported-unicode-characters-and-a-tweet-shortening-experiment/">exploring browser-supported Unicode characters</a>, I noticed that apart from the usual @ and . (dot), there was another character that resembled an @ sign (0xFF20 or ＠) and various characters that resembled a period (I think 0&#215;2024 or ․ is closer, but feel free to argue).</p>
<p>I&#8217;m wondering, if one could use this as another way of email hiding. It&#8217;s almost as easy as the foo [at] bar [dot] com technique, with the advantage of being far less common (I&#8217;ve never seen it before, so there&#8217;s a high chance that spambot developers haven&#8217;t either) and I think that the end result is more easily understood by newbies. To encode <a class="linkification-ext" title="Linkification: mailto:foo@bar.com" href="mailto:foo@bar.com">foo@bar.com</a> this way, we&#8217;d use (in an html page):</p>
<pre>foo&amp;#xFF20;bar&amp;#x2024;com</pre>
<p>and the result is: <span style="font-size:1.5em">foo＠bar․com</span></p>
<p>I used that technique on the <a href="http://leaverou.me/demos/ligatweet/#conversions">ligatweet page</a>. Of course, if many people start using it, I guess spambot developers will notice, so it won&#8217;t be a good idea any more. However, for some reason I don&#8217;t think it will ever become that mainstream <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p>By the way, if you&#8217;re interested in other ways of email hiding, <a href="http://www.csarven.ca/hiding-email-addresses">here&#8217;s an extensive article on the subject</a> that I came across after a quick googlesearch (to see if somebody else came up with this first &#8212; I didn&#8217;t find anything).</p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/T-FMOi9cmaI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/11/yet-another-email-hiding-technique/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/11/yet-another-email-hiding-technique/</feedburner:origLink></item>
		<item>
		<title>Exploring browser-supported Unicode characters and a tweet shortening experiment</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/NIKDgozhOeI/</link>
		<comments>http://leaverou.me/2009/11/exploring-browser-supported-unicode-characters-and-a-tweet-shortening-experiment/#comments</comments>
		<pubDate>Sun, 29 Nov 2009 06:10:20 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Original]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[ligatweet]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[Unicode]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=438</guid>
		<description><![CDATA[I recently wanted to post something on twitter that was just slightly over the 140 chars limit and I didn&#8217;t want to shorten it by cutting off characters (some lyrics from Pink Floyd&#8217;s &#8220;Hey You&#8221; that expressed a particular thought I had at the moment &#8212; it would be barbaric to alter Roger Waters&#8217; lyrics [...]]]></description>
			<content:encoded><![CDATA[
<p>I recently wanted to post something on twitter that was just slightly over the 140 chars limit and I didn&#8217;t want to shorten it by cutting off characters (some lyrics from Pink Floyd&#8217;s &#8220;Hey You&#8221; that expressed a particular thought I had at the moment &#8212; it would be barbaric to alter Roger Waters&#8217; lyrics in any way, wouldn&#8217;t it? <img src='http://leaverou.me/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> ). I always knew there were some ligatures and digraphs in the Unicode table, so I thought that these might be used to shorten tweets, not only that particular one of course, but any tweet. So I wrote <a title="Browser supported unicode characters" href="http://leaverou.me/scripts/unicode.html" target="_blank">a small script</a> (warning: very rough around the edges) to explore the Unicode characters that browsers supported, find the replacement pairs and build the tweet shortening script (I even thought of a name for it: ligatweet, LOL I was never good at naming).<span id="more-438"></span></p>
<p>My observations were:</p>
<ul>
<li>Different browsers support different Unicode characters. I think Firefox has the best support (more characters) and Chrome the worst. By the way, it&#8217;s a shame that Chrome doesn&#8217;t support the Braille characters.</li>
<li>The appearance of the same characters, using the same font has huge differences across browsers. A large number of glyphs are completely different. This is very apparent on dingbats (around 0&#215;2600-0&#215;2800).</li>
<li>For some reason unknown to me, hinting suffers a great deal in the least popular characters (common examples are the unit ligatures, like ㏈ or ㎉). Lots of them looked terribly unlegible and pixelated in small sizes (and only in small sizes!!). Typophiles feel free to correct me if I&#8217;m mistaken, but judging by my brief experience with font design, I don&#8217;t think bad hinting (or no hinting at all) can do that sort of thing to a glyph. These characters appeared without any anti-aliasing at all! Perhaps it has to do with Cleartype or Windows (?). If anyone has any information about the cause of this issue, I would be greatly interested.</li>
<li>It&#8217;s amazing what there&#8217;s in the Unicode table! There are many dingbats and various symbols in it, and a lot of them work cross browser! No need to be constrained by the small subset that html entities can produce!</li>
</ul>
<p>The tweet shortening script is here: <a class="linkification-ext" title="Linkification: http://leaverou.me/demos/ligatweet/" href="http://leaverou.me/demos/ligatweet/">http://leaverou.me/demos/ligatweet/</a></p>
<p>I might as well write a bookmarklet in the future. However, I was a bit disappointed to find out that even though I got a bit carried away when picking the replacement pairs, the gains are only around 6-12% for most tweets (case sensitive, of course case insensitive results in higher savings, but the result makes you look like a douchebag), but I&#8217;m optimistic that as more pairs get added (feel free to suggest any, or improvements on the current ones) the savings will increase dramatically. And even if they don&#8217;t I really enjoyed the trip.</p>
<p>Also, exploring the Unicode table gave me lots of ideas about scripts utilizing it, some of which I consider far more useful than ligatweet (although I&#8217;m not sure if I&#8217;ll ever find the time to code them, even ligatweet was finished because I had no internet connection for a while tonight, so I couldn&#8217;t work and I didn&#8217;t feel like going to sleep)</p>
<p>By the way, In case you were wondering, I didn&#8217;t post the tweet that inspired me to write the script. After coding for a while, It just didn&#8217;t fit my mood any more. <img src='http://leaverou.me/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/NIKDgozhOeI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/11/exploring-browser-supported-unicode-characters-and-a-tweet-shortening-experiment/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/11/exploring-browser-supported-unicode-characters-and-a-tweet-shortening-experiment/</feedburner:origLink></item>
		<item>
		<title>A different approach to elastic textareas</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/Z8Mwi-ebLd8/</link>
		<comments>http://leaverou.me/2009/11/a-different-approach-to-elastic-textareas/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 22:06:22 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Original]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=425</guid>
		<description><![CDATA[I loved elastic textareas since the very first moment I used one (at facebook obviously). They let you save screen real estate while at the same time they are more comfortable for the end user. It&#8217;s one of the rare occasions when you can have your UI cake and eat it too! However, I never [...]]]></description>
			<content:encoded><![CDATA[
<p>I loved elastic textareas since the very first moment I used one (at facebook obviously). They let you save screen real estate while at the same time they are more comfortable for the end user. It&#8217;s one of the rare occasions when you can have your UI cake and eat it too!</p>
<p>However, I never liked the implementation of the feature. In case you never wondered how it&#8217;s done, let me explain it in a nutshell: All elastic textarea scripts (or at least all that I know of) create a hidden (actually, absolutely positioned and placed out of the browser window) div, copy some CSS properties from the textarea to it (usually padding, font-size, line-height, font-family, width and font-weight) and whenever the contents of the textarea change they copy them to the hidden div and measure it&#8217;s dimensions. It might be good enough for facebook, where the styling of those textareas is fairly simple and consistent throughout the site, or any other particular site, but as a generic solution? I never liked the idea.<span id="more-425"></span></p>
<p>So, I tried to explore a different approach. As Andrea Giammarchi <a href="http://webreflection.blogspot.com/2009/11/google-closure-im-not-impressed.html" target="_blank">recently wrote</a><em> &#8220;This is almost intrinsic, as developers, in our DNA: we spot some interesting concept? We rewrite it from scratch pretending we are doing it better!&#8221;</em> and I&#8217;m no exception (although in this case I don&#8217;t think I did it better, I just think it has potential). The basic idea is quite naive, but it works quite well in most browsers (Internet Explorer being the black sheep as usual): Test if the textarea is scrollable, and if so, increase it&#8217;s <code>rows</code> attribute and try again. If it&#8217;s not scrollable initially, try decreasing it&#8217;s <code>rows</code> attribute until it becomes scrollable (and then ++ it).</p>
<p>It works flawlessly on Firefox and quite well on Safari, Chrome and Opera (it just slightly twitches when it enlarges in those). Stupid Internet Explorer though repaints too many times, causing a flicker at the bottom when the user is typing, something really disturbing, so I can&#8217;t consider the script anything above <strong>experimental </strong>at the moment. I&#8217;m just posting it in case anyone has an idea of how to fix the aforementioned issues, because apart from those it has quite a few advantages:</p>
<ul>
<li>Should work with any CSS styles</li>
<li><strong>No</strong> library requirements (unlike all the others I know of)</li>
<li>Only<strong> 800 bytes</strong> minified (2.4KB originally)</li>
</ul>
<p>So, here it is:</p>
<ul>
<li><a href="http://leaverou.me/scripts/elastic-textarea/">Demo</a></li>
<li><a href="http://leaverou.me/scripts/elastic-textarea/elastic-textarea.js">elastic-textarea.js</a></li>
<li><a href="http://leaverou.me/scripts/elastic-textarea/elastic-textarea-min.js">elastic-textarea-min.js</a></li>
</ul>
<p><em>For the record, I <strong>don&#8217;t </strong>think that a script <strong>should </strong>be needed for things like that. This looks like something that should be handled by CSS alone. We basically want the height of an element to adjust as necessary for it&#8217;s contents to fit. We already use CSS for these things on other elements, why not form controls as well?</em></p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/Z8Mwi-ebLd8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/11/a-different-approach-to-elastic-textareas/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/11/a-different-approach-to-elastic-textareas/</feedburner:origLink></item>
		<item>
		<title>New version of rgba.php is out!</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/PQUvSf4j5cI/</link>
		<comments>http://leaverou.me/2009/10/new-version-of-rgba-php-is-out/#comments</comments>
		<pubDate>Sun, 25 Oct 2009 07:44:57 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Original]]></category>
		<category><![CDATA[colors]]></category>
		<category><![CDATA[CSS3]]></category>
		<category><![CDATA[CSS3 values]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[RGBA]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=418</guid>
		<description><![CDATA[It&#8217;s been a while since I posted my little server-side solution for cross-browser RGBA colors (in a nutshell: native rgba for the cool browsers that support it, a PHP-generated image for those that don&#8217;t). For features, advantages, disadvantages etc, go see the original post. In this one I&#8217;ll only discuss the new version. So, since [...]]]></description>
			<content:encoded><![CDATA[
<p><a href="http://leaverou.me/2009/02/bulletproof-cross-browser-rgba-backgrounds/">It&#8217;s been a while since I posted my little server-side solution for cross-browser RGBA colors</a> (in a nutshell: native rgba for the cool browsers that support it, a PHP-generated image for those that don&#8217;t). For features, advantages, disadvantages etc, go see the original post. In this one I&#8217;ll only discuss the new version.</p>
<p>So, since it&#8217;s release I&#8217;ve received suggestions from many people regarding this script. Some other ideas were gathered during troubleshooting issues that some others faced while trying to use it. I hope I didn&#8217;t forget anything/anyone <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> <span id="more-418"></span></p>
<h3>Changelog (+credits):</h3>
<ol>
<li>You may now specify the size of the generated image (thanks <em><strong><a href="http://leaverou.me/2009/02/bulletproof-cross-browser-rgba-backgrounds/#comment-122">Sander Arts</a></strong></em>!)</li>
<li>If the PHP version is below 5.1.7 the call to imagepng() uses 2 parameters instead of 4, to workaround the bug found by <em><strong><a href="http://leaverou.me/2009/02/bulletproof-cross-browser-rgba-backgrounds/#comment-103">Bridget</a></strong></em> (thanks <strong><em>Chris Neale</em></strong> for suggesting the use of phpversion()!)</li>
<li>Added error_reporting() to only allow for fatal errors and parse errors to go through (I should had done this anyway but I completely forgot). This solves an issue that <strong><em>Erin Doak</em></strong> pointed out, since they had set up notices to be displayed and even a reference to an undefined index made the whole script collapse.</li>
<li><em><strong>Mariotti Raffaele </strong></em>pointed out that apache_request_headers() was not defined in all PHP installations. After looking into it a bit, I found out that it&#8217;s available only when PHP is installed as an Apache module. After some more research it turned out that the only way to get the If-Modified-Since header otherwise is an .htaccess, so I  ruled that out (It would complicate the workaround I think and I doubt all hosts allow .htaccess (?). On the other hand, an .htacess would also allow for some URL rewriting goodness&#8230; Hmmm&#8230; Should I consider this?). So, if the function is not available, it serves the file with an 200 response code every time, instead of just sending a 304 response when the If-Modified-Since header is present.</li>
<li><a href="http://leaverou.me/2009/10/new-version-of-rgba-php-is-out/#comment-893"><strong>Igor Zevaka</strong></a> for pointing out that the Expires header wasn&#8217;t a valid HTTP date.</li>
</ol>
<h3>Links</h3>
<p><strong><a href="http://leaverou.me/wp-content/uploads/2009/10/rgba.zip">rgba.php</a></strong></p>
<p><strong><a href="http://leaverou.me/wp-content/themes/leaverou/images/rgba.php?r=255&amp;g=0&amp;b=100&amp;a=80">Demo</a></strong></p>
<p>Enjoy <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  and please report any bugs!</p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/PQUvSf4j5cI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/10/new-version-of-rgba-php-is-out/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/10/new-version-of-rgba-php-is-out/</feedburner:origLink></item>
		<item>
		<title>A CSS3 learning(?) tool</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/hDzmF3pDAMc/</link>
		<comments>http://leaverou.me/2009/10/a-css3-learning-tool/#comments</comments>
		<pubDate>Thu, 08 Oct 2009 06:52:01 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Replies]]></category>
		<category><![CDATA[CSS3]]></category>
		<category><![CDATA[CSS3 properties]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=414</guid>
		<description><![CDATA[In case anyone is interested, this is my take on the &#8220;challenge&#8221; that Brad Neuberg posted today on Ajaxian. It needs more properties, but it&#8217;s very easy to extend. I guess I should also add CSS3 values (RGBA/HSL(A) colors, CSS gradients etc) but oh well, I&#8217;m currently in a hurry. I will, if anyone actually [...]]]></description>
			<content:encoded><![CDATA[
<p>In case anyone is interested, <a href="http://leaverou.me/scripts/css3learn.html">this is my take</a> on the <a href="http://ajaxian.com/archives/interactive-css-3-generator" target="_blank">&#8220;challenge&#8221; that Brad Neuberg posted today on Ajaxian</a>. It needs more properties, but it&#8217;s very easy to extend. I guess I should also add CSS3 values (RGBA/HSL(A) colors, CSS gradients etc) but oh well, I&#8217;m currently in a hurry. I will, if anyone actually finds it useful (?).</p>
<p>It didn&#8217;t prove much of a challenge actually and I honestly doubt it&#8217;s educational value (actually it&#8217;s value in general), but it was an interesting thing to do while drinking my first coffee in the morning &#8212; I really enjoyed writing it <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/hDzmF3pDAMc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/10/a-css3-learning-tool/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/10/a-css3-learning-tool/</feedburner:origLink></item>
		<item>
		<title>Exploring CSS3 text-shadow</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/u_fEbSxlfpA/</link>
		<comments>http://leaverou.me/2009/09/css-text-shadow/#comments</comments>
		<pubDate>Sun, 13 Sep 2009 23:13:19 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[browser bugs]]></category>
		<category><![CDATA[browsers]]></category>
		<category><![CDATA[Chrome bugs]]></category>
		<category><![CDATA[CSS3]]></category>
		<category><![CDATA[CSS3 properties]]></category>
		<category><![CDATA[experiments]]></category>
		<category><![CDATA[Opera bugs]]></category>
		<category><![CDATA[Safari bugs]]></category>
		<category><![CDATA[text-shadow]]></category>
		<category><![CDATA[Webkit bugs]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=389</guid>
		<description><![CDATA[I consider CSS3&#8242;s text-shadow one of the most exciting CSS3* properties, which offers us a lot more effects than it&#8217;s name suggests. Of course, it can be used for creating drop shadows for text, and it carries out that task very well, but it&#8217;s inherent flexibility allows it to be also used for glow effects, [...]]]></description>
			<content:encoded><![CDATA[
<p>I consider CSS3&#8242;s <code>text-shadow</code> one of the most exciting CSS3* properties, which offers us a lot more effects than it&#8217;s name suggests. Of course, it can be used for creating drop shadows for text, and it carries out that task very well, but it&#8217;s inherent flexibility allows it to be also used for glow effects, outlines, bevels, extruded text, inset text, fuzzy text and many others (until browser bugs and backwards compatibility come into play&#8230; <img src='http://leaverou.me/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> ). This post is about various findings of mine (and others&#8217;, where a source is provided) regarding this property, including browser bugs and inconsistencies, effects that can be achieved with it, compatibility woes etc.<span id="more-389"></span></p>
<h3>Browser support</h3>
<ul>
<li>Opera 9.5+</li>
<li>Firefox 3.5+</li>
<li>Safari 1.0+</li>
<li>Google Chrome</li>
</ul>
<h3>text-shadow syntax</h3>
<p>The syntax is fairly simple:</p>
<pre>text-shadow: &lt;offset-x&gt; &lt;offset-y&gt; &lt;blur-radius&gt; &lt;color&gt;;</pre>
<p>There are some variations (the color could be first instead of last, the blur radius can be omitted if it&#8217;s equal to zero and the color may be omitted if it&#8217;s the same as the text color) and you may include multiple comma delimited shadows.</p>
<p>You may read more about the syntax in the official <a href="http://www.w3.org/TR/css3-text/#text-shadow">specification</a>.</p>
<h3>How it works</h3>
<p>It helps if you imagine the algorithm for drawing the text shadow as follows:</p>
<ol>
<li>Create a (most of the times differently colored) clone of the text and place it behind the text.</li>
<li>Move it according to the X and Y offsets (positive values move it to the right and bottom respectively)</li>
<li>If a blur radius is specified and it&#8217;s &gt; 0, blur it accordingly (the specification doesn&#8217;t mention the blurring algorithm to be used, so each browser vendor may choose any blurring algorithm they prefer, and judging by my experiments, it seems they took advantage of this freedom). <strong>In all cases however, the bounding box of the blurred text can extend no further than the bounding box of the original text plus (+) the specified blur radius on each side.</strong></li>
<li>Repeat for the rest of the shadows, if more than 1 are specified. The order in which shadows are drawn seems to be a subject of debate, judging by the wording of the specification and the various existing implementations.</li>
</ol>
<h3>The experiments</h3>
<p>You will find the experiments I performed <a href="http://leaverou.me/demos/text-shadow.html">here</a>. I tried to come up with (or find) interesting uses of the property. I also tried to make some of them &#8220;pretty&#8221;, so they could be useful to others, but given the fact that these were primarily created for testing purposes, this wasn&#8217;t achievable for all of them. Next to each experiment is the CSS used to produce the effect (directly fetched from the &lt;style&gt; tag via JavaScript). You&#8217;d better not view it with IE until you read below or you might have some freaky nightmares tonight <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p>Screenshots from various browsers: (mouse over the thumbnails to see which browser was used for each one)</p>

<a href='http://leaverou.me/2009/09/css-text-shadow/firefox/' title='Firefox 3.5'><img width="150" height="150" src="http://leaverou.me/wp-content/uploads/2009/09/firefox-150x150.png" class="attachment-thumbnail" alt="Firefox 3.5" title="Firefox 3.5" /></a>
<a href='http://leaverou.me/2009/09/css-text-shadow/safari/' title='Safari 4'><img width="150" height="150" src="http://leaverou.me/wp-content/uploads/2009/09/safari-150x150.png" class="attachment-thumbnail" alt="Safari 4" title="Safari 4" /></a>
<a href='http://leaverou.me/2009/09/css-text-shadow/opera/' title='Opera 10'><img width="150" height="150" src="http://leaverou.me/wp-content/uploads/2009/09/opera-150x150.png" class="attachment-thumbnail" alt="Opera 10" title="Opera 10" /></a>
<a href='http://leaverou.me/2009/09/css-text-shadow/opera9-6/' title='Opera 9.6'><img width="150" height="150" src="http://leaverou.me/wp-content/uploads/2009/09/opera9.6-150x150.png" class="attachment-thumbnail" alt="Opera 9.6" title="Opera 9.6" /></a>
<a href='http://leaverou.me/2009/09/css-text-shadow/chrome/' title='Google Chrome'><img width="150" height="150" src="http://leaverou.me/wp-content/uploads/2009/09/chrome-150x150.png" class="attachment-thumbnail" alt="Google Chrome" title="Google Chrome" /></a>
<a href='http://leaverou.me/2009/09/css-text-shadow/the_devil_wears_filters/' title='Internet Explorer 8'><img width="150" height="150" src="http://leaverou.me/wp-content/uploads/2009/09/the_devil_wears_filters-150x150.png" class="attachment-thumbnail" alt="Internet Explorer 8" title="Internet Explorer 8" /></a>

<h3>Browser bugs and inconsistencies</h3>
<p>Apparently, some browser bugs were exposed in these experiments:</p>
<ul>
<li><strong>Opera 10</strong> and <strong>Safari</strong> don&#8217;t display the shadow when the text color is <code>transparent</code> (demonstrated in Experiment #5). <strong>Opera 9.6</strong> doesn&#8217;t seem to support <code>transparent</code> as a text color, so it ignores it.</li>
<li>When the text color is RGBA, <strong>Safari </strong>applies transparency to the shadow, equal to the Alpha component (demonstrated in Experiment #8).</li>
<li><strong>Opera</strong> paints the shadows in the order they were specified, whereas all others use the reverse. According to the current version of the specification, Opera is the only correct one, but I doubt that web designers will give her credit for it :p (Experiment #8)</li>
<li><strong>Google Chrome</strong> uses a crappy blurring algorithm (Experiments #5 and #7)</li>
<li><strong>Safari </strong>and <strong>Chrome </strong>don&#8217;t default to the text color when no color is specified in text-shadow, but to <code>transparent</code>. (Experiment #2)</li>
<li><strong>Opera </strong>is seriously messed up when it comes to transparent shadows, as demonstrated by Experiment #9. I can&#8217;t even describe the bug (try messing with the text-shadow value a bit and you&#8217;ll see why&#8230;). Luckily, I can&#8217;t think of a single case where a transparent text-shadow would be useful <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </li>
<li>You can see a bit of the shadow in <strong>Google Chrome</strong> even if the offsets and blur radius are all 0 (Experiment #9). I&#8217;m not sure if this is a bug, but it&#8217;s inconsistent with the other implementations.</li>
<li>Even if you ignore the bugs above, there are slight rendering variations when multiple blurred shadows are involved (or they are more apparent in those cases), as demonstrated by experiments #2, #6 and #7.</li>
</ul>
<p>Firefox&#8217;s implementation seems to be the clear winner here&#8230;</p>
<p>A note about the above observations: When no version number is mentioned, 3.5 is implied for Firefox, 10 for Opera and 4 for Safari and Chrome.</p>
<h3>Alternatives to text-shadow</h3>
<h4>IE Filters</h4>
<p>As you might have noticed, I have managed to completely avoid mentioning Internet Explorer up to this point. It&#8217;s no surprise that our dearest browser doesn&#8217;t support the text-shadow property. However, it does support some filters (<a href="http://msdn.microsoft.com/en-us/library/ms532985%28VS.85%29.aspx">DropShadow</a> and <a href="http://msdn.microsoft.com/en-us/library/ms533086%28VS.85%29.aspx">Shadow</a>) that could be used to provide a very small subset of the different kinds of text shadows, although they severely <strong>mess up the font anti-aliasing</strong> (just like all IE filters). Also, if the parent or siblings of the text node in question have backgrounds or borders <strong>an extra element is needed to enclose the text node</strong> (you&#8217;ll see in the experiments why&#8230;). For these reasons,  I highly doubt whether they are worth it and I don&#8217;t use them personally. However, if you are interested you can see a brief demonstration of these two filters in Experiments #3 (DropShadow) and #6 (Shadow, actually 4 of them).</p>
<h3>The :before pseudo-element</h3>
<p>This could be used instead of the text-shadow, when the blur radius is 0, since browser support for the :before pseudo-element is better than browser support for text-shadow (even IE8 supports that, yay). <a href="http://www.workingwith.me.uk/articles/css/cross-browser-drop-shadows">Here is a thorough (although slightly outdated) tutorial on this technique</a>. However,this workaround severely hurts separation of presentation and content/structure, since the content has to be duplicated in the CSS. Repeating something greatly increases the chance that the two copies become inconsistent, since people tend to be forgetful. Also, you have to know in advance the exact height of the text (in lines), another maintenance headache. For these reasons, I don&#8217;t use this workaround either.</p>
<p>In my humble opinion, the text shadow is usually just icing on the cake and not something crucial to the design, so it doesn&#8217;t hurt if it won&#8217;t show in some old and/or crappy browsers. It degrades gracefully in most cases (ok, you&#8217;ll have to wait a few years before using it in ways that don&#8217;t) so it doesn&#8217;t hurt usability/accessibility either. It&#8217;s just one of the little treats I like to offer to visitors that were smart enough to use a decent browser. <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<h3>Epilogue</h3>
<p>text-shadow is a very flexible property, with probably the best browser and editor &#8212; even Dreamweaver acknowledges it&#8217;s existence! &#8212; support among all notable CSS3* properties. It also degrades gracefully most of the times (the experiments above shouldn&#8217;t be considered &#8220;most of the times&#8221;! <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  ) and this is why it&#8217;s probably also the most widely used CSS3* property.</p>
<p>I think it could be improved even more by allowing for the inset keyword (just like inset box-shadows &#8212; sadly only Firefox 3.5 supports those at the time) and a fourth parameter could be used to enlarge or shrink the shadow (currently the only way to enlarge it is by blurring it, which isn&#8217;t always desirable) although it would complicate the shorthand (the blur radius would probably become required &#8212; so that the browser can tell them apart). However, a separate property could be used to solve that (text-shadow-size?). I guess we could combine the :before technique, with transparent text color (in the :before pseudo-element) and a text-shadow for that to imitate such an effect (I can elaborate if this seems obscure) although I haven&#8217;t actually tried it (however, even if it works, it&#8217;s too much of a hassle).</p>
<p>Anyway, I guess it&#8217;s too late for such suggestions, so let&#8217;s focus on what we actually will get (?) which is more than sufficient <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>______________________________________________________________</p>
<p>*Actually, it was originally proposed for CSS 2.1, but it was dropped due to lack of implementations (basically only Webkit supported it)</p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/u_fEbSxlfpA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/09/css-text-shadow/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/09/css-text-shadow/</feedburner:origLink></item>
		<item>
		<title>(byte)size matters</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/GuqtZv7S574/</link>
		<comments>http://leaverou.me/2009/07/bytesize-matters/#comments</comments>
		<pubDate>Fri, 31 Jul 2009 17:01:18 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[bytesizematters]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=378</guid>
		<description><![CDATA[Yesterday, I was editing a CSS file and I was wondering how many bytes/KB would a particular addition add to it, in order to decide if it was worth it. Since, I had found myself wondering about the exact same thing multiple times in the past, I decided to make a simple standalone HTML page [...]]]></description>
			<content:encoded><![CDATA[
<p>Yesterday, I was editing a CSS file and I was wondering how many bytes/KB would a particular addition add to it, in order to decide if it was worth it. Since, I had found myself wondering about the exact same thing multiple times in the past, I decided to make a simple standalone HTML page that would compute the size of any entered text in bytes, KB, MB, etc (whatever was most appropriate). It should be simple and quick and it should account for line terminator differences across operating systems.</p>
<p>About half an hour later, I was done. And then it dawned on me: Someone else might need it too! Since .com domains are, so cheap, hey, let&#8217;s get a domain for it as well! There are <a href="http://kottke.org/08/02/single-serving-sites">several</a> <a href="http://dowebsitesneedtolookexactlythesameineverybrowser.com/">sites</a> <a href="http://amiawesome.com/">with</a> <a href="http://r33b.net/">a</a> <a href="http://isitchristmas.com/">domain</a> <a href="http://justfuckinggoogleit.com/">that</a> <a href="http://www.sometimesredsometimesblue.com/">are</a> <a href="http://www.d-e-f-i-n-i-t-e-l-y.com/">way</a> <a href="http://www.tired.com/">simpler</a> than that anyway. A friend that was sitting next to me suggested &#8220;sizematters.com&#8221; as a joke, but as it turned out, <a title="(byte)size matters!" href="http://bytesizematters.com">bytesizematters.com</a> was free, so we registered it. And there it is, less than a day after, <a href="http://bytesizematters.com">it&#8217;s aliiive</a>. <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p>Any feedback or suggestions are greatly welcome!</p>
<p><span style="text-decoration: line-through;">For instance, should I implement a very simple minification algorithm and display bytesize for that as well, or is it too much and ruins the simplicity of it without being worth it? </span><strong>[edit: I did it anyway]</strong></p>
<p><span style="text-decoration: line-through;">Should I implement a way to compare two pieces of text and find out the difference in byte size (could be useful for JavaScript refactoring)?</span> <strong>[edit:</strong><strong> I did it anyway</strong><strong>]</strong></p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/GuqtZv7S574" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/07/bytesize-matters/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/07/bytesize-matters/</feedburner:origLink></item>
		<item>
		<title>Bevels in CSS3</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/j-f1KKMy4Vo/</link>
		<comments>http://leaverou.me/2009/07/bevels-in-css3/#comments</comments>
		<pubDate>Thu, 23 Jul 2009 19:24:22 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Original]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[box-shadow]]></category>
		<category><![CDATA[CSS3]]></category>
		<category><![CDATA[CSS3 properties]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=368</guid>
		<description><![CDATA[Yeah, yeah I know, bevels are soooo 1996. And I agree. However, it&#8217;s always good to know the capabilities of your tools. Talented designers will know when it&#8217;s suitable to use a certain effect and incapable ones will abuse whatever is given to them, so after a lot of thought, I decided to blog about [...]]]></description>
			<content:encoded><![CDATA[
<p>Yeah, yeah I know, bevels are soooo 1996. And I agree. However, it&#8217;s always good to know the capabilities of your tools. Talented designers will know when it&#8217;s suitable to use a certain effect and incapable ones will abuse whatever is given to them, so after a lot of thought, I decided to blog about my discovery.<span id="more-368"></span></p>
<p>Even though not directly mentioned in the spec, CSS3 is capable of easily creating a bevel effect on any element. Moreover, if the element has rounded corners, the bevel follows that as well. Before explaining the technique, let&#8217;s think about how a bevel actually gets drawn. It&#8217;s essentially two inner shadows, that when combined, create the illusion of a 3d appearance: a light one from the top left corner and a dark one from the bottom right corner. CSS3 includes the ability to create inner shadows, if you specify the keyword &#8220;inset&#8221; in the box-shadow declaration (currently only supported by Firefox 3.5). Moreover, the CSS3 spec allows for multiple box shadows on the same elements.</p>
<p>Now, let&#8217;s examine an example (only works in Firefox 3.5):</p>
<pre>button {
 background:#f16;
 color:white;
 padding:6px 12px 8px 12px;
 border:none;
 font-size:18px;
 -moz-border-radius:10px;
 -moz-box-shadow: -2px -2px 10px rgba(0,0,0,.25) inset, 2px 2px 10px white inset;
}</pre>
<p>which produces this result:</p>
<p><img class="alignnone size-full wp-image-369" title="css3bevel" src="http://leaverou.me/wp-content/uploads/2009/07/css3bevel.png" alt="css3bevel" width="110" height="52" /></p>
<p>If we want, we can also create a &#8220;pressed&#8221; button state, in a similar fashion:</p>
<pre>button:active {
 -moz-box-shadow: 2px 2px 10px rgba(0,0,0,.25) inset, -2px -2px 10px white inset;
 padding:7px 11px 7px 13px;
}

button::-moz-focus-inner { border: 0; }</pre>
<p>which produces this pressed state:</p>
<p><img class="alignnone size-full wp-image-370" title="css3bevel_pressed" src="http://leaverou.me/wp-content/uploads/2009/07/css3bevel_pressed.png" alt="css3bevel_pressed" width="116" height="56" /></p>
<p>See it in action here (only for Firefox 3.5): <a class="linkification-ext" title="Linkification: http://leaverou.me/demos/css3bevel.html" href="http://leaverou.me/demos/css3bevel.html">http://leaverou.me/demos/css3bevel.html</a></p>
<p>Of course, if implemented in a real world website, you should also add the -webkit- and -o- CSS3 properties to provide a closer effect for the other browsers and be ready for the time when the ones that aren&#8217;t implemented yet in them will finally make it (for instance, when Webkit implements inset box shadows, it will work in it as well).</p>
<p>Enjoy <strong>responsibly</strong>. <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/j-f1KKMy4Vo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/07/bevels-in-css3/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/07/bevels-in-css3/</feedburner:origLink></item>
		<item>
		<title>Idea: The simplest registration form ever</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/QEKEsVL1XoU/</link>
		<comments>http://leaverou.me/2009/07/idea-the-simplest-registration-form-ever/#comments</comments>
		<pubDate>Thu, 23 Jul 2009 17:04:12 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Thoughts]]></category>
		<category><![CDATA[registration forms]]></category>
		<category><![CDATA[UI]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=361</guid>
		<description><![CDATA[If a web application has some sort of registration system (and most do), the registration page should be one of the most attractive, inviting, usable pages of it. It should make you to want to register, not repulse you. We don&#8217;t want the user to give up in the middle of filling it because they [...]]]></description>
			<content:encoded><![CDATA[
<p>If a web application has some sort of registration system (and most do), the registration page should be one of the most attractive, inviting, usable pages of it. It should make you to <strong>want</strong> to register, not repulse you. We don&#8217;t want the user to give up in the middle of filling it because they are fed up with it&#8217;s length or bad usability, or -even worse- not even attempt to do so, do we?</p>
<p>The most popular websites usually take this rule to heart and employ the simplest registration forms: Only the basic fields required, and most of the times, even without password/email confirmation.</p>
<p>I was wondering lately &#8211; what would be the simplest possible registration form? <span id="more-361"></span>It should have the minimum number of fields required: Username and password and a field for some kind of human verification.</p>
<p>At this point, some readers might argue &#8220;Hey, why not an email field as well?&#8221;. In my opinion, the email is not always a required field. Let&#8217;s see why it&#8217;s being asked for in most cases: Unique identification (to prevent double accounts) and for sending out notifications for important events. However, it&#8217;s useless for the first purpose due to all these disposable email websites. As for the second purpose, since notifications can be switched off (and if not, then they are essentially considered spam), it could be regarded optional and we don&#8217;t include optional fields in registration forms, do we? <img src='http://leaverou.me/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Of course, in websites that use the email instead of a username to let their users log in, you may just substitute the username field above with an email field (since in that case, the username is what could be considered optional) and we also have two fields. Smart readers might have noticed another pattern here: The only fields that are truly required for a registration form are the same ones that are required for a login form plus a human verification field.</p>
<p>And then it dawned on me: We can make the registration process almost as quick as logging in! We could use the same form for both actions. The submit button label could indicate the dual nature of the form, for instance &#8220;Log in or register&#8221;. If the username (or email) doesn&#8217;t exist, we could then ask the user whether they want to create a new account and present them the human verification field at that point. There is no need for a password verification field, since <a href="http://leaverou.me/2009/06/on-password-masking-and-usability/">we could just have a checkbox for displaying what the user typed</a>, if they feel insecure about it.</p>
<p>I find 3 inherent issues with this approach:</p>
<ol>
<li>Security. If a login attempt fails, the user will know whether he got the username or the password wrong. However, in most websites, you can easily check whether a username exists anyway, so I don&#8217;t consider this a real concern. I just included it because I&#8217;m certain that if I didn&#8217;t, somebody would point it out to me in the comments.</li>
<li>Despite being a more usable approach by nature, it&#8217;s not by any means a convention yet. Until it becomes one, I&#8217;m afraid that some users will be confused by its extreme &#8230;simplicity! Funny, isn&#8217;t it?</li>
<li>We won&#8217;t be able to employ Ajax verification for the registration form, since it will essentially be a login form as well, and until the user submits, we won&#8217;t know what they plan to do (login or register). Having an Ajax verification script there by default will confuse existing users as hell (as in <em>&#8220;What do they mean by &#8216;Username is taken&#8217;? WTF??&#8221;</em>). So, we have to sacrifice some usability to gain some usability. The question is: Is the usability we gain more than the usability we sacrifice? What do you think?</li>
</ol>
<p>As you can see by the problems mentioned above, it&#8217;s still a rough-on-the-edges idea (I just thought about it and I haven&#8217;t refined it yet), but I think it&#8217;s interesting. What are your thoughts?</p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/QEKEsVL1XoU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/07/idea-the-simplest-registration-form-ever/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/07/idea-the-simplest-registration-form-ever/</feedburner:origLink></item>
		<item>
		<title>On password masking and usability</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/8wYg2CnDbds/</link>
		<comments>http://leaverou.me/2009/06/on-password-masking-and-usability/#comments</comments>
		<pubDate>Sun, 28 Jun 2009 16:24:50 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Internet Explorer bugs]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=351</guid>
		<description><![CDATA[I just read Jakob Nielsen&#8217;s recent post in which he urged web designers/developers to stop password masking due to it&#8217;s inherent usability issues. I found it an interesting read. Hey, at last, someone dared to talk about the elephant in the room! In most cases password masking is indeed useless, but still, there are several [...]]]></description>
			<content:encoded><![CDATA[
<p>I just read <a href="http://www.useit.com/alertbox/passwords.html" target="_blank">Jakob Nielsen&#8217;s recent post in which he urged web designers/developers to stop password masking</a> due to it&#8217;s inherent usability issues. I found it an interesting read. Hey, at last, someone dared to talk about the elephant in the room!</p>
<p>In most cases password masking is indeed useless, but still, there are several cases where you need that kind of protection. He also points that out, suggesting a checkbox to enable the user to mask their entered password if they wish to do so. He also suggests that checkbox being enabled by default on sites that require high security.</p>
<p>I think the checkbox idea is really good, as long as it works in the opposite way: Password masking should <strong>always </strong>be the default and you should <strong>check</strong> the checkbox to <strong>show</strong> the characters you typed. This is in line with what Windows (Vista or newer) users are already accustomed to anyway<span id="more-351"></span>:</p>
<p><img class="alignnone size-full wp-image-356" title="Enter passphrase" src="http://leaverou.me/wp-content/uploads/2009/06/vistawirelesspasscode.png" alt="Enter passphrase" width="362" height="246" /></p>
<p>This can (and should) be done with JavaScript alone: if the user has it turned off, no problem, just a regular old password field. Of course the checkbox should also be dynamically added, to prevent users with disabled JS from viewing a checkbox that does nothing at all.</p>
<p>This seems easy at first, even without a library (although, in this particular case, a library would greatly reduce the amount of code required, so much that I&#8217;m tempted to include a jQuery version as well):</p>
<pre>window.onload = function() {
	var passwords = document.getElementsByTagName('input');
	for(var i=0; i&lt;passwords.length; i++) {
		if(passwords[i].type == 'password') {
			var password = passwords[i];

			var showCharsCheckbox = document.createElement('input');
				showCharsCheckbox.type = 'checkbox';
				showCharsCheckbox.onclick = (function(input) {
					return function() {
						input.type = this.checked? 'text' : 'password';
					};
				})(password);

			var showCharsLabel = document.createElement('label');
				showCharsLabel.appendChild(showCharsCheckbox);
				showCharsLabel.appendChild(document.createTextNode('Show characters'));

			// If the password field is inside a &lt;label&gt; element, we don't want to insert our label in there as well!
			var previousSibling = /label/i.test(password.parentNode.nodeName)? password.parentNode : password;

			// Check whether it's the last child of it's parent
			if(previousSibling.nextSibling) {
				previousSibling.parentNode.insertBefore(showCharsLabel, previousSibling.nextSibling);
			}
			else {
				previousSibling.parentNode.appendChild(showCharsLabel);
			}
		}
	}
}</pre>
<p>However, nothing is ever simple, when you also need to support our <em>beloved </em>Internet Explorer. Most moderately experienced JavaScript developers have probably already understood what I&#8217;m talking about: The all time classic IE bug (still present in IE8&#8230;) in regards to setting an &lt;input /&gt; element&#8217;s type attribute. You can only set it once, for elements that are not already in the DOM. After that, it becomes read-only, and any attempt to set it results in a &#8220;The command is not supported&#8221; error. And when I say &#8220;any&#8221; attempt I mean it:</p>
<ul>
<li>element.setAttribute()</li>
<li>element.type</li>
<li>element.setAttributeNode()</li>
<li>element.removeAttribute() and then element.setAttribute()</li>
<li>element.cloneNode(), then one of the above, then replacing the node with the clone</li>
</ul>
<p><strong>everything</strong> fails miserably.</p>
<p>I&#8217;ve encountered this problem several times in the past as well, but I could always think of an alternative way to do what I wanted without having to work around it. In this case, I don&#8217;t think there is one. So we&#8217;re left with two possible scenarios:</p>
<ul>
<li>Perform an easy test in the beginning to see whether this bug exists and proceed only if the browser isn&#8217;t naughty. This could be done with the following:
<pre>var supportsChangingTypeAttribute = (function() {
	var input = document.createElement('input');
	try {
		input.type = 'password';
		input.type = 'text';
	} catch(e) {
		return false;
	}
	return input.type == 'text';
})();

if(supportsChangingTypeAttribute) {
	// do stuff...
}</pre>
</li>
<li>Wrap the statement that IE chokes on in a try&#8230;catch construct and in the catch(e) {&#8230;} block create a new input element, copy <strong>everything</strong> (where everything is <strong>at least</strong>: attributes, properties, event handlers &#8211; both traditional ones <strong>and </strong>listeners) from the password field into it (except the type attribute of course!) and replace the original password field with it. After the first time, the text field could also be reused, to improve performance.<br />
If you have a shortage of trouble in your life, you may attempt it, I currently do not. <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  It can be a <strong>very </strong>simple task for particular cases, but a generic solution that would work in any site (or even in most sites) seems a really daunting, tedious and downright boring task. I also hope there might be a better solution, that I haven&#8217;t thought of. Any ideas?</li>
</ul>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/8wYg2CnDbds" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/06/on-password-masking-and-usability/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/06/on-password-masking-and-usability/</feedburner:origLink></item>
		<item>
		<title>Tip: Multi-step form handling</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/gjszVFkFg08/</link>
		<comments>http://leaverou.me/2009/06/tip-multi-step-form-handling/#comments</comments>
		<pubDate>Tue, 16 Jun 2009 05:02:07 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[forms]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=346</guid>
		<description><![CDATA[First of all, sorry for my long absence! I haven&#8217;t abandoned this blog, I was just really, really busy. I&#8217;m still busy, and this probably won&#8217;t change soon. However, I will still blog when I get too fed up with work or studying (this is one of these moments&#8230;). Now, let&#8217;s get to the meat. [...]]]></description>
			<content:encoded><![CDATA[
<p>First of all, sorry for my long absence! I haven&#8217;t abandoned this blog, I was just really, really busy. I&#8217;m still busy, and this probably won&#8217;t change soon. However, I will still blog when I get too fed up with work or studying (this is one of these moments&#8230;). Now, let&#8217;s get to the meat.</p>
<h3>The situation</h3>
<p>In most web applications, even the simplest ones, the need for form handling will arise. There will be forms that need to be submitted, checked, processed or returned to the user informing them about any errors. A good empirical rule I try to follow is &#8220;Try not to produce URLs that don&#8217;t have a meaning if accessed directly&#8221;. It sounds simple and common-sense, doesn&#8217;t it? However, as Francois Voltaire said, &#8220;common sense is not so common&#8221;. I&#8217;ve seen variations of the following scenario several times, in several websites or even commercial web application software:<span id="more-346"></span></p>
<p>Lets assume we have a two step process, like a registration form with an arguably¹ bad usability. The hypothetical script is called register.php (PHP is just an example here, the exact language doesn&#8217;t matter, it could be register.jsp or anything else). The user fills in the information required for the first step, and if they get it right, they advance to something like register.php?step=2 to complete the rest of the information. They fill in their information there as well, and submit the form. Everything is fine.</p>
<h3>Or is it?</h3>
<p>What we have done this way is that we have effectively created a completely useless URL. If someone tries to access register.php?step=2 directly (via their history for instance), we don&#8217;t have the POST data from the first step, so we either have to redirect them to the first step or, even worse, assume they are actually coming from the first step and present it to them full of errors telling them they got everything wrong. In both cases we have duplicate content, and in the second one, usability suffers a great deal.</p>
<p>So, the right way is to pass step=2 via POST as well. This way, the URL stays as it was (register.php) and we avoid all the problems mentioned above. So, we end up doing something like this:</p>
<pre>... form fields here ...
&lt;input type="hidden" name="step" value="2" /&gt;
&lt;input type="submit" value="Create my account" /&gt;</pre>
<h3>Now we&#8217;re done. Or not?</h3>
<p>This works fine. However, there&#8217;s still room for improvement. We could get rid of the extra input element by utilizing the submit button. Yeah, it&#8217;s a form element too, even though we often overlook that and just focus on styling it. If we give it a name, it will get sent along with the other form fields. So instead of the html above, we can do that:</p>
<pre>... form fields here ...
&lt;input type="submit" name="step" value="2" /&gt;</pre>
<h3>But wait! What the f*ck is that<br />
<input name="step" type="submit" value="2" />???</h3>
<p>Now usability suffers! Instead of our nice &#8220;Create my account&#8221; button, the user now sees a cryptic &#8220;2&#8243;. Who cares if it works or if it requires less code, if nobody understands how to register, right? Luckily for us, we don&#8217;t <strong>have </strong>to use the <code>&lt;input /&gt;</code> tag to create submit buttons. A better (in terms of styling, semantics, markup clarity etc), albeit less known, alternative exists: The <code>&lt;button /&gt;</code> tag. When using the <code>&lt;button /&gt;</code> tag, the label of the button is derived from the markup within the start and end tags (yeah, we can also have html elements in there, not only text nodes, in case you&#8217;re wondering), not from the value attribute. So, we can set it&#8217;s name and value attributes to whatever we want, and the user won&#8217;t notice a thing:</p>
<pre>... form fields here ...
&lt;button type="submit" name="step" value="2"&gt;Create my account&lt;/button&gt;</pre>
<p>It&#8217;s really simple, although not done often. I guess it&#8217;s one of these &#8220;OMG how come I&#8217;ve never thought about this??&#8221; kind of things. <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p>¹ <span style="font-size:smaller">I firmly believe we should eliminate the number of steps required in any procedure and especially in registration forms that users are bored to fill in anyway. However, there&#8217;s an exception to that: If the form <strong>has </strong>to be big for some reason, breaking it into steps actually makes it <strong>more </strong>usable, since the user is not overwhelmed with all these fields. Another situation when this approach is favorable is when the second step is determined according to the data from the first, although thanks to JavaScript and Ajax, this is becoming obsolete nowadays.</span></p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/gjszVFkFg08" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/06/tip-multi-step-form-handling/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/06/tip-multi-step-form-handling/</feedburner:origLink></item>
		<item>
		<title>9 reasons why I prefer MySQL to MS SQL Server</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/RH8n_sx2q6o/</link>
		<comments>http://leaverou.me/2009/05/9-reasons-why-i-prefer-mysql-to-ms-sql-server/#comments</comments>
		<pubDate>Sat, 16 May 2009 19:13:36 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Rants]]></category>
		<category><![CDATA[Thoughts]]></category>
		<category><![CDATA[MS SQL Server]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=334</guid>
		<description><![CDATA[In the past, I used MySQL for any of my DBMS needs. It wasn&#8217;t really an informed decision based on solid facts, actually I had never really given it any thought. It was what most developers used, it was what vBulletin used (one of the main projects of my company is based on vBulletin), it [...]]]></description>
			<content:encoded><![CDATA[
<p>In the past, I used MySQL for any of my DBMS needs. It wasn&#8217;t really an informed decision based on solid facts, actually I had never really given it any thought. It was what most developers used, it was what vBulletin used (one of the main projects of my company is based on vBulletin), it was what most hosts had pre-installed, in other words, it was the popular choice and I went with the crowd.</p>
<p>Unlike most decisions taken that way, this one turned out to be correct (so far at least). In the university where I study (yeah, I do that too occasionally <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  ), there is a great and extremely useful class on Database Systems offered in my semester. The only drawback is that it&#8217;s done on MS SQL Server. Consequently, I had to work with it quite a lot, and my conclusion was that MySQL is far superior (mostly syntax-wise as I don&#8217;t have the deep knowledge required to judge them fairly for other things, so don&#8217;t expect a deep analysis about performance or security &#8211; as far as I&#8217;m concerned, they are equally good at those).<span id="more-334"></span> Here are a few reasons:</p>
<ol>
<li>No ENUM datatype. Yeah, of course I can define a column with a char/varchar type and add a constraint to only allow for particular strings, but this kinda defeats the purpose of <a href="http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html" target="_blank">memory saving that the ENUM datatype in MySQL offers</a>.</li>
<li>No INSERT IGNORE. Instead you have to go through hell to simulate that in MS SQL Server.</li>
<li>I hate it that I can&#8217;t use &#8220;USING(columnlabel)&#8221; in a JOIN query and I have to use &#8220;ON(table1.columnlabel = table2.colmnlabel)&#8221; all the time. Yeah, I know that the first one isn&#8217;t standard, but it&#8217;s shorter, cleaner, more elegant, and &#8230;you can still use &#8220;ON(&#8230;)&#8221; if you don&#8217;t like it. Having more options is never bad, is it?</li>
<li>With MySQL you may insert multiple rows at once elegantly (&#8220;INSERT INTO tablename (&#8230;), (&#8230;), &#8230;&#8221;), without using the &#8220;INSERT INTO tablename SELECT (&#8230;) UNION ALL SELECT (&#8230;) UNION ALL &#8230;&#8221; hack. Moreover, the elegant MySQL way also <a href="http://troels.arvin.dk/db/rdbms/#insert-multiple">happens to be the standard</a>, a standard that SQL Server doesn&#8217;t follow.</li>
<li>Triggers can only run per statement, and not per row. This isn&#8217;t really important, since for most cases, it&#8217;s more efficient to define a per statement trigger anyway, but it doesn&#8217;t do any harm to have an extra option, does it?</li>
<li>Paging is dead-easy on MySQL: SELECT * FROM foo LIMIT 10,20 . With MS SQL Server you have to <a href="http://www.sqlteam.com/article/server-side-paging-using-sql-server-2005" target="_blank">jump</a> <a href="http://www.asp101.com/articles/gal/effectivepaging/default.asp" target="_blank">through</a> <a href="http://sqltips.wordpress.com/2007/08/10/optimized-solution-of-paging-by-using-count-over-functionality/" target="_blank">hoops</a> to do the same thing, especially if your query is not trivial.</li>
<li>In MySQL, when you want to convert an integer to a hex string, you just call HEX(). In SQL Server you have to call an undocumented function and do some string manipulation to do the exact same thing.</li>
<li>MySQL runs on every platform, whereas with MS SQL Server you&#8217;re stuck with Windows.</li>
<li>Last but not least, MySQL is free (and when it&#8217;s not free, it&#8217;s at least cheap) and opensource <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </li>
</ol>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/RH8n_sx2q6o" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/05/9-reasons-why-i-prefer-mysql-to-ms-sql-server/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/05/9-reasons-why-i-prefer-mysql-to-ms-sql-server/</feedburner:origLink></item>
		<item>
		<title>Creating the perfect slider</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/xsKAT7rgDTE/</link>
		<comments>http://leaverou.me/2009/04/creating-the-perfect-slider/#comments</comments>
		<pubDate>Fri, 24 Apr 2009 01:43:56 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[forms]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=321</guid>
		<description><![CDATA[I&#8217;ve previously discussed many times the color picker I have to create, and blogged about my findings on the way. An essential component of most color pickers is a slider control. I won&#8217;t go through much techincal details or JavaScript code in this article (after all the usability guidelines presented don&#8217;t only apply to JavaScript [...]]]></description>
			<content:encoded><![CDATA[
<p>I&#8217;ve previously discussed many times the color picker I have to create, and blogged about my findings on the way. An essential component of most color pickers is a slider control.</p>
<p>I won&#8217;t go through much techincal details or JavaScript code in this article (after all the usability guidelines presented don&#8217;t only apply to JavaScript applications, and this is why I used Adobe Kuler as a good or bad example for some of them), it&#8217;s been done numerous times before and I prefer being a bit original than duplicating web content. You can google it and various implementations will come up if you need a starting point.</p>
<p>Some might argue that I suffer from <a href="http://en.wikipedia.org/wiki/Not_Invented_Here" target="_blank">NIH syndrome</a>, but I prefer to code things my way when I think I can do something even<strong> a bit</strong> better. After all, if nobody ever tries to reinvent the wheel, the wheel stands no chances of improvement. In this case, I wanted to build the most usable slider ever (at least for color picking uses), or -from an arguably more conservative point of view- something significantly more usable than the rest (if you think about it, the two statements are equivalent, the first one just <em>sounds </em>more arrogant <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  ).<span id="more-321"></span></p>
<p>I started by thinking about the way I personally use sliders and other form controls, and what bothers me most in the process. Then I combined that with the previously-done accessibility guidelines and the best slider implementations I&#8217;ve encountered (from a usability perspective), and here is what I came up with.</p>
<h3>Requirements for the perfect slider control</h3>
<ol>
<li>It should be <a href="http://www.w3.org/WAI/intro/aria" target="_blank">ARIA</a>-compatible, so that disabled users can easily utilize it.</li>
<li>It should be focusable, so that you can Tab to it.</li>
<li>Of course the thumb should be draggable (why would you call it a slider otherwise anyway?)</li>
<li>Of course the slider should be labeled so that the user knows what to use it for.</li>
<li>Normal, hover and focus states should be different (at least in browsers supporting the :hover and :focus pseudo-classes)</li>
<li>You should be able to click somewhere in the rail and have the thumb <strong>instantly move there</strong>. Many slider implementations use animations for that, and even though I admit it raises the <em>wow </em>factor, I don&#8217;t think it&#8217;s good for usability. <strong>When I choose something, I want it to be instantly selected</strong>, I don&#8217;t want to wait for the pretty animation to finish, even if it&#8217;s short. Other implementations don&#8217;t move the slider to the point of the rail that you clicked, but just a bit <em>towards</em> it. I find that very annoying. <strong>I clicked there because I want the slider to go there, not <em>towards </em>there!</strong> If I wanted to increment/decrement it a bit, I&#8217;d use other methods (read below).</li>
<li>It should be keyboard-navigable. I think the ideal key-mappings are:
<ul>
<li><strong>Left and right arrow keys</strong> for small adjustments</li>
<li><strong>Page up/down</strong> and <strong>Ctrl + left and right arrow keys</strong> for big adjustments.</li>
<li><strong>Esc </strong>to focus out (blur)</li>
<li><strong>Home</strong> and <strong>End </strong>to navigate to the minimum and maximum respectively</li>
</ul>
</li>
<li>It should respond to the <strong>mousewheel </strong>(and this is where all current implementations I&#8217;ve tested fail misreably) when focused. Small adjustments for normal mousewheel movement, big adjustments if the <strong>Ctrl </strong>key is pressed as well. The pitfall to that is that you can&#8217;t cancel the default action (zoom in/out) in Safari. Why the Ctrl key and not Alt or Shift? Because we are accustomed to using the Ctrl key as a modifier. Alt and Shift are used more rarely. Especially designers (and for most color pickers they are a significant part of the target audience) are used in using the Ctrl key together with the mousewheel, since that&#8217;s a popular way for zooming or scrolling in most Adobe CS applications. Another important consideration when designing a mousewheel-aware slider, is to bind the event to the document element once the slider thumb is focused and unbind it when the slider thumb is blurred. Why? Because in most such cases, we don&#8217;t like to have to keep out mouse pointer on the slider to adjust it with the mousewheel. <strong>It being focused should suffice for letting the app know that this is what we want to adjust.</strong></li>
<li>The exact numerical choice of the user should be visible, not only in an indicator that is positioned in a static place, but also <strong>above the slider thumb and have it move as the slider thumb moves</strong>. <strong>I don&#8217;t want to have to look at two different places to see what I have selected!</strong> (the slider thumb and the indicator) Why above the slider thumb? Because if it&#8217;s below, the mouse pointer is likely to hide it. This movable indicator should be hidden once the user focuses out (as long as we provide another one that is positioned statically). <a href="http://kuler.adobe.com/#create/fromacolor" target="_blank">Adobe Kuler</a> does this fairly well, although it suffers from a few issues: When you click on the slider rail, the indicator doesn&#8217;t show up.</li>
<li>The user should be able to click at some point in the rail and start dragging right away, <strong>without lifting their mouse button in the meantime</strong>. Even though this sounds common-sense, I&#8217;ve seen <strong>many</strong> implementations that fail at it (including Kuler&#8217;s).</li>
</ol>
<p>So, that&#8217;s it! What do you think? Could you come up with anything else to add?</p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/xsKAT7rgDTE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/04/creating-the-perfect-slider/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/04/creating-the-perfect-slider/</feedburner:origLink></item>
		<item>
		<title>Cross-browser imageless linear gradients v2</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/ooDt8fKALAY/</link>
		<comments>http://leaverou.me/2009/04/cross-browser-imageless-linear-gradients-v2/#comments</comments>
		<pubDate>Fri, 24 Apr 2009 00:47:57 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Original]]></category>
		<category><![CDATA[gradient]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=316</guid>
		<description><![CDATA[A while ago, I posted a script of mine for creating 2-color cross-browser imageless linear gradients. As I stated there, I needed them for a color picker I have to create. And even though 2-color gradients are sufficient for most components, in most color spaces, I had forgotten an important one: Hue. You can&#8217;t represent [...]]]></description>
			<content:encoded><![CDATA[
<p>A while ago, I posted <a title="Cross-browser imageless linear gradients v1" href="http://leaverou.me/2009/03/cross-browser-imageless-linear-gradients/" target="_blank">a script of mine for creating 2-color cross-browser imageless linear gradients</a>. As I stated there, I needed them for a color picker I have to create. And even though 2-color gradients are sufficient for most components, in most color spaces, I had forgotten an important one: <strong>Hue</strong>. You can&#8217;t represent Hue with a 2-color gradient! So, I had to revise the script, and make it able to produce linear gradients of more than 2 colors. Furthermore, I needed to be able to specify a fully transparent color as one of the gradient colors, in order to create the photoshop-like 2d plane used by the picker (and no, a static image background like the one used in most JS color pickers wouldn&#8217;t suffice, for reasons irrelevant with this post). I hereby present you <em>Cross-browser, imageless, linear gradients <strong>v2</strong></em>!</p>
<p><span id="more-316"></span>The API has stayed just the same, with the following differences:</p>
<ul>
<li>You may specify the keyword &#8220;transparent&#8221; instead of a #RRGGBB color (that was such a pain to implement btw!).</li>
<li>When creating a Gradient object, color strings are now defined in an array. Example:
<pre>var g = new Gradient(200, 100, ['#000000', '#ff1166', '#23ff46'], true);</pre>
</li>
<li>When calling <code>g.paint()</code> it now takes <strong>2</strong> arguments instead of 3: The new color array (or null if you don&#8217;t want that to change) and the direction (true for vertical, false for horizontal). For example:
<pre>g.paint(['#000000', '#ff1166', '#23ff46'], true);</pre>
</li>
<li>2 new methods have been added: <code>g.setColorAt(index, color)</code> and <code>g.direction(newDirection)</code>. The first allows you to set a particular gradient color (index starting from 0) and the second to alter or toggle the direction (if you specify a direction parameter, you set the direction, if you call it with no parameters, it toggles from horizontal to vertical).</li>
<li>The fields <code>g.startColor</code> and <code>g.endColor</code> have been replaced by the array <code>g.colors</code>.</li>
</ul>
<p><strong>Update</strong>: <strong>v2.0.1</strong> Fixed a small bug with the &#8216;transparent&#8217; keyword that affected multi-color gradients in browsers != IE when the transparent color wasn&#8217;t first or last.</p>
<p>Enjoy:</p>
<p><a href="http://leaverou.me/scripts/gradient2/gradient.js" target="_blank">gradient.js (5.1 KB)</a></p>
<p><a href="http://leaverou.me/scripts/gradient2/gradient-min.js" target="_blank">gradient-min.js (2.7 KB)</a></p>
<p><a href="http://leaverou.me/scripts/gradient2/" target="_blank">Test page</a></p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/ooDt8fKALAY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/04/cross-browser-imageless-linear-gradients-v2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/04/cross-browser-imageless-linear-gradients-v2/</feedburner:origLink></item>
		<item>
		<title>Java pretty dates</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/Kkq2I-YbZHc/</link>
		<comments>http://leaverou.me/2009/04/java-pretty-dates/#comments</comments>
		<pubDate>Tue, 21 Apr 2009 18:05:52 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Original]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=312</guid>
		<description><![CDATA[First of all, sorry for not posting as frequently as before. I&#8217;m feverishly working on a new project with a really tight deadline and I don&#8217;t have as much time as I previously did. For reasons that are irrelevant to this post, I have to write lots of Java code. So, sorry if I disappoint [...]]]></description>
			<content:encoded><![CDATA[
<p>First of all, sorry for not posting as frequently as before. I&#8217;m feverishly working on a new project with a really tight deadline and I don&#8217;t have as much time as I previously did.</p>
<p>For reasons that are irrelevant to this post, I have to write lots of Java code. So, sorry if I disappoint my fellow readers, but this post isn&#8217;t about JavaScript or CSS, it&#8217;s about Java. I wanted to display &#8220;pretty dates&#8221; (a bit like Twitter&#8217;s, for example <em>&#8220;yesterday&#8221;</em>, <em>&#8220;5 minutes ago&#8221;</em>, <em>&#8220;last year&#8221;</em> and so on) in a few places and I couldn&#8217;t find a Java implementation, so I decided to code my own.<span id="more-312"></span></p>
<p>For anyone that might need it, here it is:</p>
<pre>import java.util.Date;

/**
 * Class for human-readable, pretty date formatting
 * @author Lea Verou
 */
public class PrettyDate
{
	private Date date;

	public PrettyDate() {
		this(new Date());
	}

	public PrettyDate(Date date) {
		this.date = date;
	}

	public String toString() {
		long	current = (new Date()).getTime(),
			timestamp = date.getTime(),
			diff = (current - timestamp)/1000;
		int	amount = 0;
		String	what = "";

		/**
		 * Second counts
		 * 3600: hour
		 * 86400: day
		 * 604800: week
		 * 2592000: month
		 * 31536000: year
		 */

		if(diff &gt; 31536000) {
			amount = (int)(diff/31536000);
			what = "year";
		}
		else if(diff &gt; 31536000) {
			amount = (int)(diff/31536000);
			what = "month";
		}
		else if(diff &gt; 604800) {
			amount = (int)(diff/604800);
			what = "week";
		}
		else if(diff &gt; 86400) {
			amount = (int)(diff/86400);
			what = "day";
		}
		else if(diff &gt; 3600) {
			amount = (int)(diff/3600);
			what = "hour";
		}
		else if(diff &gt; 60) {
			amount = (int)(diff/60);
			what = "minute";
		}
		else {
			amount = (int)diff;
			what = "second";
			if(amount &lt; 6) {
				return "Just now";
			}
		}

		if(amount == 1) {
			if(what.equals("day")) {
				return "Yesterday";
			}
			else if(what.equals("week") || what.equals("month") || what.equals("year")) {
				return "Last " + what;
			}
		}
		else {
			what += "s";
		}

		return amount + " " + what + " ago";
	}
}</pre>
<p>Hope someone finds it useful. <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/Kkq2I-YbZHc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/04/java-pretty-dates/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/04/java-pretty-dates/</feedburner:origLink></item>
		<item>
		<title>Better usability in 5 minutes</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/ScoMILSvt-4/</link>
		<comments>http://leaverou.me/2009/04/better-usability-in-5-minutes/#comments</comments>
		<pubDate>Fri, 10 Apr 2009 00:36:06 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Original]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[CSS3]]></category>
		<category><![CDATA[CSS3 selectors]]></category>
		<category><![CDATA[CSS3 transitions]]></category>
		<category><![CDATA[usability]]></category>
		<category><![CDATA[Webkit]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=296</guid>
		<description><![CDATA[In this post I&#8217;m going to share some tips to increase a site&#8217;s usability that are very quick to implement. Not all of them are cross-browser, but they are the icing on the cake anyway, nobody would mind without them. 1. Make buttons and button-like links appear pressed This is a personal favorite. When you [...]]]></description>
			<content:encoded><![CDATA[
<p>In this post I&#8217;m going to share some tips to increase a site&#8217;s usability that are very quick to implement. Not all of them are cross-browser, but they are the icing on the cake anyway, nobody would mind without them.<span id="more-296"></span></p>
<h3>1. Make buttons and button-like links appear pressed</h3>
<p>This is a personal favorite. When you use CSS to style a button, or when you use an image (either as a background image or in the &lt;img /&gt; tag) to depict a fancy button, it will remain the same when being pressed in some or all browsers (depending on the case). You can use this easy trick to let the user know that he actually clicked something that is, indeed, clickable:</p>
<pre>.mybutton:active {
	position:relative;
	top: 1px;
	left: 1px;
}</pre>
<p>which actually moves the button 1 pixel to the right and 1 pixel to the bottom when it&#8217;s being clicked. Try it, it&#8217;s actually quite convincing.</p>
<p>Other, equally quick options are: making the border inset, giving to the text a text-indent of 1px, reversing a gradient background (if you already use the reversed version somewhere else in the site, it is quick since you don&#8217;t have to use an image editor just for that), or a combination of them.</p>
<h3>2. Smooth transitions</h3>
<p>This is a webkit-only tip, but as I said, it&#8217;s just the icing on the cake, so who cares? If a smooth transition is crucial to your design, by all means, write a script for that or use a library. If you were planning to go the CSS-only way anyway, this will significantly increase the user experience for webkit users.</p>
<p>Let&#8217;s suppose that the links in your page are normally blue, and red on hover. To make the transition from blue to red smooth for webkit users, only 2 lines are needed in the CSS:</p>
<pre>a {
	color:blue;
<strong>	-webkit-transition-property: color;
	-webkit-transition-duration: 1s;</strong>
}

a:hover {
	color:red;
}</pre>
<p>The first one (<code>-webkit-transition-property</code>) tells the browser which CSS property to smoothly transition and the second one (<code>-webkit-transition-duration</code>)<strong></strong><strong> </strong>how long you want the whole effect to last. It&#8217;s important to place those in the normal CSS rule and not the one with the :hover pseudoclass, because otherwise there will be no transition when the user mouses out of the element.</p>
<h3>3. Add dingbats to buttons that depict their functionality</h3>
<p>We all know that most browsers don&#8217;t like dingbat-only fonts. However, there are some dingbats that are available in most web-safe unicode fonts. For instance, review the following examples:</p>
<h4>Without dingbats:</h4>
<p><button>Next</button><br />
<button>Previous</button><br />
<button>Done</button><br />
<button>Favorite</button></p>
<h4>With dingbats:</h4>
<p><button>Next →</button><br />
<button>← Previous</button><br />
<button>✔ Done</button><br />
<button>♥ Favorite</button></p>
<p>There are named html entities for some of them, others have to be used by their hex unicode index like &amp;#xABCD;  (you have to test the last ones a lot, since not all are web-safe enough).</p>
<p>You can find many such dingbats with their unicode hex codes in <a class="linkification-ext" title="Linkification: http://www.copypastecharacter.com/" href="http://www.copypastecharacter.com/">http://www.copypastecharacter.com/</a> and http://www.alanwood.net/unicode/dingbats.html.</p>
<p>Of course, if you have the time, by all means, use normal icons. If you don&#8217;t however, I find symbols to be a handy alternative. Sometimes I also use them as icon placeholders in work in progress until I find the time to design real icons.</p>
<h3>4. Zebra rows</h3>
<p>This won&#8217;t work on IE and Firefox 3. You can increase readability of tables and some types of lists by slightly alternating the background color of the rows. You&#8217;ve probably seen this effect numerous times and it&#8217;s usually done via JavaScript or the server side code that generates the table. You can quickly do it with plain CSS3 however, if you don&#8217;t mind it not working in IE and older browser versions or don&#8217;t have the time for a complete cross-browser solution:</p>
<pre>table.stats tr {
	background:white;
}

table.stats tr:nth-child(odd) {
	background:#f4f4f4;
}</pre>
<h3>5. Highlight the current target</h3>
<p>This won&#8217;t work in IE and older browser versions. If a particular page has lots of content, navigable by anchors (for example a FAQ page), you can use the CSS3 :target pseudo-class to let the user know where they landed:</p>
<pre>h3:target {
	background:#FFFBCC;
}</pre>
<p>The h3 will only get a #FFFBCC background when it&#8217;s actually the landing point for the user. For example, if it has the id &#8220;foo&#8221;, it will get an #FFFBCC background when the user navigates to #foo.</p>
<h3>That&#8217;s all folks</h3>
<p>Did it actually take more than 5 minutes? <img src='http://leaverou.me/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/ScoMILSvt-4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/04/better-usability-in-5-minutes/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/04/better-usability-in-5-minutes/</feedburner:origLink></item>
		<item>
		<title>Help me: take the color survey</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/1jcDlT84Ypg/</link>
		<comments>http://leaverou.me/2009/04/help-me-take-the-color-survey/#comments</comments>
		<pubDate>Mon, 06 Apr 2009 10:46:21 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[colors]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=286</guid>
		<description><![CDATA[If you are a creative professional, or just passionate about colors, please take my survey: http://bit.ly/colorsurvey It will greatly help me to make a future project of our company more usable (some of its features at least) and it only takes a few minutes (it contains 10-19 questions, depending on your responses). Any suggestions, corrections, [...]]]></description>
			<content:encoded><![CDATA[
<p>If you are a creative professional, or just passionate about colors, please take my survey:</p>
<p>http://bit.ly/colorsurvey</p>
<p>It will greatly help me to make a future project of our company more usable (some of its features at least) and it only takes a few minutes (it contains 10-19 questions, depending on your responses).</p>
<p>Any suggestions, corrections, questions etc are of course welcome.</p>
<p>Thanks a lot in advance to everyone that takes the survey! <img src='http://leaverou.me/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>Of course, when it ends and I find the time to analyze the results, I&#8217;ll post them here for anyone interested. (Hint: That means that if you are interested in the results, you can promote the survey yourself as well, since more responses = more accurate results)</p>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/1jcDlT84Ypg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/04/help-me-take-the-color-survey/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/04/help-me-take-the-color-survey/</feedburner:origLink></item>
		<item>
		<title>Advocacy of JavaScript</title>
		<link>http://feedproxy.google.com/~r/leaverou/~3/UdsyYfW2TwM/</link>
		<comments>http://leaverou.me/2009/03/advocacy-of-javascript/#comments</comments>
		<pubDate>Mon, 30 Mar 2009 02:42:39 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Rants]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=269</guid>
		<description><![CDATA[I frequently meet these &#8220;hardcore&#8221; developers that deep (or not so deep) inside them, tend to underestimate JavaScript developers and boast about their own superiority. I&#8217;m sure that if you spent an important percentage of your career working with JavaScript and are even barely social, you definitely know what I&#8217;m talking about. It&#8217;s those desktop [...]]]></description>
			<content:encoded><![CDATA[
<p>I frequently meet these &#8220;hardcore&#8221; developers that deep (or not so deep) inside them, tend to underestimate JavaScript developers and boast about their own superiority. I&#8217;m sure that if you spent an important percentage of your career working with JavaScript and are even barely social, you definitely know what I&#8217;m talking about. It&#8217;s those desktop application programmers or these back-end developers that tend to consider JavaScript a toy, and try to convince you to engage in &#8220;more serious stuff&#8221; (if they appreciate you even a little; if they don&#8217;t they just mock you endlessly and/or look down on you).</p>
<p>Funnily enough, when most of these people are required to write JavaScript for some reason, one of the following happens:</p>
<ol>
<li>They write 2000-style code, which is usually the reason that most of them underestimate JavaScript so much: They think that <strong>everybody</strong> codes in JavaScript like themselves.</li>
<li>They desperately look for &#8220;a good library&#8221; because &#8220;it&#8217;s not worth wasting my time to learn that stuff&#8221;.</li>
<li>They actually learn the darn language and the relevant browser quirks and change their attitude towards JavaScript developers.</li>
</ol>
<p><a href="http://javascript.crockford.com/javascript.html" target="_blank">Douglas Crockford did it much better than me</a>, but I would like to take my turn in arguing against their most frequent claims, if I may.<span id="more-269"></span></p>
<h3>&#8220;Javascripters are not really developers.&#8221;</h3>
<p>Oh r&#8217;ly? Is it because JavaScript doesn&#8217;t follow what you&#8217;ve learned to expect from most languages? Well, newsflash: Assembly doesn&#8217;t either and every programming language is actually an abstraction to it. It&#8217;s in fact much harder to write the same thing in a language that lacks what we&#8217;ve learned to expect. Think about low level coding: Even the simplest tasks seem hard. At a smaller extent, it&#8217;s the same with JavaScript: Things that are easy to do in other languages, are a pain in JavaScript, even if we leave out the implementation differences across browsers. For instance, in Java there is a built-in class for most common tasks. JavaScript isn&#8217;t that rich, and it penalizes you for every external library you use, by forcing your users to download extra Kilobytes of code. JavaScript is probably the only modern language in which short code isn&#8217;t only elegance, but also a necessity.</p>
<p>Also, in other languages, you only have to deal with <strong>one </strong>implementation. Even when using Java to code for multiple operating systems, the differences are minor for most applications. With JavaScript, you are dealing with at least 5 implementations with many differences and bugs to circumvent. Writing a piece of code that works in one browser is not good enough, you have to make it work across <strong>all </strong>major browsers, in <strong>all </strong>their versions that still have significant market share. And yeah, this is most of the times just as dreadful as it sounds, if not more.</p>
<p>Of course, I&#8217;m not implying that everyone who wrote a script in JavaScript is a developer, just like everyone that wrote a Hello World application in C++ is not a programmer. JavaScript is notorious for being used mostly by amateurs for the following reasons:</p>
<ol>
<li>Most people that ever wrote a webpage needed something that could only be done with JavaScript. Most of these people weren&#8217;t developers and didn&#8217;t have any interest in programming.</li>
<li>Because of (1) there are many JavaScript tutorials and books around for accomplishing simple tasks, most of them being leftovers from the 2000 era and promote bad code practices. During that era, people didn&#8217;t care about nice code, usability, accessibility and cross-browser functionality. They just wanted to get the job done spending the least possible time and they only cared if it worked in Internet Explorer.</li>
<li>Most people just copy and paste stuff from the tutorials mentioned in (2), leading to duplicate functionality, bad code, bad usability, complete absence of accessibility and buggy results in browsers other than the target one. This caused JavaScript to be related to these vices although these things were actually caused by abusing the language.</li>
</ol>
<h3>&#8220;Javascript is a toy, not a real programming language&#8221;</h3>
<p>It may have been a toy in the 2000 era where your mind is still stuck. Currently, browser vendors are constantly adding new features to it, in order to make it able to compete with a fully-fledged programming language and competent front-end developers have been pushing JavaScript to an extent that was unimaginable when it was first introduced. If you are not convinced, pay a visit to <a href="http://www.chromeexperiments.com/" target="_blank">Chrome Experiments</a> (as the name suggests, you are advised to use Google Chrome when viewing them).</p>
<p><strong>JavaScript is not a light version of Java, nor is it a light version of any programming language. </strong>It has a soul of it&#8217;s own, so stop comparing it to other languages and pointing out the areas where it lacks. Open your eyes instead to see the areas where it&#8217;s superior to all other languages you probably know (<a href="http://www.hunlock.com/blogs/Functional_Javascript" target="_blank">lambda</a> for instance).</p>
<h3>&#8220;How can I respect a language that only lives inside a browser?&#8221;</h3>
<p>Newsflash: You are wrong, <strong>again</strong>. You can code in JavaScript <a href="http://en.wikipedia.org/wiki/Server-side_JavaScript" target="_blank">for the server</a>, <a href="http://www.phpied.com/make-your-javascript-a-windows-exe/" target="_blank">create Windows executable files (.exe)</a>, create  plugins and extensions for a plethora of applications, and actually even Flash&#8217;s ActionScript is based on ECMAScript, a standard that was derived from and currently controls JavaScript implementations.</p>
<h3>Disclaimers</h3>
<p>Ah, these are always necessary in rants <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<ol>
<li><strong>I didn&#8217;t have any particular individual in mind when writing this post, so if you think it&#8217;s about you, get over it. </strong>My memory is too bad to do so anyway. <img src='http://leaverou.me/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </li>
<li>I am not implying that JavaScript is the best programming language around. I actually don&#8217;t think there is such a language. My point was that JavaScript is not inferior to the others. That doesn&#8217;t mean I consider it superior either.</li>
<li>I don&#8217;t claim to be a programming guru (anyone who does so is usually ignorant anyway), nor do I claim to be always right. Feel free to argue, if you have thought a valid counterargument. <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </li>
</ol>

<img src="http://feeds.feedburner.com/~r/leaverou/~4/UdsyYfW2TwM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/03/advocacy-of-javascript/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://leaverou.me/2009/03/advocacy-of-javascript/</feedburner:origLink></item>
	</channel>
</rss>
