<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-277055053587992327</id><updated>2012-01-31T06:47:45.672-08:00</updated><category term='alpha opacity'/><category term='interface development'/><category term='image replacment'/><category term='UI'/><category term='accessibility'/><category term='progressive enhancement'/><category term='css'/><category term='javascript'/><category term='ie'/><category term='browsers'/><category term='HTML'/><title type='text'>Beneath the fold</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>21</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-7002339463728880276</id><published>2012-01-31T04:51:00.000-08:00</published><updated>2012-01-31T06:47:45.677-08:00</updated><title type='text'>IE7 and hasLayout</title><content type='html'>&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 140px; height: 140px;" src="http://www.fixcomputerproblems.net/wp-content/uploads/2010/10/internet-explorer-7-300x300.jpg" border="0" alt="" /&gt;&lt;br /&gt;All these years I've assumed that {zoom:100%;} and {height:1%;} where essentially the same, forcing an element to have layout &lt;a href="http://msdn.microsoft.com/en-us/library/ie/bb250481(v=vs.85).aspx"&gt;(hasLayout property)&lt;/a&gt;. After a very unproductive morning, being made to look foolish by IE7, I finally in desperation changed the zoom directive to height and my clear float hack started working. Note to self, go round the country and personally upgrade all IE6/7 versions to IE9!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-7002339463728880276?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/7002339463728880276/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2012/01/ie67-and-haslayout.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/7002339463728880276'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/7002339463728880276'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2012/01/ie67-and-haslayout.html' title='IE7 and hasLayout'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-6381429746176632150</id><published>2011-05-08T23:40:00.000-07:00</published><updated>2011-05-08T23:48:15.660-07:00</updated><title type='text'>Dynamcially adding style</title><content type='html'>Dynamically add style to a page...&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;var style = "body{color:#666;}";&lt;br /&gt;var s = document.createElement('style');&lt;br /&gt;s.setAttribute("type", "text/css");&lt;br /&gt;if (s.styleSheet) {   // IE&lt;br /&gt;    s.styleSheet.cssText = style;&lt;br /&gt;} else {&lt;br /&gt;    var stxt = document.createTextNode(style);&lt;br /&gt;    s.appendChild( stxt );&lt;br /&gt;}&lt;br /&gt;document.getElementsByTagName('head')[0].appendChild(s);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Remember to minify the style text using something like http://refresh-sf.com/yui/&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-6381429746176632150?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/6381429746176632150/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2011/05/dynamcially-adding-style.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/6381429746176632150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/6381429746176632150'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2011/05/dynamcially-adding-style.html' title='Dynamcially adding style'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-481945923773545376</id><published>2011-04-04T03:02:00.000-07:00</published><updated>2011-04-04T03:05:19.727-07:00</updated><title type='text'>'require': no such file to load -- sqlite3/sqlite3_native (LoadError)</title><content type='html'>When running "rails server" I was getting the following error... &lt;br /&gt;'require': no such file to load -- sqlite3/sqlite3_native (LoadError)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Banging my head on the desk for ages with this one. Then realised the default Aptana workspace name contained white space chars! Remove these and all is fine. &lt;br /&gt;&lt;br /&gt;Shame on me!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-481945923773545376?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/481945923773545376/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2011/04/require-no-such-file-to-load.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/481945923773545376'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/481945923773545376'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2011/04/require-no-such-file-to-load.html' title='&apos;require&apos;: no such file to load -- sqlite3/sqlite3_native (LoadError)'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-3700753319460257794</id><published>2010-08-27T07:41:00.000-07:00</published><updated>2010-08-29T14:28:04.004-07:00</updated><title type='text'>Chrome extension, accessing extension variables from scripts</title><content type='html'>&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 114px; height: 110px;" src="http://2.bp.blogspot.com/_2IOxbRFZS2c/THfjOiIiW_I/AAAAAAAAAZU/lFuj21oO7BE/s320/chome.jpg" border="0" alt="chrome logo" id="BLOGGER_PHOTO_ID_5510122507931376626" /&gt;&lt;br /&gt;Just went all around the houses trying to access variables from a script running within a web page. In actual fact it's quite easy. You need two things, a background pages and an options page to administer your options. So the first thing you need to do is make sure you have a reference to background and options in your extention manifest...&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;...&lt;br /&gt;  "background_page": "background.html",&lt;br /&gt;  "options_page": "options.html",&lt;br /&gt;...&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;From within your script you can then access variables using...&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;chrome.extension.sendRequest({action:"getItem",item:"somekey"}, function(response) {&lt;br /&gt;    var myvar = response.value&lt;br /&gt;    console.log("somekey:"+myvar);&lt;br /&gt;});&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Background page should look something like this...&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&amp;lt;html&gt;&lt;br /&gt;&amp;lt;head&gt;&amp;lt;title&gt;background&amp;lt;/title&gt;&lt;br /&gt;&amp;lt;script type="text/javascript"&gt;&lt;br /&gt;chrome.extension.onRequest.addListener(&lt;br /&gt;  function(request, sender, sendResponse) {&lt;br /&gt;    console.log(sender.tab ?&lt;br /&gt;                "from a content script:" + sender.tab.url :&lt;br /&gt;                "from the extension");&lt;br /&gt; switch(request.action){&lt;br /&gt;  case "clear" :&lt;br /&gt;   localStorage.clear();&lt;br /&gt;   sendResponse({message:"Thanks, localStorage has been cleared"});&lt;br /&gt;  break;&lt;br /&gt;  case "getItem" : &lt;br /&gt;          var value = localStorage.getItem(request.item);&lt;br /&gt;          sendResponse({value:value,message:"value returned from background.html"});&lt;br /&gt;  break;  &lt;br /&gt;  case "getItems" :&lt;br /&gt;   var value = {}; &lt;br /&gt;          for (var i=0;i&lt;request.items.length;i++){&lt;br /&gt;    value[request.items[i]] = localStorage.getItem(request.items[i])&lt;br /&gt;   }&lt;br /&gt;        sendResponse({value:value,message:"value returned from background.html"});&lt;br /&gt;  break;  &lt;br /&gt;  case "setItem" :&lt;br /&gt;         localStorage.setItem(request.item,request.value);&lt;br /&gt;   sendResponse({message:"Thanks, your update has been saved"});&lt;br /&gt;  break;&lt;br /&gt;  case "setItems" :&lt;br /&gt;          for (name in request.items){&lt;br /&gt;    localStorage.setItem(name,request.items[name]);&lt;br /&gt;   }  &lt;br /&gt;   sendResponse({message:"Thanks, your updates have been saved"});&lt;br /&gt;  break;&lt;br /&gt; }&lt;br /&gt;  });&lt;br /&gt;&amp;lt;/script&gt;&lt;br /&gt;&amp;lt;/head&gt;&lt;br /&gt;&amp;lt;/html&gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The above will give you a simple way to store variables.  &lt;br /&gt;&lt;br /&gt;Your options page needs to use the background.html to save variables to&lt;br /&gt;&lt;pre class="code"&gt;&amp;lt;html&gt; &lt;br /&gt;&amp;lt;head&gt; &lt;br /&gt;&amp;lt;title&gt;Extention options&amp;lt;/title&gt; &lt;br /&gt;&amp;lt;script type="text/javascript"&gt;&lt;br /&gt; window.myOptions = {&lt;br /&gt;  init:function(){&lt;br /&gt;&lt;br /&gt;   chrome.extension.sendRequest({action:"getItem",item:"optionOne"}, function(response) {&lt;br /&gt;    console.log("!responce.value"+response.value);&lt;br /&gt;    document.getElementById("optionOne").checked = (response.value=="off") ? false : true;&lt;br /&gt;   });    &lt;br /&gt;   chrome.extension.sendRequest({action:"getItem",item:"optionTwo"}, function(response) {&lt;br /&gt;    console.log("!responce.value"+response.value);&lt;br /&gt;    document.getElementById("optionTwo").checked = (response.value=="off") ? false : true;&lt;br /&gt;   });    &lt;br /&gt;   &lt;br /&gt;   document.getElementById("optionOne").addEventListener("click",function(){&lt;br /&gt;    myOptions.change("optionOne");&lt;br /&gt;   },false)&lt;br /&gt;   document.getElementById("optionTwo").addEventListener("click",function(){&lt;br /&gt;    myOptions.change("optionTwo");&lt;br /&gt;   },false)&lt;br /&gt;   document.getElementById("resetButton").addEventListener("click",function(){&lt;br /&gt;    myOptions.reset();&lt;br /&gt;   },false)    &lt;br /&gt;  }&lt;br /&gt;  ,change:function(key){&lt;br /&gt;   var value = document.getElementById(key).checked ? "on" : "off";&lt;br /&gt;   chrome.extension.sendRequest({action:"setItem",item:key,value:value}, function(response) {&lt;br /&gt;    console.log("!responce.message"+response.message);&lt;br /&gt;    var m = (value == "off")? "disabled" : "enabled"&lt;br /&gt;    document.getElementById("settings").innerHTML = key + " has been "+ m;&lt;br /&gt;   });      &lt;br /&gt;  }&lt;br /&gt;  ,reset:function(){&lt;br /&gt;   chrome.extension.sendRequest({action:"clear"}, function(response) {&lt;br /&gt;    location.reload();&lt;br /&gt;   });    &lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt; window.addEventListener("load", window.myOptions.init, false)&lt;br /&gt;&amp;lt;/script&gt; &lt;br /&gt;&lt;br /&gt;&amp;lt;/head&gt; &lt;br /&gt;&amp;lt;body&gt;    &lt;br /&gt; &amp;lt;form&gt;&lt;br /&gt;  &amp;lt;h1&gt;Options&amp;lt;/h1&gt;&lt;br /&gt;  &amp;lt;p&gt;&lt;br /&gt;   Intro text &lt;br /&gt;  &amp;lt;/p&gt;&lt;br /&gt;  &amp;lt;p&gt;&lt;br /&gt;   &amp;lt;span class="option"&gt;&lt;br /&gt;    &amp;lt;input type="checkbox" name="optionOne" id="optionOne" value="on" /&gt;&lt;br /&gt;   &amp;lt;/span&gt;&lt;br /&gt;   &amp;lt;label for="optionOne" class="wiki"&gt;Enable option one&amp;lt;/label&gt;&lt;br /&gt;  &amp;lt;/p&gt;&lt;br /&gt;  &amp;lt;p&gt;&lt;br /&gt;   &amp;lt;span class="option"&gt;&lt;br /&gt;    &amp;lt;input type="checkbox" name="optionTwo" id="optionTwo" value="on" /&gt;&lt;br /&gt;   &amp;lt;/span&gt;&lt;br /&gt;   &amp;lt;label for="optionTwo" class="wiki"&gt;Enable option two&amp;lt;/label&gt;&lt;br /&gt;  &amp;lt;/p&gt;&lt;br /&gt;  &amp;lt;p style="height:1.3em;color:red" class="alert"&gt;&lt;br /&gt;   &amp;lt;span id="settings"&gt;&amp;lt;/span&gt;&lt;br /&gt;  &amp;lt;/p&gt;&lt;br /&gt;  &amp;lt;p&gt;&lt;br /&gt;   &amp;lt;input type="button" id="resetButton" value="Reset default options"/&gt;&lt;br /&gt;  &amp;lt;/p&gt;&lt;br /&gt; &amp;lt;/form&gt;&lt;br /&gt; &lt;br /&gt; &amp;lt;/body&gt; &lt;br /&gt;&lt;br /&gt;&amp;lt;/html&gt; &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-3700753319460257794?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/3700753319460257794/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2010/08/chrome-extension-accessing-extension.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/3700753319460257794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/3700753319460257794'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2010/08/chrome-extension-accessing-extension.html' title='Chrome extension, accessing extension variables from scripts'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_2IOxbRFZS2c/THfjOiIiW_I/AAAAAAAAAZU/lFuj21oO7BE/s72-c/chome.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-2793954954916102774</id><published>2010-08-12T09:08:00.000-07:00</published><updated>2010-08-12T09:12:41.729-07:00</updated><title type='text'>Math.random()</title><content type='html'>&lt;p&gt;Note to self... for a three number 100 - 999&lt;/p&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;var min = 100&lt;br /&gt;var max = 1000&lt;br /&gt;Math.floor(Math.random()*(max-min)+min)&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-2793954954916102774?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/2793954954916102774/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2010/08/mathrandom.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/2793954954916102774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/2793954954916102774'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2010/08/mathrandom.html' title='Math.random()'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-795120671789429093</id><published>2010-01-04T12:00:00.000-08:00</published><updated>2010-01-04T12:18:28.369-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='css'/><title type='text'>funny font size in safari on the iPhone</title><content type='html'>&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; width: 94px; height:149px;" src="http://www.gotomobile.com/wp-content/uploads/iphone_safari_browser.png" border="0" alt="picture of an iphone" width="300" height="300" /&gt; I finally decided I needed to sort out the font size in safari mobile, after a little tinkering it turns out you can just set the -webkit-text-size-adjust to "none" and that stops the browser from resizing the text. &lt;br /&gt;&lt;br /&gt;&lt;pre class="code" style="clear:both"&gt;&lt;br /&gt;body {&lt;br /&gt;   -webkit-text-size-adjust:none;&lt;br /&gt;}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-795120671789429093?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/795120671789429093/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2010/01/funny-font-size-in-safari-on-iphone.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/795120671789429093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/795120671789429093'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2010/01/funny-font-size-in-safari-on-iphone.html' title='funny font size in safari on the iPhone'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-864404837621628637</id><published>2009-12-23T06:24:00.000-08:00</published><updated>2009-12-23T07:08:49.029-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='browsers'/><category scheme='http://www.blogger.com/atom/ns#' term='css'/><title type='text'>hasLayout problems after all these years</title><content type='html'>Having terrible trouble with all version of IE trying to get some peekaboo text to stay put. In this scenario a div was not paying ball at all, after setting hasLayout on pretty much every element in the entire page I realised that the system was outputting HTML without a DTD, dogh, I feel like i've just called tech support to complain about not being able to print, only to find out that the cleaner unplugged the printer.&lt;br /&gt;&lt;br /&gt;Note to self, always check the most obvious thing first!&lt;br /&gt;&lt;br /&gt;In IE7 I have a normal input type = button which as the behaviour that when you scroll the text in the button gets visually corrupted. So very slowly scrolling the button into view will wipe the text and the button will appear empty. The offending button is fine in IE6 and IE8, I was tempted to ignore this and mark it down as a bug in the browser but weakened and decided to fix it. &lt;br /&gt;&lt;br /&gt;After tinkering with the CSS for a while I couldn't find any hack/fix for this issue, setting the writing-mode style to top to bottom, did fix it but didn't think having the button text written out vertically would go down well!&lt;br /&gt;&lt;br /&gt;In the end....&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;window.attachEvent ('onscroll', function(){&lt;br /&gt; // layout fix for IE7 disappearing text, element has layout so resorting to this madness!&lt;br /&gt; document.getElementById('buttonMoreSections').style.backgroundColor=(document.documentElement.scrollTop % 2)? '#fff':'white';&lt;br /&gt;})&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;total MADNESS !&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://haslayout.net/haslayout"&gt;More about hasLayout&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-864404837621628637?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/864404837621628637/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2009/12/haslayout-problems-after-all-these.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/864404837621628637'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/864404837621628637'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2009/12/haslayout-problems-after-all-these.html' title='hasLayout problems after all these years'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-799322731772703166</id><published>2009-12-16T10:10:00.000-08:00</published><updated>2009-12-27T04:21:21.877-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='accessibility'/><category scheme='http://www.blogger.com/atom/ns#' term='image replacment'/><title type='text'>Image Replacement, but only if images are enabled</title><content type='html'>The fact that you don't know whether the user has images enabled or not is a real problem with &lt;a href="http://en.wikipedia.org/wiki/Fahrner_Image_Replacement"&gt;image replacement&lt;/a&gt;. You can't hide the existing text if images are disabled as the user will just end up with nothing, the standard way to handle this problem is to keep the text visible and have an image bigger than the text and place the image over the text, if the user doesn't have images they will still see the text. This is only ok if your replacing a header where the image is bigger than the text, but no good for any small images like icons where the text is always going to be bigger. &lt;br /&gt;&lt;br /&gt;One way round this is to only add images if your sure the user has images enabled and to keep the text in the HTML flow for screen reader users.&lt;br /&gt;&lt;br /&gt;One way of testing for images is to use JavaScript and set a class name on the HTML element if image are enabled/supported, then you can apply styles based on the existence of this class name, using this technique you'll only do image replacement if the user has JavaScript, CSS and Images enabled which is a good thing. If the user doesn't have any of these three you probably don't want to mess with the UI at all.&lt;br /&gt;&lt;br /&gt;See the &lt;a href="http://pclancey.com/test/img.html"&gt;image replacement test page&lt;/a&gt; for some uses. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="code" style="display:none"&gt;&lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"&lt;br /&gt;    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt;&lt;br /&gt;&amp;lt;head&gt;&lt;br /&gt; &amp;lt;title&gt;Image Replacment example&amp;lt;/title&gt;&lt;br /&gt; &amp;lt;style type="text/css"&gt;&lt;br /&gt;  /* styles if images are enabled */&lt;br /&gt;  html.img span.enabled {&lt;br /&gt;   color:#080;&lt;br /&gt;   display:inline;&lt;br /&gt;  }&lt;br /&gt;  html.img span.disabled {&lt;br /&gt;   display:none;&lt;br /&gt;  }&lt;br /&gt;  span.enabled {&lt;br /&gt;   display:none;&lt;br /&gt;  }&lt;br /&gt;  span.disabled {&lt;br /&gt;   color:#f00;&lt;br /&gt;   display:inline;&lt;br /&gt;  } &lt;br /&gt;  /* hide text if images are enebled */&lt;br /&gt;  html.img h1 span,&lt;br /&gt;  html.img a span span {&lt;br /&gt;   display:block;&lt;br /&gt;   height:1px;&lt;br /&gt;   overflow:hidden;&lt;br /&gt;   width:1px;&lt;br /&gt;  } &lt;br /&gt;  &lt;br /&gt;  /* add images */ &lt;br /&gt;  html.img a span.img {&lt;br /&gt;   display:inline-block;&lt;br /&gt;   height:12px;&lt;br /&gt;   overflow:hidden;&lt;br /&gt;   width:12px;&lt;br /&gt;  }&lt;br /&gt;  html.img a.external span.img {&lt;br /&gt;   background-image:url(http://upload.wikimedia.org/wikipedia/commons/6/64/Icon_External_Link.png);&lt;br /&gt;  }&lt;br /&gt;  html.img a.doc span.img {&lt;br /&gt;   background-image:url(http://pclancey.com/i/btf/doc.png);&lt;br /&gt;  }&lt;br /&gt;  html.img a.pdf span.img {&lt;br /&gt;   background-image:url(http://pclancey.com/i/btf/pdf.png);&lt;br /&gt;  }&lt;br /&gt;  html.img h1 {&lt;br /&gt;   background-image:url(http://pclancey.com/i/btf/h103.png);&lt;br /&gt;   height:88px;&lt;br /&gt;   width:680px;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;br /&gt;  /* menu styles */&lt;br /&gt;  *.menu a {&lt;br /&gt;   text-decoration:none;&lt;br /&gt;  }&lt;br /&gt;  *.menu a:active,&lt;br /&gt;  *.menu a:focus,&lt;br /&gt;  *.menu a:hover {&lt;br /&gt;   text-decoration:underline;&lt;br /&gt;  }&lt;br /&gt; &amp;lt;/style&gt; &lt;br /&gt;&amp;lt;/head&gt;&lt;br /&gt;&amp;lt;body&gt;&lt;br /&gt; &amp;lt;h1&gt;&amp;lt;span&gt;Beneath the Fold&amp;lt;/span&gt;&amp;lt;/h1&gt;&lt;br /&gt; &amp;lt;p&gt;&lt;br /&gt;  Image replacement test: &lt;br /&gt;  Can you see an image of a mouse?&lt;br /&gt;  &amp;lt;img src="http://news.nationalgeographic.com/news/2009/03/images/090320-new-mouse-picture_big.jpg" height="60" alt="image of a wet mouse" /&gt;&lt;br /&gt;  &amp;lt;br/&gt;Images seem to be: &lt;br /&gt;   &amp;lt;span class="enabled"&gt;enabled, using image replacement&amp;lt;/span&gt;&lt;br /&gt;   &amp;lt;span class="disabled"&gt;disabled or can't tell, not using image replacement&amp;lt;/span&gt;&lt;br /&gt; &amp;lt;/p&gt; &lt;br /&gt; &amp;lt;ul class="menu"&gt;&lt;br /&gt;  &amp;lt;li&gt;&amp;lt;a href="http://google.com" class="external" target="_blank"&gt;&lt;br /&gt;   External link&lt;br /&gt;   &amp;lt;span class="img"&gt;&lt;br /&gt;    &amp;lt;span&gt;(opens in new window)&amp;lt;/span&gt;&lt;br /&gt;   &amp;lt;/span&gt;&lt;br /&gt;  &amp;lt;/a&gt;&amp;lt;/li&gt;&lt;br /&gt;  &amp;lt;li&gt;&amp;lt;a href="http://google.com" class="doc"&gt;&lt;br /&gt;   Link to some document&lt;br /&gt;   &amp;lt;span class="img"&gt;&lt;br /&gt;    &amp;lt;span&gt;(Word DOC)&amp;lt;/span&gt;&lt;br /&gt;   &amp;lt;/span&gt;&lt;br /&gt;  &amp;lt;/a&gt;&amp;lt;/li&gt;&lt;br /&gt;  &amp;lt;li&gt;&amp;lt;a href="http://google.com" class="pdf"&gt;&lt;br /&gt;   Link to some other document&lt;br /&gt;   &amp;lt;span class="img"&gt;&lt;br /&gt;    &amp;lt;span&gt;(PDF)&amp;lt;/span&gt;&lt;br /&gt;   &amp;lt;/span&gt;&lt;br /&gt;  &amp;lt;/a&gt;&amp;lt;/li&gt;&lt;br /&gt; &amp;lt;/ul&gt;&lt;br /&gt; &lt;br /&gt;&amp;lt;/body&gt; &lt;br /&gt; &amp;lt;script type="text/javascript"&gt;&lt;br /&gt;  /* &lt;br /&gt;   * set the img class name on the HTML doc&lt;br /&gt;   * run this oncontentready, onload or &lt;br /&gt;   * at the bottom of the page&lt;br /&gt;   * &lt;br /&gt;   */&lt;br /&gt;  (function(){&lt;br /&gt;   if (!document.getElementsByTagName){return}&lt;br /&gt;   var existentimg = new Image;&lt;br /&gt;   var html = document.getElementsByTagName('html')[0];&lt;br /&gt;   existentimg.onload = function(){&lt;br /&gt;    html.className+=' img';&lt;br /&gt;    var nonexistentimg = new Image;&lt;br /&gt;    nonexistentimg.onload = function(){&lt;br /&gt;     html.className=html.className.replace(/\bimg\b/,'');&lt;br /&gt;    }&lt;br /&gt;    nonexistentimg.src="/nonexistentimg.gif";&lt;br /&gt;   }&lt;br /&gt;   existentimg.src = (document.images.length)? document.images[0].src : 'http://upload.wikimedia.org/wikipedia/commons/6/64/Icon_External_Link.png' ; &lt;br /&gt;  })();  &lt;br /&gt; &amp;lt;/script&gt;&lt;br /&gt;&amp;lt;/html&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-799322731772703166?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/799322731772703166/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2009/12/image-of-wet-mouse.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/799322731772703166'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/799322731772703166'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2009/12/image-of-wet-mouse.html' title='Image Replacement, but only if images are enabled'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-5962500310597398517</id><published>2009-11-10T06:53:00.001-08:00</published><updated>2009-12-05T12:44:11.813-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='ie'/><category scheme='http://www.blogger.com/atom/ns#' term='alpha opacity'/><title type='text'>IE, butters text after filter is applied</title><content type='html'>&lt;a href="http://www.pcnews.by/UserFiles/Image/2009/apr/15/ie8_logo.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; width: 100px; height: 100px;" src="http://www.pcnews.by/UserFiles/Image/2009/apr/15/ie8_logo.jpg" border="0" alt="IE8 logo" width="300" height="300" /&gt;&lt;/a&gt;  In my little world IE8 usage over took IE7 for the first time last month, so decided to try to sort out my JavaScript fades which I disable for IE. The problem with the fades is after the fade in ends the text is blurred, fuzzy and generally butters! &lt;br /&gt;&lt;br /&gt;TODO: add image of butters text...&lt;br /&gt;&lt;br /&gt;I haven't looked into this in any great depth, but the problem seems to be with clearType text in IE and obj.style.filter. If you apply the Alpha(opacity) filter the text gets mashed up, so setting obj.style.filter="Alpha(opacity=100)" breaks the anti-alias on text. &lt;br /&gt;&lt;br /&gt;One work around is to set a background colour on the element your going to apply a filter to. If you don't know which elements your going to fade in advance you can reset the filter after the fade has run, which isn't ideal but better than nothing.&lt;br /&gt;&lt;br /&gt;I user a method similar to the bellow for setting opacity&lt;br /&gt;&lt;pre style="font-size:90%"&gt;&lt;br /&gt;/** @id Transition.SetOpacity */&lt;br /&gt;function SetOpacity(el,opacity){&lt;br /&gt;    opacity = (opacity&gt;=100)? 100 : opacity;&lt;br /&gt;    el.style.opacity   = (opacity / 100); &lt;br /&gt;    el.style.MozOpacity  = (opacity / 100); &lt;br /&gt;    el.style.KhtmlOpacity  = (opacity / 100); &lt;br /&gt;    &lt;br /&gt;    // private method to set opacity in IE&lt;br /&gt;    setIEOpacity(el,opacity)&lt;br /&gt;  &lt;br /&gt;    function setIEOpacity(el,opacity){&lt;br /&gt;        if (!el.currentStyle.hasLayout){&lt;br /&gt;            // give element layout&lt;br /&gt;            el.style.zoom = 1;&lt;br /&gt;        }&lt;br /&gt;        if (!el.originalFilter){&lt;br /&gt;            // save the original filter, if one exists, so you can replace it after fade &lt;br /&gt;            el.originalFilter = el.currentStyle.filter || 'none';&lt;br /&gt;        }&lt;br /&gt;        // if opacity = 100 put the original filter back&lt;br /&gt;        el.style.filter = (opacity == 100) ? &lt;br /&gt;            el.originalFilter : &lt;br /&gt;            'progid:DXImageTransform.Microsoft.Alpha(opacity='+ opacity + ')';&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;NB. for a fade to work in IE at all, the element needs to have layout (obj.currentStyle.hasLayout) this is a read only attribute, to set it to true you need to give the element a style that will trigger it to set .hasLayout to true. I normally set the zoom style to 1 in an IE only stylesheet. For other ways of tringering hasLayout see &lt;a href="http://haslayout.net/haslayout"&gt;haslayout.net&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-5962500310597398517?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/5962500310597398517/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2009/11/ie-butters-text-after-filter-is-applied.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/5962500310597398517'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/5962500310597398517'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2009/11/ie-butters-text-after-filter-is-applied.html' title='IE, butters text after filter is applied'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-171624053771929981</id><published>2009-10-07T03:07:00.000-07:00</published><updated>2009-10-07T03:51:59.406-07:00</updated><title type='text'>Forms, field by field error checking</title><content type='html'>&lt;a href="http://images.wellcome.ac.uk/" title="Pyramidal neurons forming a network in the brain"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 170px;" src="http://images.wellcome.ac.uk/indexplus/obf_images/26/9f/65fc2d97ea8d9b87a285a2efc12d.jpg" border="0" alt="Pyramidal neurons forming a network in the brain" /&gt;&lt;/a&gt;Like most developers for the past couple of years I've been implementing form checking on a field by field basis so when a user is filling in a form field the client side error checking is run. This has a couple of advantages, firstly the users gets the errors there and then, so when they get to the end of the form it should be valid and ready to submit, also it's quite fun to implement! &lt;br /&gt;&lt;br /&gt;However, I was reading some research (which I have now temporarily misplaced!) which calls this approach into question. The basic premise was that in regard to form filling, the brain works in two different modes,  the 'create' mode and the 'edit' mode. &lt;br /&gt;&lt;br /&gt;In light of this the best way to handle forms is to allow the user to fill in the form (brain is in create mode) then validate all the elements in one go, so the user can go back over the form (brain in edit mode) to fix any errors. This was tested and found to be better than making the user switch from create to edit mode on a form field by field basis. &lt;br /&gt;&lt;br /&gt;I'll try to find the relevant article, unfortunately my brain is in permanent 'confusion' mode so that may take some time!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-171624053771929981?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/171624053771929981/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2009/10/forms-and-error-checking.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/171624053771929981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/171624053771929981'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2009/10/forms-and-error-checking.html' title='Forms, field by field error checking'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-35763397109821477</id><published>2009-06-16T08:09:00.000-07:00</published><updated>2009-06-22T08:41:25.485-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='progressive enhancement'/><title type='text'>Good bye browser matrix...</title><content type='html'>Is it time to just say "So long, and thanks for all the fish" to the browser matrix? &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.flickr.com/photos/fmg2001/679774853/"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 196px; height: 240px;" src="http://farm2.static.flickr.com/1179/679774853_bb16c795a4_m.jpg" border="0" alt="" /&gt;&lt;/a&gt; The browser matrix was quite handy in days of yor, when browsers worked in quite fundamentally different ways from each other (remember NS4 vis IE4?). Nice then to just pick a couple of browsers to support, you couldn't really expect your site to work on anything that you hadn't tested it on anyway.&lt;br /&gt;&lt;br /&gt;So why don't we need it anymore? &lt;br /&gt;Well, for a start if your using progressive enhancement you could expect your site will work on any user-agent that understands HTML. In which case what does "Support" actually mean? The notion that a website supports a specific browser OS combination is an old school way of looking at the web.  &lt;br /&gt;&lt;br /&gt;What's really the problem with saying that a site supports a particular browser though?&lt;br /&gt;Well, let's look at what we really want from our website in the first place, we put our site up on the Internet, it's available to anyone, so we want it to work as well as possible, on as many user-agents as possible. &lt;br /&gt;&lt;br /&gt;How should we achieve this? &lt;br /&gt;The browser matrix method encourages developers to adopt a blinkered approach, we ask developers to build a site that works on browsers A, B and C. They build it using A and then debug on B and C, job done. &lt;br /&gt;&lt;br /&gt;So where does that leave users of browser D? &lt;br /&gt;Testers don't check browser D because its not on the matrix and any bugs that do get raised by users get rejected as "Unsupported user-agent" for the same reason. So, over time the browser matrix is a self for filling prophecy, the site will only work on browsers A, B and C. &lt;br /&gt;There is another interesting aspect though, the notion of a browser being "Supported" changes the responsibility of the developer, if browser C has a bug in it that results in a visual formatting issue, the fact that the problem is a bug in the browser is irrelevant, because browser C is supported the developer has to accommodate the bug in the website, this means hacks and work-a-rounds in the code. The result of which means the more supported browsers in the matrix the more bloated your site gets as more and more browser bugs get accommodated for. &lt;br /&gt;&lt;br /&gt;So what's the alternative? &lt;br /&gt;The best alternative to having a browser matrix, is to NOT have a browser matrix! &lt;br /&gt;&lt;br /&gt;Let's look at a scenario; we ask our developer to build the site to work on a text only browser, and give them a visual design or two of how the site should look on a desktop browser. The developer makes semantic, working HTML and enhances it to match the visual design, not having a matrix to work from the developer checks the enhanced look and feel on the browsers they have on their machine, likely the latest versions of the main browsers, the developer then hands the site over to testing. &lt;br /&gt;&lt;br /&gt;The testers, without a browser matrix to follow, will start testing the site, they are likely to check the analytics of the site, or of a similar site, to see what user-agents people are using and organise their test effort accordingly, as well as that, they will test on any user-agent they have to hand, they can't help them selves! &lt;br /&gt;&lt;br /&gt;Other people in the company will also raise bugs as the user-agent they are using is no longer "Unsupported". &lt;br /&gt;&lt;br /&gt;Okay, so we have anarchy! &lt;br /&gt;Our developer has loads of bugs assigned against the UI, how do we handle them all? &lt;br /&gt;&lt;br /&gt;In actual fact, it's quite easy, bugs can be prioritised quite quickly by assessing a number of factors:&lt;br /&gt;&lt;br /&gt;* What is the impact of the bug to the user? (is it a show stopper?)&lt;br /&gt;* What is the frequency of the effected user-agent? (is it a high frequency browser?)&lt;br /&gt;* How easy is it to fix&lt;br /&gt;* What is the negative impact of fixing the bug? (e.g. do you have to introduce code forking?)&lt;br /&gt;&lt;br /&gt;For example; bugs come in around visual layout in IE6, impact on users is fairly high, it's a high frequency browser, easy to fix and impact on other browsers is nil as we can fix issues using conditional comments for IE6 only, these can be done ASAP. So basic common sense really!&lt;br /&gt;&lt;br /&gt;In the end the simple fact that more issues are know about will help and the site get better over time, since it won't get held back by the existence of a Browser Matrix.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-35763397109821477?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/35763397109821477/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2009/04/good-bye-browser-matrix.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/35763397109821477'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/35763397109821477'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2009/04/good-bye-browser-matrix.html' title='Good bye browser matrix...'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm2.static.flickr.com/1179/679774853_bb16c795a4_t.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-7613072132893767280</id><published>2009-06-03T06:59:00.001-07:00</published><updated>2009-06-04T02:22:20.329-07:00</updated><title type='text'>Font size switching, yes again!</title><content type='html'>I was just having the font-size switching conversation with someone. I was banging on about our policy which is tell users how to change the font size in their browser, rather than duplicating this functionality with client side script. &lt;br /&gt;&lt;br /&gt;All very well, but down at Shaw-Trust they (pretty much everyone) prefers the click to change method (e.g. three varying size "A"s next to each other and you click on the one you like the size of... &lt;a href="http://www.webcredible.co.uk"&gt;www.webcredible.co.uk&lt;/a&gt;). &lt;br /&gt;&lt;br /&gt;But, I complained, if you set the size of text you like in your browser then text in all websites sites, that aren't fixed size text, will be the right size?&lt;br /&gt;&lt;br /&gt;Yes, but some sites don't support changing text size and break.&lt;br /&gt;&lt;br /&gt;What do you mean? Either a site will be coded old school with fixed font size, in which case it wont change or it be relative size and will work?&lt;br /&gt;&lt;br /&gt;No, some sites have relative font size but don't support larger sizes so if you change the font size in your browser the layout will be broken and you'll need to change it back in order to use the site.&lt;br /&gt;&lt;br /&gt;You can't be serious, show me a site like that...&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.virginmedia.com"&gt;www.virginmedia.com&lt;/a&gt; (try IE with anything other than default font size)&lt;br /&gt;&lt;br /&gt;oh...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;IE6 Screen shot with larger and normal font size...&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_2IOxbRFZS2c/SiaOLVO0SqI/AAAAAAAAARw/0gQ7jFfQtSU/s1600-h/screenone.jpg"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 146px;" src="http://2.bp.blogspot.com/_2IOxbRFZS2c/SiaOLVO0SqI/AAAAAAAAARw/0gQ7jFfQtSU/s320/screenone.jpg" border="0" alt="IE6 Screenshot with larger and normal font size" title="IE6 Screenshot with larger and normal font size" id="BLOGGER_PHOTO_ID_5343114333250669218" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-7613072132893767280?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/7613072132893767280/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2009/06/font-size-switching-yes-again.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/7613072132893767280'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/7613072132893767280'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2009/06/font-size-switching-yes-again.html' title='Font size switching, yes again!'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_2IOxbRFZS2c/SiaOLVO0SqI/AAAAAAAAARw/0gQ7jFfQtSU/s72-c/screenone.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-5666811542019147061</id><published>2009-05-01T09:10:00.000-07:00</published><updated>2009-05-01T09:33:20.355-07:00</updated><title type='text'>@media nasty hacks</title><content type='html'>What with IEs conditional comments its been a long time since in needed to do any CSS hacks. Being a bit out of practise it goes against the grain to add stuff that's obviously wrong just to get something to display in one browser or another. Still, what are you going to do? Telling people to change their user agent is not really a viable option. The particular problem I was trying to hack was on Opera mini on the Blackberry, so took to delivering a little CSS for that it could understand to fix the layout issue.&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;/* hack to fix search form in Opera mini */&lt;br /&gt;@media screen and (max-device-width: 480px) { &lt;br /&gt; html #search-options,&lt;br /&gt; html #search-options div.searchOptions,&lt;br /&gt; html #search-box,&lt;br /&gt; html #search-options div.searchBoxWrapper,&lt;br /&gt; html #search-options div.searchBoxWrapper div.searchBoxContainer,&lt;br /&gt; html #search-options div.searchBoxWrapper div.search-btn {&lt;br /&gt;  height:20px;&lt;br /&gt;  overflow:hidden;&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As you can see, fixed the heights of a load of divs which fixed the layout issue. So only problem is, this breaks they layout that worked perfectly well before in the iPhone! So I had to add yet another hack to reset it back to how it was...&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;/* remove for webkit */&lt;br /&gt;@media screen and (-webkit-min-device-pixel-ratio:0){ &lt;br /&gt;    html body #search-box  {&lt;br /&gt;       height:auto;&lt;br /&gt;    }        &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It's like 1999 all over again! Anyway, question is, is there a better opera mini only way to write the first hack which won't get picked up by other small screen devices??? &lt;br /&gt;&lt;br /&gt;I shall investigate (at some point!)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-5666811542019147061?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/5666811542019147061/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2009/05/media-nasty-hacks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/5666811542019147061'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/5666811542019147061'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2009/05/media-nasty-hacks.html' title='@media nasty hacks'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-6932724702894770829</id><published>2009-03-26T05:12:00.000-07:00</published><updated>2009-03-26T05:24:55.222-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>Mouse over menus and delay</title><content type='html'>Just been looking at menus, not for the first time nor the last. One thing i picked up on in &lt;a href="http://www.useit.com/alertbox/mega-dropdown-menus.html"&gt;Jakob Nielsen's Alertbox&lt;/a&gt; is his opinion that mouse over menus should appear after a half second delay, this is to reduce the irritating flicker you get when moving the mouse around a page. I've only seen this implemented a couple of times, can't remember where, but I totally agree with this approach.&lt;br /&gt;&lt;br /&gt;I'm much more of a clicky menu person myself, but if you must go mouse over then, delay before showing and delay before closing too!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Related links&lt;/h2&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.useit.com/alertbox/mega-dropdown-menus.html"&gt;http://www.useit.com/alertbox/mega-dropdown-menus.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.smashingmagazine.com/2009/03/24/designing-drop-down-menus-examples-and-best-practices/"&gt;http://www.smashingmagazine.com/2009/03/24/designing-drop-down-menus-examples-and-best-practices/&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-6932724702894770829?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/6932724702894770829/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2009/03/mouse-over-menus-and-delay.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/6932724702894770829'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/6932724702894770829'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2009/03/mouse-over-menus-and-delay.html' title='Mouse over menus and delay'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-5785078149356635177</id><published>2009-03-21T12:26:00.000-07:00</published><updated>2009-04-18T07:30:30.091-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='progressive enhancement'/><title type='text'>JavaScript support levels</title><content type='html'>Generally, i breakdown JavaScript support into 4 levels. This makes life much easier and as i'm a lazy bas****d it suits me to keep development time down to a minimum.&lt;br /&gt;&lt;br /&gt;I'm using something like this...&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt; window.user = {&lt;br /&gt; jsSupportLevel : 0,&lt;br /&gt; init: function(){&lt;br /&gt;  if(!document.getElementById){return;}&lt;br /&gt;  var ua=navigator.userAgent.toLowerCase();&lt;br /&gt;  var platform=navigator.platform.toLowerCase();&lt;br /&gt;  var isPC = (platform.match('win32')||platform.match('win64'))?true:false;&lt;br /&gt;  var isDeskTop = ( ua.match('firefox') || isPC || platform.match('macintel')  )?true:false;&lt;br /&gt;  var support = 1;&lt;br /&gt;  if (window.XMLHttpRequest){support = 2}&lt;br /&gt;  if ( support==2 &amp;&amp; isDeskTop ){&lt;br /&gt;   support = 3;&lt;br /&gt;  }&lt;br /&gt;  this.jsSupportLevel =  support;&lt;br /&gt; }&lt;br /&gt;};user.init();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This will give you a js global "user" and you use it in your js to determine whether to do some enhancements or not. &lt;br /&gt;e.g. &lt;br /&gt;&lt;pre class="code"&gt;if (user.jsSupportLevel&gt;1){&lt;br /&gt;   ... attach Ajax related event handlers ...&lt;br /&gt;} &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Example support levels&lt;br /&gt;&lt;br /&gt;0 = user-agent doesn't understand DOM (!document.getElementById)&lt;br /&gt;1 = user-agent DOM enabled&lt;br /&gt;2 = user-agent has native ajax support (window.XMLHttpRequest)&lt;br /&gt;3 = user-agent is probably a desktop browser&lt;br /&gt;&lt;br /&gt;You can use the above to deliver the appropriate level of JavaScript support to users, e.g. Don't implement any JavaScript if the support level is 0, only do very basic JavaScript for level 1, do pretty much everything for level 2 and level 3 is level 2 with transitions and opacity (stuff you wouldn't want on a mobile/hand-held). &lt;br /&gt;&lt;br /&gt;This will only work if your using progressive enhancement of course!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-5785078149356635177?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/5785078149356635177/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2009/03/javascript-support-levels.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/5785078149356635177'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/5785078149356635177'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2009/03/javascript-support-levels.html' title='JavaScript support levels'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-3254580045620214433</id><published>2009-03-19T03:19:00.000-07:00</published><updated>2009-03-19T03:54:10.032-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='browsers'/><title type='text'>Expression Web SuperPreview</title><content type='html'>Having a play with &lt;a href="http://blogs.msdn.com/xweb/archive/2009/03/18/Microsoft-Expression-Web-SuperPreview-for-Windows-Internet-Explorer.aspx"&gt;Web SuperPreview&lt;/a&gt; from good'ol Microsoft and I have to say i'm a little disappointed.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_2IOxbRFZS2c/ScIgzZbW47I/AAAAAAAAARE/FmmGSCItCw0/s1600-h/superpreview.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 238px;" src="http://4.bp.blogspot.com/_2IOxbRFZS2c/ScIgzZbW47I/AAAAAAAAARE/FmmGSCItCw0/s320/superpreview.png" border="0" title="screen shot of Web SuperPreview" alt="screen shot of Web SuperPreview" id="BLOGGER_PHOTO_ID_5314846577621656498" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It very  much aimed and a px by px comparison of two browsers, which in my experience is pretty much a waste of time. I've never had a support call were someone is upset about the look and feel being slightly different on a different browser.&lt;br /&gt;&lt;br /&gt;Focusing on minor UI display differences results in designers insisting on using graphic buttons and DHTML scrollbars and code forking in the CSS in order to achieve pixel perfect adherence to the visual design on various target browsers. Not a road that I want to go down. &lt;br /&gt;&lt;br /&gt;I think I'll be sticking to &lt;a href="http://www.my-debugbar.com/wiki/IETester/HomePage"&gt;IETester&lt;/a&gt; and VMs, for now anyway.&lt;br /&gt;&lt;br /&gt;Also, i may be missing something blatantly obvious but I couldn't workout how to trigger a control or even follow a link in the preview panel so couldn't inspect any dynamic page elements. I assume that's just me being a twat. The product would have no value at all if you can't interact with the page, but it's not immediately obvious how you do (well, not to me anyway!! : ).&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Related links...&lt;/h2&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.sitepoint.com/blogs/2009/03/19/microsoft-superpreview-website-tester/"&gt;http://www.sitepoint.com/blogs/2009/03/19/microsoft-superpreview-website-tester/&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.sitepoint.com/blogs/2008/12/04/adobe-meermeer-will-change-the-way-you-test-web-sites/"&gt;http://www.sitepoint.com/blogs/2008/12/04/adobe-meermeer-will-change-the-way-you-test-web-sites/&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.my-debugbar.com/wiki/IETester/HomePage"&gt;http://www.my-debugbar.com/wiki/IETester/HomePage&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://browsershots.org/"&gt;http://browsershots.org/&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-3254580045620214433?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/3254580045620214433/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2009/03/expression-web-superpreview.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/3254580045620214433'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/3254580045620214433'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2009/03/expression-web-superpreview.html' title='Expression Web SuperPreview'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_2IOxbRFZS2c/ScIgzZbW47I/AAAAAAAAARE/FmmGSCItCw0/s72-c/superpreview.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-3550850112667230586</id><published>2009-03-08T07:26:00.000-07:00</published><updated>2009-09-20T03:55:48.118-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='accessibility'/><title type='text'>Icons and image replacment</title><content type='html'>Generally speaking i'm not a fan of image replacement, but for inline icons it seems to work a treat. We had this issue that users with screen readers where struggling with our icons that we use liberally in our pages. For example, the "More information" icons that we use on some links to indicate that there is more detailed information available, looks something like this.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://pclancey.com/i/btf/iconreplacement/link1.png" alt="Image of an internet link with an icon" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://pclancey.com/i/btf/iconreplacement/moreicon4.png" alt="HTML view of anchor link code, containing an img tag" /&gt;&lt;br /&gt;&lt;br /&gt;Although this looks quite reasonable it was causing problems for screen readers as they list out all images which means the user will get a list of images all saying "More information" (so a bit like having a list of links all saying "Read more..."). This is a problem with using images as text (an icon is really short hand text) if you look at them out of context they don't make sense.&lt;br /&gt;&lt;br /&gt;Using image replacement as a way of hiding images from screen readers works quite well, as they are background images and not img tags. If we look at the same link using image replacement...&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://pclancey.com/i/btf/iconreplacement/moreicon3.png" alt="HTML view of anchor link code, containg image replacement code" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I tend to use nested spans for image replacment, you may prefer to use a single span with a combination of overflow hidden and a text-indent value, depends what browser support your after. If you don't need backwards compatibility you could just use the CSS "content" property instead.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-3550850112667230586?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/3550850112667230586/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2009/03/icons-and-image-replacment.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/3550850112667230586'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/3550850112667230586'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2009/03/icons-and-image-replacment.html' title='Icons and image replacment'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-4354695930455874899</id><published>2009-03-03T13:49:00.000-08:00</published><updated>2009-03-05T13:47:22.359-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='browsers'/><title type='text'>Are DOM browsers the edge case?</title><content type='html'>&lt;P&gt;I think the answer might be Yes. &lt;/P&gt;&lt;P&gt;You want your application to work on the web so you write it to output semantic HTML, if you do this without using script (or noscript tags) your site should work on pretty much any browser that understands HTML regardless of platform, OS, browser version etc... that's quite a lot of different user-agents running on, mobiles, iTV, games consols, PCs etc... A subset of these user-agents will understand javascript to some degree, and a sub-set of these will understand DOM. If you then think of DOM browsers as a edge case (albeit an improtant one) everything falls into place.    &lt;/P&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-4354695930455874899?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/4354695930455874899/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2009/03/are-dom-browsers-edge-case.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/4354695930455874899'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/4354695930455874899'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2009/03/are-dom-browsers-edge-case.html' title='Are DOM browsers the edge case?'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-1870679330032281972</id><published>2009-02-27T14:08:00.000-08:00</published><updated>2009-03-31T07:33:34.847-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='accessibility'/><title type='text'>Is the NoScript tag the tag of the devil?</title><content type='html'>&lt;p&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 103px; height: 110px;" src="http://1.bp.blogspot.com/_2IOxbRFZS2c/SdIoOVrfnkI/AAAAAAAAARM/rVBw7Chz9YI/s320/noscript.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5319358336680828482" /&gt; I came to the realisation today that the noscript tag is the sporn of the devil. It encourages developers to think of JavaScript in black and white, it's either on or off, the users support it or they don't. Unfortunately this simplistic approach can leave your users frustrated and thinking your site is broken. Consider this over heard conversation...&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;Project manager:&lt;br /&gt;&lt;blockquote&gt;"Why doesn't the site work on my Blackberry?"&lt;br /&gt;&lt;/blockquote&gt;Developer:&lt;br /&gt;&lt;blockquote&gt;"We don't support the Blackberry"&lt;/blockquote&gt;Project manager:&lt;br /&gt;&lt;blockquote&gt;"but I thought you said it works without CSS and JavaScript?"&lt;br /&gt;&lt;/blockquote&gt;Developer:&lt;br /&gt;&lt;blockquote&gt;"yes it works fine without CSS and JavaScript, we've built it in semantic HTML"&lt;/blockquote&gt;Project manager:&lt;br /&gt;&lt;blockquote&gt;"so it should work on anything that understands HTML?"&lt;/blockquote&gt;Developer:&lt;br /&gt;&lt;blockquote&gt;"... yes ..."&lt;/blockquote&gt;Project manager:&lt;br /&gt;&lt;blockquote&gt;"so why doesn't it work on the Blackberry??"&lt;/blockquote&gt;Developer: ".... err ....&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The NoScript tag has struck, pretty much all user agents support JavaScript. Much better to use progressive enhancement instead. &lt;br /&gt;&lt;br /&gt;Consider this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;&amp;lt;noscript&amp;gt;&lt;br /&gt;&amp;lt;p&amp;gt;&lt;br /&gt;  Important information for users without JavaScript&lt;br /&gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&amp;lt;/noscript&amp;gt;&lt;br /&gt;&amp;lt;script type="text/javascript"&amp;gt;&lt;br /&gt;if (document.&lt;span&gt;getElementById&lt;/span&gt;){&lt;br /&gt;  &lt;span class="comment"&gt;// do funky things &lt;/span&gt;&lt;br /&gt;  ...&lt;br /&gt;}&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We have just created a crack down the back of the sofa which has swallowed every user-agent that supports javascript but doesn't support document.getElementById or doesn't get the JavaScript in the first place. These users don't get the JavaScript enhancement and they don't get the noscript fallback : (&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-1870679330032281972?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/1870679330032281972/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2009/02/is-noscript-tag-tag-of-devil.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/1870679330032281972'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/1870679330032281972'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2009/02/is-noscript-tag-tag-of-devil.html' title='Is the NoScript tag the tag of the devil?'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_2IOxbRFZS2c/SdIoOVrfnkI/AAAAAAAAARM/rVBw7Chz9YI/s72-c/noscript.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-918150338546291362</id><published>2009-02-24T01:42:00.000-08:00</published><updated>2009-12-08T09:02:34.057-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>Are images enabled?</title><content type='html'>If your not sure what image replacement is, it's  a technique to replace a bit of text (often an H1 level header) with an image. It's not really a very good idea, for one thing it creates a no fall back situation, e.g.  you hide the text and put in a nice background image, which, if images are disabled the user can't see (oops!) and since it's a background image there is no alt text, hence no fall back, just an empty space.&lt;br /&gt;&lt;br /&gt;So what to do? Using progressive enhancement you wouldn't want to implement something unless you know it's supported, you can use JavaScript to test if images are enabled and then add a class name to the html tag is one way to go. &lt;br /&gt;&lt;br /&gt;Browsers seem to fall into two camps when images are turned off. Ones that don't load images at all and ones that load all img tags with an empty image. So you need to create two tests, first attach an onload function to an image you know exists, this will not fine on browsers that don't load images at all.&lt;br /&gt;&lt;br /&gt;e.g...&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;var existentimg = new Image;&lt;br /&gt;existentimg.onload = function(){&lt;br /&gt;  // if this didn't fine, images aren't enabled&lt;br /&gt;}&lt;br /&gt;existentimg.src = "know_to_exist.png";&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;As the above will fire on browsers that load images when images are disabled you need to do the same test again but this time attach the onload to an image you know does not exist.&lt;br /&gt;&lt;br /&gt;e.g...&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;var nonexistentimg = new Image;&lt;br /&gt;nonexistentimg.onload = function(){&lt;br /&gt;  // if this fires, images are disabled&lt;br /&gt;}&lt;br /&gt;nonexistentimg.src = "/nonexistent.gif";&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I've put an example function at the bottom of this page that combines the two functions.&lt;br /&gt;&lt;br /&gt;What to do with the info when you have it? Once you know if the user-agent has images enabled you can add a class name (e.g. "img") to the HTML tag, this will provide a way of using the information in your CSS.&lt;br /&gt;&lt;br /&gt;e.g...&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;/* these styles will only be implemented if images are enabled */&lt;br /&gt;html.img h1 {background-image:url(H1.png);width:XXXpx;height:XXpx;}&lt;br /&gt;html.img h1 span {position:absolute;left:-9999px;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Anonymous JavaScript function example, run this on DOM ready&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;(function(existingimageurl){&lt;br /&gt; var existentimg = new Image;&lt;br /&gt; existentimg.onload = function(){&lt;br /&gt;  document.getElementsByTagName('html')[0].className+= " img";&lt;br /&gt;  var nonexistentimg = new Image;&lt;br /&gt;  nonexistentimg.onload = function(){&lt;br /&gt;   document.getElementsByTagName('html')[0].className = document.getElementsByTagName('html')[0].className.replace(/\bimg\b/,"");&lt;br /&gt;  }&lt;br /&gt;  nonexistentimg.src="/nonexistentimg.png";&lt;br /&gt; }&lt;br /&gt; existentimg.src = existingimageurl || (document.images.length?document.images[0].src:'http://www.google.co.uk/images/nav_logo.png');&lt;br /&gt;})();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If your using jQuery (or something similar) and you know there is at least one image on your page...&lt;br /&gt;&lt;br /&gt;&lt;pre class="code"&gt;&lt;br /&gt;$(document).ready(function(){&lt;br /&gt;(function(){&lt;br /&gt; var existentimg = new Image;&lt;br /&gt; existentimg.onload = function(){&lt;br /&gt;  $('html').addClass('img');&lt;br /&gt;  var nonexistentimg = new Image;&lt;br /&gt;  nonexistentimg.onload = function(){&lt;br /&gt;   $('html').removeClass('img');&lt;br /&gt;  }&lt;br /&gt;  nonexistentimg.src="/nonexistent.gif";&lt;br /&gt; }&lt;br /&gt; existentimg.src = document.images[0].src; &lt;br /&gt;})();&lt;br /&gt;})&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-918150338546291362?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/918150338546291362/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2009/02/are-images-enabled.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/918150338546291362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/918150338546291362'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2009/02/are-images-enabled.html' title='Are images enabled?'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-277055053587992327.post-1486549756736032103</id><published>2009-02-21T13:37:00.000-08:00</published><updated>2009-03-04T06:08:36.859-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='accessibility'/><category scheme='http://www.blogger.com/atom/ns#' term='UI'/><category scheme='http://www.blogger.com/atom/ns#' term='HTML'/><category scheme='http://www.blogger.com/atom/ns#' term='interface development'/><title type='text'>JavaScript support, who does, who doesn't?</title><content type='html'>JavaScript or lack of is a thorny issue, but if we take a quick look at some of the user groups that this effects:&lt;br /&gt;&lt;br /&gt;1: User agents that don't have JavaScript enabled. As a lot of user tracking software relies on JavaScript to work so it's hard to tell how many users actually don't have JS, but in the beginning of 2009 it could be &lt;a href="http://www.thecounter.com/stats/2009/January/javas.php"&gt;about 6%&lt;/a&gt;. Made up of user-agents that don't support JS, user-agents that have it turned off as part of company policy and user-agents routed though a proxy (e.g. public proxies normally don't support JavaScript)&lt;br /&gt;&lt;br /&gt;2: User-agent that you haven't tested your JavaScript on. Just because a user-agent supports JavaScript doesn't mean your script will work (ever done this: if (!document.getElementById){return} ? ), even the four (webkit/moz/opera/ie) main desktop browsers diverge radically in some areas, meaning that there is a good chance that you scripts may not work on anything you haven't tested them on.&lt;br /&gt;&lt;br /&gt;3: User-agents where your script is meaningless. e.g. if the user is using a small screen (or zoom software) and they click on a DHTML link that moves some page content from out of view left (eg. margin-left:-9999px) to out of view right (e.g. margin-left:800px;). In these cases JavaScript is no help to the user.&lt;br /&gt;&lt;br /&gt;4: Assistive technologies: Most assistive technologies like screen-readers run on the top of your normal browser so although the browser understands JavaScript the assistive technology may not. They may not see things you have written in with JavaScript rendering your JavaScript content inaccessible.&lt;br /&gt;&lt;br /&gt;There are probably other user groups effected, will add when they come to mind...&lt;br /&gt;&lt;br /&gt;So our user groups fall in to a number of categories...&lt;br /&gt;&lt;br /&gt;1. users with browsers that don't support JavaScript at all, or have JavaScript turned off&lt;br /&gt;2. users with browsers can't run your scripts (they error or don't support DOM)&lt;br /&gt;3. users accessing your site though anal proxy, firewall etc...&lt;br /&gt;4. users for whom your JavaScript is redundant (not really any help)&lt;br /&gt;5. users for whom your JavaScript is actively blocking access to content&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/277055053587992327-1486549756736032103?l=beneaththefold.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beneaththefold.blogspot.com/feeds/1486549756736032103/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://beneaththefold.blogspot.com/2009/02/javascript-support-who-does-who-doesnt.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/1486549756736032103'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/277055053587992327/posts/default/1486549756736032103'/><link rel='alternate' type='text/html' href='http://beneaththefold.blogspot.com/2009/02/javascript-support-who-does-who-doesnt.html' title='JavaScript support, who does, who doesn&apos;t?'/><author><name>patrick</name><uri>http://www.blogger.com/profile/09834663950926240564</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://1.bp.blogspot.com/_2IOxbRFZS2c/SaHUFqi39II/AAAAAAAAAQg/2YXPREme228/S220/dad.png'/></author><thr:total>0</thr:total></entry></feed>
