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

<channel>
	<title>Lea Verou &#187; Articles</title>
	<atom:link href="http://leaverou.me/category/articles/feed/" rel="self" type="application/rss+xml" />
	<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>
		<item>
		<title>Organizing a university course on modern Web development</title>
		<link>http://leaverou.me/2010/07/organizing-a-university-course-on-modern-web-development/</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[
<div class="topsy_widget_data topsy_theme_mustard" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fleaverou.me%252F2010%252F07%252Forganizing-a-university-course-on-modern-web-development%252F%22%2C%20%22shorturl%22%3A%20%22http%3A%2F%2Fbit.ly%2F9j5Bz7%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22Organizing%20a%20university%20course%20on%20modern%20Web%20development%22%20%7D);"></div>
<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>

]]></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>
		</item>
		<item>
		<title>On CSS counters plus a CSS3 Reversi UI</title>
		<link>http://leaverou.me/2010/04/on-css-counters-plus-a-css3-reversi-ui/</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[
<div class="topsy_widget_data topsy_theme_mustard" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fleaverou.me%252F2010%252F04%252Fon-css-counters-plus-a-css3-reversi-ui%252F%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22On%20CSS%20counters%20plus%20a%20CSS3%20Reversi%20UI%22%20%7D);"></div>
<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>

]]></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>
		</item>
		<item>
		<title>Exploring browser-supported Unicode characters and a tweet shortening experiment</title>
		<link>http://leaverou.me/2009/11/exploring-browser-supported-unicode-characters-and-a-tweet-shortening-experiment/</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[
<div class="topsy_widget_data topsy_theme_mustard" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fleaverou.me%252F2009%252F11%252Fexploring-browser-supported-unicode-characters-and-a-tweet-shortening-experiment%252F%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22Exploring%20browser-supported%20Unicode%20characters%20and%20a%20tweet%20shortening%20experiment%22%20%7D);"></div>
<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>

]]></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>
		</item>
		<item>
		<title>Exploring CSS3 text-shadow</title>
		<link>http://leaverou.me/2009/09/css-text-shadow/</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[
<div class="topsy_widget_data topsy_theme_mustard" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fleaverou.me%252F2009%252F09%252Fcss-text-shadow%252F%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22Exploring%20CSS3%20text-shadow%22%20%7D);"></div>
<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>

]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/09/css-text-shadow/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>On password masking and usability</title>
		<link>http://leaverou.me/2009/06/on-password-masking-and-usability/</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[
<div class="topsy_widget_data topsy_theme_mustard" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fleaverou.me%252F2009%252F06%252Fon-password-masking-and-usability%252F%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22On%20password%20masking%20and%20usability%22%20%7D);"></div>
<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>

]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/06/on-password-masking-and-usability/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Tip: Multi-step form handling</title>
		<link>http://leaverou.me/2009/06/tip-multi-step-form-handling/</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[
<div class="topsy_widget_data topsy_theme_mustard" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fleaverou.me%252F2009%252F06%252Ftip-multi-step-form-handling%252F%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22Tip%3A%20Multi-step%20form%20handling%22%20%7D);"></div>
<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>

]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/06/tip-multi-step-form-handling/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Creating the perfect slider</title>
		<link>http://leaverou.me/2009/04/creating-the-perfect-slider/</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[
<div class="topsy_widget_data topsy_theme_mustard" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fleaverou.me%252F2009%252F04%252Fcreating-the-perfect-slider%252F%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22Creating%20the%20perfect%20slider%22%20%7D);"></div>
<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>

]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/04/creating-the-perfect-slider/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Better usability in 5 minutes</title>
		<link>http://leaverou.me/2009/04/better-usability-in-5-minutes/</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[
<div class="topsy_widget_data topsy_theme_mustard" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fleaverou.me%252F2009%252F04%252Fbetter-usability-in-5-minutes%252F%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22Better%20usability%20in%205%20minutes%22%20%7D);"></div>
<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>

]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/04/better-usability-in-5-minutes/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>On native, single-input, multiple file uploads</title>
		<link>http://leaverou.me/2009/03/regarding-native-single-input-multiple-file-uploads/</link>
		<comments>http://leaverou.me/2009/03/regarding-native-single-input-multiple-file-uploads/#comments</comments>
		<pubDate>Sat, 07 Mar 2009 22:57:28 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[browsers]]></category>
		<category><![CDATA[feature detection]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Webkit]]></category>
		<category><![CDATA[Webkit bugs]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=209</guid>
		<description><![CDATA[If you are following the current news on web development, you probably heard that the new Safari 4 has a great feature: It natively allows the user to select multiple files via a single input control, if you specify a value for the attribute multiple: &#60;input type="file" multiple&#62; or, in XHTML: &#60;input type="file" multiple="multiple" /&#62; [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_mustard" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fleaverou.me%252F2009%252F03%252Fregarding-native-single-input-multiple-file-uploads%252F%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22On%20native%2C%20single-input%2C%20multiple%20file%20uploads%22%20%7D);"></div>
<p>If you are following the current news on web development, you probably heard that the new Safari 4 has a great feature: It natively allows the user to select multiple files via a single input control, if you specify a value for the attribute <code>multiple</code>:</p>
<pre>&lt;input type="file" multiple&gt;</pre>
<p>or, in XHTML:</p>
<pre>&lt;input type="file" multiple="multiple" /&gt;</pre>
<p>You might not know that <a href="http://ajaxian.com/archives/input-typefile-multiple-now-in-a-real-browser#comment-271852" target="_blank">Opera supported multiple file uploads for a while now, based on the earlier Web Forms 2.0 standard</a> in a slightly different (and more flexible) format:</p>
<pre>&lt;input type="file" min="1" max="9999″ /&gt;</pre>
<p><span id="more-209"></span></p>
<h3>Can we use those currently?</h3>
<p>Sure we can, but we should provide fallbacks for the other browsers. Using these features will put pressure on the other browser vendors to implement them as well and generally, native is always better.</p>
<h3>How can we find out whether the browser supports them?</h3>
<h4>Opera</h4>
<p>Opera supports accessing those <code>min</code> and <code>max</code> properties as properties of the element. So, it&#8217;s quite trivial to check whether Opera-style multiple inputs are supported:</p>
<pre>var supportsMin = (function(){
	var fi = document.createElement('input');
	fi.type = 'file';
	return fi.min === '' &amp;&amp; fi.max === '';
})();</pre>
<h4>Safari 4</h4>
<p>In Safari 4 the check would be equally simple, if it supported accessing the <code>multiple</code> attribute as a property. Then we could easily check whether it&#8217;s boolean and conclude that Safari-style multiple inputs are supported:</p>
<pre>var supportsMultiple = (function(){
	var fi = document.createElement('input');
	fi.type = 'file';
	// The second check is probably redundant but what if in the future an implementor
	// decides to make the file inputs to handle multiple selections by default?
	// Yeah, it's not likely, but it's not entirely impossible.
	return fi.multiple === false || fi.multiple === true;
})();</pre>
<p>However, that&#8217;s currently not the case. The good news are that <a href="https://bugs.webkit.org/show_bug.cgi?id=24444" target="_blank">I reported this as a bug today, and the Webkit team fixed it</a>, so it will be possible in the next Webkit nightly!</p>
<h4>Combining the two</h4>
<p>You can easily combine these two together with the workaround you prefer:</p>
<pre>// Create a file input that allows multiple file selection
var fi = document.createElement('input');
fi.type = 'file';

if(fi.multiple === false || fi.multiple === true) {
	fi.multiple = true;
}
else if(fi.min === '' &amp;&amp; fi.max === '') {
	fi.min = 1;
	fi.max = 9999;
}
else {
	// Our preferred workaround here
}</pre>
<h3>What about Mozilla?</h3>
<p>Ok, we all know that IE will probably take years to implement similar functionality. But usually, the Mozilla team implements new and exciting stuff quite fast.</p>
<p>As it turns out, <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=63687">there is a relevant ticket sitting in their Bugzilla</a> for a while now. If you want them to implement it, vote for it so that it&#8217;s priority increases.</p>
<p>If they do implement it in the way suggested, the code posted above will work for that too, without any changes &#8211; The advantages of feature detection baby! <img src='http://leaverou.me/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>

]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/03/regarding-native-single-input-multiple-file-uploads/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>&#8220;Appearances can be deceiving Mr. Anderson&#8221; &#8211; a.k.a. short code is not always fast code</title>
		<link>http://leaverou.me/2009/02/appearances-can-be-deceiving-mr-anderson-aka-short-code-is-not-always-fast-code/</link>
		<comments>http://leaverou.me/2009/02/appearances-can-be-deceiving-mr-anderson-aka-short-code-is-not-always-fast-code/#comments</comments>
		<pubDate>Wed, 25 Feb 2009 01:12:11 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Benchmarks]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[type checks]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=182</guid>
		<description><![CDATA[I used to take pride in my short, bulletproof and elegant String and Number type checks: // Check whether obj is a Number obj + 0 === obj // Check whether obj is a String obj + '' === obj I always thought that apart from being short and elegant, they should be faster. However, [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_mustard" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fleaverou.me%252F2009%252F02%252Fappearances-can-be-deceiving-mr-anderson-aka-short-code-is-not-always-fast-code%252F%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22%5C%22Appearances%20can%20be%20deceiving%20Mr.%20Anderson%5C%22%20-%20a.k.a.%20short%20code%20is%20not%20always%20fast%20code%22%20%7D);"></div>
<p>I used to take pride in my short, bulletproof and elegant String and Number type checks:</p>
<pre>// Check whether obj is a Number
obj + 0 === obj

// Check whether obj is a String
obj + '' === obj</pre>
<p>I always thought that apart from being short and elegant, they <strong>should </strong>be faster.</p>
<p>However, some quick tests gave me a cold slap in the face and proved my assertion to be entirely false. <span id="more-182"></span>When comparing the following 4 methods for string and number type checking:</p>
<ol>
<li>&#8220;My&#8221; method (mentioned above)</li>
<li>Object.prototype.toString method: <code>Object.prototype.toString.call(obj) === '[object String]'</code> or  <code>Object.prototype.toString.call(obj) === '[object Number]'</code></li>
<li>Typeof method: <code>typeof obj === 'string'</code> or <code>typeof obj === 'number'</code></li>
<li>Contructor method: <code>obj.constructor === String</code> or <code>obj.constructor === Number</code></li>
</ol>
<p>It turned out that the Object.prototype.toString method was <strong>50%</strong> faster than my method, and both typeof and constructor methods were a whopping <strong>150%</strong> faster than my method! No wonder <a href="http://docs.jquery.com/JQuery_Core_Style_Guidelines" target="_blank">jQuery uses the typeof method for their String/Number tests</a>.</p>
<p>Now that I think about it, it does actually make sense &#8211; my method converts <code>obj</code> to a String or Number, then concatenates/adds it with another String/Number, then compares value and type. Too much stuff done there to be fast. But I guess I was too innocent and subconsciously thought that it wouldn&#8217;t be fair if elegant and short code wasn&#8217;t fast too.</p>
<p>Of course the overall time needed for any of these tests was neglible, but it&#8217;s a good example of how much appearances can be deceiving &#8211; even in programming! <img src='http://leaverou.me/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>The moral: Never assume. Always test.</p>
<h3>So, which method is ideal for String/Number checks? (added afterwards)</h3>
<p>The typeof method and my method fail for non-primitive String/Number objects, as you can easily observe if you type in the console:</p>
<pre>typeof new String('foo') // 'object'
typeof new Number(5) // 'object'
new String('foo') + '' === new String('foo') // false</pre>
<p>This can easily be solved if you also check the type via instanceof (the decrease in speed is negligible):</p>
<pre>foo = new String('foo');
typeof foo === 'string' || foo instanceof String
foo + '' === foo || foo instanceof String</pre>
<p>Don&#8217;t use instanceof alone, since it fails for String and Number primitives. The instanceof method also fails for Strings and Numbers created in another window, since their constructor there is different. Same happens with the Constructor method mentioned above.</p>
<p>It seems that if you need a <strong>bulletproof </strong>check the only method you can use is the Object.prototype.toString method and luckily, it&#8217;s one of the fastest (not the fastest one though), so I guess we can safely elect it as the ideal method for String and Number checks (and not only for arrays, as it was first made popular for).</p>
<p><span style="font-size:smaller">PS: For anyone wondering what the quote in the title reminds him/her, its from the <em>Matrix Revolutions</em> movie.</span></p>

]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/02/appearances-can-be-deceiving-mr-anderson-aka-short-code-is-not-always-fast-code/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>20 things you should know when not using a JS library</title>
		<link>http://leaverou.me/2009/02/20things-you-should-know-when-not-using-a-js-library/</link>
		<comments>http://leaverou.me/2009/02/20things-you-should-know-when-not-using-a-js-library/#comments</comments>
		<pubDate>Sun, 22 Feb 2009 01:23:18 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[browsers]]></category>
		<category><![CDATA[feature detection]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[JavaScript libraries]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=119</guid>
		<description><![CDATA[You might just dislike JavaScript libraries and the trend around them, or the project you&#8217;re currently working on might be too small for a JavaScript library. In both cases, I understand, and after all, who am I to judge you? I don&#8217;t use a library myself either (at least not one that you could&#8217;ve heard [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_mustard" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fleaverou.me%252F2009%252F02%252F20things-you-should-know-when-not-using-a-js-library%252F%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%2220%20things%20you%20should%20know%20when%20not%20using%20a%20JS%20library%22%20%7D);"></div>
<p>You might just dislike JavaScript libraries and the trend around them, or the project you&#8217;re currently working on might be too small for a JavaScript library. In both cases, I understand, and after all, who am I to judge you? I don&#8217;t use a library myself either (at least not one that you could&#8217;ve heard about  <img src='http://leaverou.me/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ), even though I admire the ingenuity and code quality of some.</p>
<p>However, when you take such a brave decision, it&#8217;s up to you to take care of those problems that JavaScript libraries carefully hide from your way. A JavaScript library&#8217;s purpose isn&#8217;t only to provide shortcuts to tedious tasks and allow you to easily add cool animations and Ajax functionality as many people (even library users) seem to think. Of course these are things that they are bound to offer if they want to succeed, but not the only ones. JavaScript libraries also have to workaround browser differences and bugs and this is the toughest part, since they have to constantly keep up with browser releases and their respective bugs and judge which ones are common enough to deserve workaround and which ones are so rare that would bloat the library without being worth it. Sometimes I think that nowadays, how good of a JavaScript developer you are doesn&#8217;t really depend on how well you know the language, but rather on how many browser bugs you&#8217;ve heard/read/know/found out. <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<p>The purpose of this post is to let you know about the browser bugs and incompatibilities that you are most likely to face when deciding againist the use of a JavaScript library. Knowledge is power, and only if you know about them beforehand you can workaround them without spending countless debugging hours wondering &#8220;WHAT THE&#8230;&#8221;. And even if you do use a JavaScript library, you will learn to appreciate the hard work that has been put in it even more.<span id="more-119"></span></p>
<p>Some of the things mentioned below might seem elementary to many of you. However, I wanted this article to be fairly complete and contain as many common problems as possible, without making assumptions about the knowledge of my readers (as someone said, &#8220;assumption is the mother of all fuck-ups&#8221; <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  ). After all, it does no harm if you read something that you already know, but it does if you remain ignorant about something you ought to know. I hope that even the most experienced among you, will find at least one thing they didn&#8217;t know very well or had misunderstood (unless I&#8217;m honoured to have library authors reading this blog, which in that case, you probably know all the facts mentioned below <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  ) . If you think that something is missing from the list, feel free to suggest it in the comments, but have in mind that I conciously omitted many things because I didn&#8217;t consider them common enough.</p>
<h3>DOM</h3>
<ol>
<li><code>getElementById('foo')</code> also returns elements with <code>name="foo"</code> in IE and older versions of Opera.</li>
<li><code>getElementsByTagName('*')</code> returns <strong>no </strong>elements in IE5.5 and also returns comment nodes in all versions of IE (In case you&#8217;re wondering: <code>DOCTYPE</code> declaration will count, Conditional comments will not).</li>
<li><code>getElementsByClassName()</code> in Opera (even Opera 10 Alpha) doesn&#8217;t match elements with 2 or more classes when the one you&#8217;re looking for is not the first but it&#8217;s also a substring of the first. Read the discussion between me and John Resig on the latter&#8217;s blog post mentioned below if this seems a bit unclear.</li>
<li><a href="http://www.quirksmode.org/dom/w3c_core.html#t71">There is no <code>element.children</code> collection in Firefox 3-</a>. You have to create it yourself by filtering the <code>childNodes</code> collection if it doesn&#8217;t exist.</li>
<li>If your code involves preformatted elements (for instance if you are making a syntax highlighter), beware when setting the <code>innerHTML</code> of those: <a href="http://www.quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html" target="_blank">IE won&#8217;t preserve line breaks (<code>\r\n</code> s) and whitespace</a>. You have to use <code>outerHTML</code>, which will actually replace the element so you should find a way to obtain a reference to the newly created one in case you still need to perform stuff on it.</li>
<li>To get the dimensions of the viewport, <a href="http://www.quirksmode.org/dom/w3c_cssom.html#t00" target="_blank">standard compliant browsers use <code>window.innerWidth</code> (and <code>innerHeight</code>)</a> whereas IE uses <code>document.documentElement.clientWidth</code> (and <code>clientHeight</code>).</li>
<li>To get the scroll offsets of the current page, <a href="http://www.quirksmode.org/dom/w3c_cssom.html#t02" target="_blank">standard compliant browsers use <code>window.pageXOffset</code> (and <code>pageYOffset</code>)</a> whereas IE uses <code>document.documentElement.scrollTop</code> (and <code>scrollLeft</code>).</li>
<li>To make matters worse, in both cases above, you need to use <code>document.body</code> instead of <code>document.documentElement</code> when in Quirks mode.</li>
</ol>
<p>John Resig (of the jQuery fame), recently <a href="http://ejohn.org/blog/the-dom-is-a-mess/">posted a great presentation</a>, which summarized some browser bugs related to DOM functions. A few of the bugs/inconsistencies mentioned above are derived from that presentation.</p>
<h3>Events</h3>
<ol>
<li>When using IE&#8217;s <code>attachEvent()</code> the <code>this</code> reference inside the callback refers to the useless <code>window</code> object</li>
<li><code>eventObject.target</code> is <code>eventObject.srcElement</code> in IE</li>
<li><code>eventObject.stopPropagation()</code> is <code>eventObject.cancelBubble = true;</code> in IE</li>
<li><code>eventObject.preventDefault()</code> is <code>eventObject.returnValue = false;</code> in IE</li>
<li>There are many more event object incompatibilities for specific events (the ones above are for <strong>all </strong>events). Take a trip to <a href="http://www.quirksmode.org/dom/w3c_events.html">QuirksMode</a> for more information.</li>
<li>IE leaks horribly (especially IE6) in <a href="http://msdn.microsoft.com/en-us/library/bb250448.aspx">various cases</a>.</li>
<li>If you register the same event handler X times, IE fires it X times.</li>
<li>Determining when the DOM is ready is <strong>a complete mess</strong>. Firefox and Opera 9+ support the <code>DOMContentLoaded</code> event, Safari doesn&#8217;t but <a href="http://peter.michaux.ca/articles/the-window-onload-problem-still#webkitAndDocumentReadyState" target="_blank">you can check it&#8217;s <code>document.readyState</code> property</a> and <a href="http://peter.michaux.ca/articles/the-window-onload-problem-still#InternetExplorerAndDocumentReadyState" target="_blank">in IE <code>document.readyState</code> is unreliable</a> and you should either <a href="http://peter.michaux.ca/articles/the-window-onload-problem-still#InternetExplorerAndDefer" target="_blank">inject a deferred script</a>, either <a href="http://javascript.nwbox.com/IEContentLoaded/" target="_blank">poll the DOM untill there are no errors</a> or <a href="http://dean.edwards.name/weblog/2005/09/busted2/" target="_blank">use an external behavior file</a>. Of course you could always just put <a href="http://peter.michaux.ca/articles/the-window-onload-problem-still#bottomScript" target="_blank">a <code>script</code> tag at the bottom of the page, just before the <code>body</code> closing tag, which will fire all attached handlers</a> which is actually the best approach in terms of which way fires earliest (but not too early) according to my tests, but that hardly qualifies as unobtrusive&#8230;</li>
<li><strong>(edit, thanks Sobral!)</strong> The Event object is not passed as a parameter to the callback but resides in <code>window.event</code> in older versions of IE</li>
</ol>
<h3>Type detection</h3>
<ol>
<li>The <code>typeof</code> operator is almost useless:
<ul>
<li><code>typeof null == 'object'</code></li>
<li><code>typeof new String('foo') == 'object'</code></li>
<li><code>typeof [] == 'object'</code></li>
</ul>
<p><a href="http://thinkweb2.com/projects/prototype/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/" target="_blank">Use Object.prototype.toString instead</a>.</li>
</ol>
<h3>CSS</h3>
<ol>
<li>Although most CSS properties are converted to their JavaScript equivalents in a standard way (characters after dashes are Uppercase, others are lowercase, the dashes get removed), float is an exception: It&#8217;s converted to cssFloat in most browsers and styleFloat in IE. Check <a href="http://leaverou.me/2009/02/check-if-a-css-property-is-supported/">which one exists</a> and use that.</li>
<li>Getting the current (computed) style of an element is another<strong> complete mess</strong>. IE uses <code>element.currentStyle[propertyJS]</code> whereas standard compliant browsers use <code>document.defaultView.getComputedStyle(element, null).getPropertyValue(propertyCSS)</code>. And as if this wasn&#8217;t enough, there are various problems associated with specific properties or browsers, like:
<ul>
<li>IE returns the cascaded values and not the computed ones (for instance, it might return <code>em</code>s for a property that was specified in <code>em</code>s, and not pixels). <a href="http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291" target="_blank">Dean Edwards has thought a very clever hack to workaround this</a> and didn&#8217;t even blog about it (it&#8217;s simply a comment in a blog post of Erik Arvidsson&#8217;s!).</li>
<li>Any hidden (via <code>display:none;</code>) element, yields a <code>width</code>/<code>height</code>/<code>top</code>/<code>right</code>/<code>bottom</code>/<code>left</code> value of zero.</li>
<li><code>auto</code> or <code>normal</code> might be returned for properties that are left at their defaults. For instance, IE does this with <code>width</code>/<code>height</code> for elements that don&#8217;t have dimensions explicitly set via CSS.</li>
<li>In most browsers, shorthands (like <code>border</code>) will yield a blank string. You&#8217;d have to use the most specific property (for instance, <code>border-left-width</code>).</li>
<li>Colors will be returned in different formats across browsers. For instance, IE uses <code>#RRGGBB</code> whereas Mozilla uses <code>rgb(red, green, blue)</code>.</li>
</ul>
</li>
</ol>
<h3>So, what now?</h3>
<p>Never, EVER use a browser detect to solve the problems mentioned above. They can <strong>all</strong> be solved with feature/object detection, simple one-time tests or defensive coding. I have done it myself (and so did most libraries nowadays I think) so I know it&#8217;s possible. I will not post all of these solutions to avoid bloating this post even more. You can ask me about particular ones in the comments, or read the uncompressed source code of any library that advertises itself as &#8220;not using browser detects&#8221;. JavaScript Libraries are a much more interesting read than literature anyway. <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>
<h3>Are the facts mentioned above actually 20?</h3>
<p>I&#8217;m not really sure to be honest, it depends on how you count them. I thought that if I put a nice round number in the title, it would be more catchy <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>

]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/02/20things-you-should-know-when-not-using-a-js-library/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Bulletproof, cross-browser RGBA backgrounds, today</title>
		<link>http://leaverou.me/2009/02/bulletproof-cross-browser-rgba-backgrounds/</link>
		<comments>http://leaverou.me/2009/02/bulletproof-cross-browser-rgba-backgrounds/#comments</comments>
		<pubDate>Sun, 15 Feb 2009 16:38:50 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Original]]></category>
		<category><![CDATA[colors]]></category>
		<category><![CDATA[CSS3]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[RGBA]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=70</guid>
		<description><![CDATA[UPDATE: There is a new version, here First of all, happy Valentine&#8217;s day for yersterday. This is the second part of my &#8220;Using CSS3 today&#8221; series. This article discusses current RGBA browser support and ways to use RGBA backgrounds in non-supporting browsers. Bonus gift: A PHP script of mine that creates fallback 1-pixel images on [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_mustard" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fleaverou.me%252F2009%252F02%252Fbulletproof-cross-browser-rgba-backgrounds%252F%22%2C%20%22shorturl%22%3A%20%22http%3A%2F%2Fbit.ly%2Fcng9HM%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22Bulletproof%2C%20cross-browser%20RGBA%20backgrounds%2C%20today%22%20%7D);"></div>
<p><strong>UPDATE:</strong> There is a new version, <a href="http://leaverou.me/2009/10/new-version-of-rgba-php-is-out/">here</a></p>
<p>First of all, happy Valentine&#8217;s day for yersterday. <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  This is the second part of my &#8220;<a href="http://leaverou.me/2009/02/css3-border-radius-today/" target="_blank">Using CSS3 today</a>&#8221; series. This article discusses current RGBA browser support and ways to use RGBA backgrounds in non-supporting browsers. Bonus gift: A PHP script of mine that creates fallback 1-pixel images on the fly that allow you to easily utilize RGBA backgrounds in any browser that can support png transparency. In addition, the images created are forced to be cached by the client and they are saved on the server&#8217;s hard drive for higher performance.<span id="more-70"></span></p>
<h3>Browsers that currently support RGBA</h3>
<p>These are:</p>
<ul>
<li>Firefox 3+</li>
<li>Safari 2+</li>
<li>Opera 10 (still in beta)</li>
<li>Google Chrome</li>
</ul>
<p>In these browsers you can write CSS declarations like:</p>
<pre>background: rgba(255,200,35,0.5) url(somebackground.png) repeat-x 0 50%;
border: 1px solid rgba(0,0,0,0.3);
color: rgba(255,255,255,0.8);</pre>
<p>And they will work flawlessly.</p>
<h3>Internet Explorer</h3>
<p>Surprisingly, it seems that <a href="http://www.hedgerwow.com/360/dhtml/rgba/demo.php">Internet Explorer supported RGBA backgrounds long before the others</a>. Of course, with it&#8217;s <a href="http://msdn.microsoft.com/en-us/library/ms532997.aspx">very own properietary syntax</a>, as usual:</p>
<pre>filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#550000FF, endColorstr=#550000FF);</pre>
<p>And since nothing is ever simple with IE, IE8 <a href="http://blogs.msdn.com/ie/archive/2008/09/08/microsoft-css-vendor-extensions.aspx">requires a special syntax which has to be put before the first one</a> to work properly in IE8 beta1:</p>
<pre>-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#550000FF, endColorstr=#550000FF)";</pre>
<p>The code above actually draws a gradient from <code>rgba(0,0,255,0.33)</code> to <code>rgba(0,0,255,0.33)</code> using a Microsoft-proprietary &#8220;extended&#8221; hex format that places the Alpha parameter first (instead of last) and in the range of 00-FF (instead of 0-1). The rest is a usual hex color, in that case #0000FF.</p>
<p><strong>Caution: </strong>The &#8220;gradients&#8221; that are created via the gradient filter are placed <strong>on top</strong> of any backgrounds currently in effect. So, if you want to have a background image as well, the result may not be what you expected. If you provide a solid color as a background, it will also not work as expected (no alpha transparency), since the gradients created are not exactly backgrounds, they are just layers <strong>on top</strong> of backgrounds.</p>
<h3 id="filter-issues">Problems with the filter method</h3>
<ul>
<li>Filters are bad for client-side performance.</li>
<li>Filters cause the text rendering to be aliased and especially when it&#8217;s bold and there is no background-color set it becomes completely unreadable. (the worst disadvantage if you ask me)</li>
<li>Filters only work with IE. What about Firefox 2- and Opera 9.6-?</li>
<li>Filters are lengthy (especially now that you have to include 2 different syntaxes) so they significantly increase the size of your CSS when used frequently.</li>
<li>You have to convert the red, green and blue values to hex to use that method.</li>
<li>To use a filter, the element has to <a href="http://haslayout.net/" target="_blank">have Layout</a>. This is usually done via zoom:1. More non-standard clutter in your CSS.</li>
<li>Doesn&#8217;t play along well with other workarounds, since it doesn&#8217;t modify the background of the element.</li>
</ul>
<p>So, personally, I only use that approach sparingly, in particular, only when &#8220;no/minimum external files&#8221; is a big requirement.</p>
<h3>A bulletproof solution</h3>
<p>My favored approach is to use rgba() for all RGBA-capable browsers and fallback pngs for the ones that don&#8217;t support RGBA. However, creating the pngs in Photoshop, or a similar program and then uploading them is too much of a fuss for me to bare (I get bored easily <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  ). So, I created a small PHP script that:</p>
<ul>
<li>Creates a 1-pixel png image with the parameters passed for red, green, blue and alpha. No need to convert to hex.</li>
<li>Supports named colors, to speed up typing even more for colors that you use commonly in a site (it includes white and black by default, but you may easily add as many as you like).</li>
<li>Stores the generated images on the server, so that they don&#8217;t have to be created every time (generating images on the fly has quite an important performance impact).</li>
<li>Forces the images to be cached on the browser so that they don&#8217;t have to be generated every time (even though their size is very small, about 73 bytes).</li>
</ul>
<p>Here it is: <a href="http://leaverou.me/wp-content/uploads/2009/02/rgba.zip">rgba.php</a></p>
<p>You use it like this:</p>
<pre>background: url(rgba.php?r=255&amp;g=100&amp;b=0&amp;a=50) repeat;
background: rgba(255,100,0,0.5);</pre>
<p>or, for named colors:</p>
<pre>background: url(rgba.php?name=white&amp;a=50) repeat;
background: rgba(255,255,255,0.5);</pre>
<p>Browsers that are RGBA-aware will follow the second background declaration and will not even try to fetch the png. Browsers that are RGBA-incapable will ignore the second declaration, since they don&#8217;t understand it, and stick with the first one. <strong>Don&#8217;t change the order of the declarations: The png one goes first, the rgba() one goes second.</strong> If you put the png one second, it will always be applied, even if the browser <strong>does </strong>support rgba.</p>
<p>Before you use it, open it with an editor to specify the directory you want it to use to store the created pngs (the default is <code>'colors/'</code>) and add any color names you want to be able to easily address (the defaults are white and black). If the directory you specify does not exist or isn&#8217;t writeable you&#8217;ll get an error.</p>
<p><strong>Caution: </strong>You have to enter the alpha value in a scale of 0 to 100, and not from 0 to 1 as in the CSS. This is because you have to urlencode dots to transfer them via a URI and it would complicate things for anyone who used this.</p>
<p><strong>Edit: </strong>It seems that IE8 sometimes doesn&#8217;t cache the image produced. I should investigate this further.</p>
<p><strong><span style="color: #ff0000;">IMPORTANT:</span> If your PHP version is below 5.1.2 perform <a href="http://leaverou.me/2009/02/bulletproof-cross-browser-rgba-backgrounds/#comment-101">this change</a> in the PHP file or it won&#8217;t work.</strong></p>
<h3>Why not data:// URIs?</h3>
<p>Of course, you could combine the IE gradient filter, rgba() and <code>data://</code> URIs for <a href="http://www.webdevelopedia.com/better_opacity.html">a cross-browser solution that does not depend on external files</a>. However, this approach has some disadvantages:</p>
<ul>
<li>All the <a href="#filter-issues">disadvantages of filters mentioned above</a>.</li>
<li>You can&#8217;t be spontaneous in your CSS and changes are difficult. Every time you want to use RGBA, you have to resort to some converter to create the png and it&#8217;s <code>data://</code> URI. Unless you are some kind of a cyborg with an embedded base64 encoder/decoder in your head <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </li>
<li>Larger filesize (you have to use 4-5 declarations (the rgba() one, the <code>data://</code> one, 2 filters, one for IE7- and one for IE8 and a <code>zoom:1;</code> to give the element &#8220;layout&#8221; so that filters can be applied) instead of 2, and the data:// URI has the same size as the png). Also, the <code>data://</code> URI can not be cached so every time you use it, you increase the filesize even more.  Ok, you save an http request per use, but is it worth it?</li>
</ul>
<p>and some advantages:</p>
<ul>
<li>You will not see the site without a background for even a single millisecond. Since the png is embedded in the CSS, it&#8217;s loaded as soon as the CSS itself is loaded. If your site background is too dark and you rely on the RGBA background to make the content legible, you might want to consider this solution.</li>
<li>No external files, no extra http requests.</li>
<li>The filter method works in IE6- without the script for transparent PNGs.</li>
</ul>
<p>Choose the method that fits your needs better. <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>RGBA is not only for backgrounds!</h3>
<p>It&#8217;s also for every CSS property that accepts color values. However, backgrounds in most cases are the easiest to workaround. As for borders, if you want solid ones, you can simulate them sometimes by wrapping a padded container with an RGBA background around your actual one and giving it as much padding as your desired border-width. For text color, sometimes you can fake that with opacity. However, these &#8220;solutions&#8221; are definitely incomplete, so you&#8217;d probably have to wait for full RGBA support and provide solid color fallbacks for those (unless someone comes up with an ingenious solution in &lt;canvas&gt;, it&#8217;s common these days <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />  ).</p>

]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/02/bulletproof-cross-browser-rgba-backgrounds/feed/</wfw:commentRss>
		<slash:comments>33</slash:comments>
		</item>
		<item>
		<title>CSS3 border-radius, today</title>
		<link>http://leaverou.me/2009/02/css3-border-radius-today/</link>
		<comments>http://leaverou.me/2009/02/css3-border-radius-today/#comments</comments>
		<pubDate>Fri, 13 Feb 2009 06:00:01 +0000</pubDate>
		<dc:creator>Lea Verou</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[border-radius]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[CSS3]]></category>
		<category><![CDATA[CSS3 properties]]></category>

		<guid isPermaLink="false">http://leaverou.me/?p=40</guid>
		<description><![CDATA[This is the first one from a series of articles I&#8217;m going to write about using CSS3 properties or values today. I&#8217;ll cover everything I have found out while using them, including various browser quirks and bugs I know of or have personally filed regarding them. In this part I&#8217;ll discuss ways to create rounded [...]]]></description>
			<content:encoded><![CDATA[
<div class="topsy_widget_data topsy_theme_mustard" style="float: right;margin-left: 0.75em; background: url(data:,%7B%20%22url%22%3A%20%22http%253A%252F%252Fleaverou.me%252F2009%252F02%252Fcss3-border-radius-today%252F%22%2C%20%22style%22%3A%20%22big%22%2C%20%22title%22%3A%20%22CSS3%20border-radius%2C%20today%22%20%7D);"></div>
<p>This is the first one from a series of articles I&#8217;m going to write about <em>using CSS3 properties or values <strong>today</strong></em>. I&#8217;ll cover everything I have found out while using them, including various browser quirks and bugs I know of or have personally filed regarding them. In this part I&#8217;ll discuss ways to create rounded corners without images and if possible without JavaScript in the most cross-browser fashion.<span id="more-40"></span></p>
<p>I will not cover irregular curves in this article, since I&#8217;ve yet to find any person who actually needed them, even once, including myself and browser support for them is far worse.</p>
<p><strong>Caution: </strong>The contents of a container with border-radius set are NOT clipped according to the border radius in any implementation/workaround mentioned below, and no, setting overflow to hidden won&#8217;t help (and even if it did, you&#8217;d risk text missing). You should specify a proper border-radius and/or padding to them if you want them to  follow their container&#8217;s curves properly. This could allow for some nice effects but most of the time it&#8217;s just a pain in the a$$.</p>
<h3>Mozilla Firefox</h3>
<p>Firefox supports rounded corners since version 2. However incomplete support in version 2 made designers sceptical to use them. The problem was that the rounded corners created were aliased back then, and also did not crop the background image, so if you had one, no rounded corners for you. This was fixed in FF3, so now more and more designers are starting to use them. The syntax is</p>
<pre>-moz-border-radius: [Number][unit];</pre>
<p>This is effectively a shorthand for:</p>
<pre>-moz-border-radius-bottomleft: [Number][unit];
-moz-border-radius-bottomright: [Number][unit];
-moz-border-radius-topleft: [Number][unit];
-moz-border-radius-topright: [Number][unit];<span class="cssPropName editable">
</span></pre>
<p>You don&#8217;t need to specify all these properties though, even if you wan&#8217;t different measures per corner, as <code>-moz-border-radius</code> functions as a regular CSS shorthand, allowing us to specify all 4 corners at once. It can be used in the following ways:</p>
<pre>-moz-border-radius: [Top-left and Bottom-right] [Top-right and bottom-left];
-moz-border-radius: [Top-left] [Top-right and bottom-left] [Bottom-right];
-moz-border-radius: [Top-left] [Top-right] [Bottom-right] [Bottom-left];</pre>
<p>A good mnemonic rule for the order of the values is that they are arranged clockwise, starting from Top left.</p>
<h3>Apple Safari</h3>
<p>Safari also implements CSS3 border-radius, but in a quite different way. If you want to set all four corners to the same border-radius, the process is almost identical. The only thing needed is:</p>
<pre>-webkit-border-radius: [Number][unit]</pre>
<p>However, things start to get tricky when you want to specify different radiuses per corner. Webkit does not support a shorthand syntax, since it chose to implement the spec closely, sacrifycing clarity but allowing for more flexibility. To cut a long story short, <a title="Read more about the difference between Mozilla's and Webkit's implementations" href="http://www.css3.info/border-radius-apple-vs-mozilla/" target="_blank">Webkit supports irregular curves instead of just circle quarters on each corner</a>, so if you try to add 2 values, the result will be  <a href="http://www.css3.info/wp-content/uploads/2007/06/border-radius.png" target="_blank">horrendous</a>.</p>
<p>So, you have to specify all four properties (or less if you want some of them to be square). To make matters even worse, the way the names of the properties are structured is different. There is one more dash, and the position of the corner styled by each property is not at the end but before <em>-radius</em>:</p>
<pre>-webkit-border-top-left-radius
-webkit-border-top-right-radius
-webkit-border-bottom-left-radius
-webkit-border-bottom-right-radius<span class="cssSemi">
</span></pre>
<p><strong>Caution: </strong>If the dimensions of your element are not enough to accomodate the rounded corners, they will be square in Webkit-based browsers. Specify a <code>min-width</code>/<code>min-height</code> or enough padding to avoid this.</p>
<h3>Google Chrome</h3>
<p>Since Google Chrome is based on Webkit, its border-radius support is like Safari&#8217;s. However, it&#8217;s haunted by an ugly bug: It renders the rounded corners <strong>aliased</strong>. <img src='http://leaverou.me/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<h3>Opera</h3>
<p>The bad news is that Opera does not implement the CSS3 border-radius yet (it will in the future, <a href="http://twitter.com/dstorey/status/1177020119" target="_blank">confirmed</a>). The good news is that it allows for SVG backgrounds since version 9.5. The even better news is that it supports <code>data://</code> URIs, so you can embed the SVG in your CSS, without resorting to external files as <a href="http://ejohn.org/blog/talk-performance-improvements-in-browsers/#comment-345434" target="_blank">someone recently pointed out to me</a>. <a href="http://a.deveria.com/" target="_blank">Alexis Deveria</a> was clever enough to even <a href="http://a.deveria.com/roundgen/" target="_blank">create a generator for them</a>, so that you could easily specify the background, border width and border-color and get the data URI instantly. This is a quite useful tool, but lacks some features (for instance you might want the background to be semi-transparent, like the one used in this blog). It&#8217;s ok for most cases though.</p>
<p>While Opera&#8217;s current lack of border-radius support is disappointing, you can utilize it pretty well with this method and if you know SVG well enough yourself you can create stunning effects.</p>
<h3>Internet Explorer (aka &#8220;The Web designer&#8217;s nemesis&#8221;)</h3>
<p>There&#8217;s no need to tell you that IE doesn&#8217;t support border-radius or SVG backgrounds, even in it&#8217;s latest version, right? You probably guessed already. There is some hope here though, a clever guy named <a href="http://dillerdesign.wordpress.com/" target="_blank">Drew Diller</a> carefully researched the MS-proprietary <a href="http://en.wikipedia.org/wiki/Vector_Markup_Language" target="_blank">VML language</a> and came up with <a href="http://www.dillerdesign.com/experiment/DD_roundies/" target="_blank">a script that utilizes it to create rounded corners in IE</a>. The bad news is that MS when releasing IE8 fixed some things and messed up others, so the script barely works on it. It also has some other <a href="http://www.dillerdesign.com/experiment/DD_roundies/#lacking" target="_blank">shortcomings</a>, but for most cases it can be a great tool (for IE7 and below, unless MS surprises us and fixes the VML regressions in IE8 before the stable). Also, if rounded corners are not crucial to your design and you don&#8217;t get too much traffic from IE users, you might consider ignoring IE altogether and having square corners in it. This way you&#8217;re also serving the greater good, since when IE users see your site in a supporting browser, they&#8217;ll conclude that &#8220;Oh, this browser shows the web nicer!&#8221; and the site will still be just as usable (in most cases rounded corners are not that crucial for usability, although <a href="http://www.usabilitypost.com/2008/09/24/the-function-of-rounded-corners/">they enchance it a bit</a>).</p>
<h3>Afterword</h3>
<p>I hope this article helped you learn something new. If you found any mistakes or inaccuracies, don&#8217;t hesitate to leave a comment, I don&#8217;t know everything and I&#8217;m not god. <img src='http://leaverou.me/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>One thing I have in mind is creating a PHP script that takes care of all these incompatibilities for you and caches the result. I don&#8217;t know if I&#8217;ll ever find the time to write it though, especially before someone else does <img src='http://leaverou.me/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> </p>

]]></content:encoded>
			<wfw:commentRss>http://leaverou.me/2009/02/css3-border-radius-today/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
