Amazon’s Pure CSS Solution to Avoid Cutting Off Text

Amazon is using a nice CSS trick to truncate a text block without showing half-lines (like someone cut the document horizontally). The problem is that CSS “overflow: hidden;” is a crude creature that will brutally cut lines off halfway through like a 1970s dot-matrix printer. There’s no “overflow hidden, but jeez be gentle about it okay” property. So this is a workaround, but it does impose a change on the UI…the fading text on the bottom.

Using Devtools for the image below, I’ve enhanced the mask with outline and gradient colour, and also filled the block with text to build a continuous paragraph on the bottom.

There’s a semi-transparent gradient mask in front of the content. The mask is mostly clear, but has a white band on the bottom 15%. This band is turquoise for illustration purposes here. So this bottom band covers up text on the next line without occupying too much whitespace. You’ll notice the band starts where the bottom line ends. So the bottom line is already fading, and then BOOM! It’s all white below that.

The mask is 50 pixels, so there will be about 45 pixels (85% of 50px) transition from full text to fully-transparent text, followed by about 5 pixels of white.

A side note is the layout technique for the mask. Probably basic for most CSS designers, but not how I would have done it. It’s simply using standard flow, but with position: relative to shift the mask up 50px, and a 50px negative margin to ensure the mask doesn’t actually affect the flow. (I would have done it by making the whole thing position relative, and absolute elements inside it. This technique is much simpler.)

I found this technique via StackOverflow a little while ago, as mentioned here earlier, so I was chuffed to spot it in the wild, and on Amazon no less.

Update: Syd Lawrence points out that it’s worth using pointer-events: none on the mask. This is the CSS property that makes the front layer porous, allowing mouse clicks to cheekily slip through to the element behind it.

Whereupon HTML5 Doctype Messes with My Layout (and my head)

TL;DR Use “5px” in your CSS, not just “5″. It will be ignored with HTML5 doctype.

About to release my favicon tool and did the right thing with a <!doctype html>, which in Jade is simply !!! 5. I previously had no doctype.

Okay, but then I get some weird happenstance going down with the CSS. And Chrome devtools smugly crossing out style rules without telling me what’s actually the matter. (For reasons having to do with the absurd time it takes to open a UK business bank account and my general lack of enthusiasm for paperwork, I’m currently using a computer so slow it’s not economical to try this in Firebug.)

It took me a while to track down as I thought I’d made some other change in the meantime and simply didn’t put it down to impulsively changing the doctype at some random moment of inspiration.

Specifically, I found with Chrome 14 at least that CSS needs a unit of measurement. You can’t just say “5″, you have to say “5px”. I was actually saying “5″ and assuming Stylus would translate it to 5 pixels. Serves me right anyway for using absolute measurements and now I’ve updated everything to use “em” units.

I also discovered negative padding is not possible (regardless of doctype). And I agree with Aza, that sucks. There’s definitely cases where it would save work and avoid adding wrapper elements just for the sake of it.

Simple Labels for HTML5 Slider (Input Type = Range)

For a favicon tool I’m working on, I tried using an HTML5 slider for the first time and was surprised to learn there’s no labels. Looked at a couple of shims out there, but they are just shims and don’t include labels either. So d-i-y …

The slider looks as below, and the CSS doesn’t make any assumptions about length of the slider or the two labels.

The labels are generated using the old margin 50% wrapper trick, as you can see in the following Jade markup and Stylus CSS:

input.rangeOption(type="range",min="0",max="1",step="0.1",title="Transparency: 0 to 1")
  .labels
    .minLabel
      span solid
    .maxLabel
      span transparent

  1. .rangeOption
  2.   float left
  3.   margin-left 2em
  4.   input
  5.     display block
  6.   .minLabel
  7.     float left
  8.     span
  9.       margin-left -50%
  10.   .maxLabel
  11.     float right
  12.     span
  13.       margin-left 50%

“Classy HTML”: A Speculative Design Pattern about Classes and Composition

This is a pattern about Classy HTML.

Classy

ooo posh

No, not THAT “Classy”. This “Classy”:

HTML

No, not THAT “HTML”. This HTML:

The Classy HTML Pattern

Pretty simple: Store important app state as classes in your root (“html”) element.

For example, consider a countdown app. Its significant (from a UI perspective) state can be summed up as being one of three things: “fresh” (app just started), “counting”, “done”. Your app is, in effect, a state machine transitioning between those states according to a set of rules. (Acknowledging that reality and subsequently managing those state transitions with JavaScript can also be an interesting problem ripe for a parsimonious design, but let’s just take that for granted here.)

You would set your HTML class as “fresh” to begin with, and then programmatically switch it over to “counting” or “done” as the app plays out.

Your CSS reflects it:

  1. /* We choose the default case to reflect the most common case, ie "counting" or "done" */
  2. html.fresh .welcomeMessage { display: none; }
  3.  
  4. html.fresh { background: white; }
  5. html.fresh .counter { opacity: 0.3; }
  6.  
  7. html.done { background: red; }

The important thing here is the selector idiom, which can be summed up as “html.state descendentSelector“. We’re styling our classes all the way down, based on the overall application state.

I haven’t done too much of this kind of design, but I can see myself doing more of it as apps get more complex and everything becomes single-state. I’ve been contemplating refactoring the Hacker News Reader along these lines, since (thanks mostly to Paul), it now has sliding panels, and so can effectively be in three states: stories, story (one story above the list of stories), comments (comments above one story above the list of stories).

I guess all this is obvious to CSS design pros, i.e. it’s a natural consequence of the CSS model, but I’ve not thought about doing it much and I mainly got the idea from this FOUC trick, which uses this pattern, but in a very restricted and specific way. The main insight really is that single-page apps usually have a small number of key states which can affect the entire UI.

As with any good pattern, it raises further questions:

  • Should you use “class” or an HTML5 custom “data-something” attributes. I think it’s in the spirit of HTML/CSS to use “class” to represent a state, so that’s fine. And CSS attribute-based support won’t work on older browsers, so that’s another tick for “class”. BUT custom attributes have the distinct advantage that you can be more precise about what kind of state you’re referring to. So while it could just be “data-state”, it could also be “data-phase” or (a boolean) “data-active”. Which takes us to the next question …
  • Should you use more than one type of state? I think for complex apps, yes. And you can then use custom data attributes to manage the type of class. Or you could just use them as a list of free-floating class names on the HTML tag.
  • Should you use multiple selectors, e.g. [data-phase="counting"][data-authenticated="false"] to be more precise? In general, I think no. It would lead to ridiculous combinatorial complexity, so it’s better to treat each state variable – if you must have more than one of them – as being orthogonal. That said, there are probably special cases where it makes sense and fortunately modern CSS makes it easy to pull off.
  • What’s the base case? Should it be the initial state or the “typical” state?
  • Looking at the bigger picture, when do you switch pages versus switch states inside the app?

Is this what the App of 2015 looks like? HTML5 + CoffeeScript + Less + WebStore + PhoneGap + Apparatio

My weekend project was a Hacker News Reader (source code). It works on Chrome, Safari, and Opera. Sorry, Firefox doesn’t work at present, reasons why speculated below. Mostly started this project because I want one with Twitter integration, but also to play with a few technologies, which I did. Among things explored and demonstrated:

  • Server-Less App The app is entirely browser-side. The server serves only as a repository of static files. Content comes from the iHackerNews unofficial API, by way of JSONP, the protocol we’ll still use for cross-domain calls until CORS becomes eminent in the hopefully not-too-distant future.
  • CoffeeScript. The app logic is written in CoffeeScript, and compiled to JavaScript in the browser with coffee-script.js.
  • Less. The UI styling is written in Less and compiled to CSS with less.js.
  • Chrome Web App. The app is also a hosted web app on the Chrome Web Store, which is to say (a) it can be discovered by users of the store; (b) it can be installed into the New Tab page of Chrome, for convenience sake; (c) if I wanted to, and added some extra server smarts, I could charge for it. I wrapped it up as an app with Paul’s super-handy Appmator utility.
  • Mobile HTML5. Although I didn’t (yet) optimise the site for HTML5, I did make it available on mobile, with the right icons for being added to the Home Page, and used Build.PhoneGap.com and Apparatio to roll it up as a native mobile app.

CoffeeScript

I wanted to try out CoffeeScript. While I’ve been skeptical about languages which are said to “compile down” to JavaScript, as if JavaScript was a complicated tangle of 1s and 0s rather than the high-level language it is…CoffeeScript is different. It’s more like JavaScript++ as the name implies. While I do find JavaScript to be pretty good, its syntax can get too verbose. Especially for closures, where you have too many curly braces and “function” keywords getting in the way of the actual logic we care about. You can also be more expressive with keywords like “unless”.

As ~98% of code people write never sees high-scale production use, I like to opt for quick and dynamic over tedious and “it just feels like the right way to do it”. So I employed coffee-script.js to compile dynamically, in the browser when the web app loads, instead of pre-compiling it on the command-line. Doing it dynamically means I can just type some code and reload the browser page, about the smallest possible debug-test cycle that is possible.

I found it slow-going at first, because I ran into some coffee-script.js gotchas and learned a few things about the language on the way:

  • Keep CoffeeScript in a separate server. Although CoffeeScript supports inline CoffeeScripts in your HTML (<script type=”text/coffeescript”>…here is my script….</script>) – perfect for quick hacking), I recommend you stick them in a separate file (<script type=”text/coffeescript” src=”myscript.coffee”></script>. I can’t explain exactly why, but when it was inline, things were note very deterministic and I found my CoffeeScript script was getting executed three times!
  • Use a server, not file:/// URIs. As with less.js, CoffeeScript mocks the browser’s script-downloading behaviour, using XMLHttpRequest to pull down any scripts specified in “text/coffeescript” script tags. Unforuntately, Chrome doesn’t let you XHR one file from another file, so you need to set up a server, if only to serve these static files over HTTP.
  • Don’t bother with window.onload (or jQuery intializer). I *think* coffee-script.js guarantees any CoffeeScripts you provide will be executed after the window has already loaded. I haven’t confirmed this, but seems to be that way on Chrome, Safari, and Opera. OTOH, the app doesn’t work on Firefox – CoffeeScript isn’t executed at all – and this may be related.
  • Declare before you use. A consequence of the previous rule is that your initialisation sequence will run in the order you specify it. This is different to the usual JS situation where you make a window.onload handler, which might call things that you’ve declared further down in the file. So in the code further down, note that I declare “show” before I call it. Pretty obvious, but JS habits and lack of descriptive error messages meant it caught me out.
  • Whitespace matters. There are no semi-colons and no braces here; similar to Python, whitespace dictates structure. However, you can also use parantheses to keep things on the same line, so I didn’t find this threatening to concise code.
  • Use “window” for global. Declarations like “x=5″ out in the open will *not* make global variables; and nor is there a “var” keyword. The only way to hook into global space is to explicitly reference the “window” object; e.g. “window.x = 5″.

How’s the code look? See for yourself, CoffeeScript keeps it pretty tight. I couldn’t find many examples of jQuery-CoffeeScript combos, so this will hopefully be useful in that regard:

javascript
< view plain text >
  1. storiesTemplate = _.template($("#storiesTemplate").html())
  2. show = () ->
  3.   $.getJSON "http://api.ihackernews.com/page?format=jsonp&callback=?",
  4.     (storyInfo) -> $("#stories").fadeOut () ->
  5.       $(this).html(storiesTemplate(storyInfo))
  6.       $(this).fadeIn()
  7.  
  8. show()
  9. setInterval show, 10*60*1000
  10.  
  11. $(".story").live "click", (ev) ->
  12.   return if $(ev.target).closest("a").length
  13.   window.open($(".url", this).attr("href"), "hackernews"+Math.random());

  • Less fails silently. Unfotunately, you don’t get error messages, so develop things gradually and be prepared to undo.

Less

If I was going to take a sip of CoffeeScript, it would only be fair to munch on a slice of Less too. If CoffeeScript is JavaScript++, then Less is CSS+. It’s really augmented CSS, because you can present a regular CSS stylesheet and it will be valid Less too. That’s not true at all about CoffeeScript; a typical JavaScript script has Buckley’s of passing the CoffeeScript compiler.

The other thing they have in common is JavaScript compilers. Which is not the case with SASS for instance.

Less talk:

  • Same XHR issues. As with CoffeeScript, the Chrome cross-domain restriction means you have to use a server even though the files are static. Also, it doesn’t seem to be possible to include Less stylesheets inline, or to get hold of the less compiler, which I think is a shame if true.
  • Silent fail. If any Less doesn’t parse, the entire stylesheet won’t be applied, and there’s no error message.

So some downsides, but the upside was a cleaner stylesheet with less redundancy. Gradient macro makes the ridiculously verbose gradient declarations completely DRY:

  1. /*****************************************************************************
  2.    MACROS
  3. *****************************************************************************/
  4. .linearGradient(@color1:#ccc, @color2:#ddd) {
  5.   background-image:-webkit-gradient(linear, left bottom, left top, color-stop(0, @color1), color-stop(100%, @color2));
  6.   background-image:-moz-linear-gradient(center bottom, @color1 0, @color2 100%);
  7.   background-image:-o-linear-gradient(center bottom, @color1 0, @color2 100%);
  8.   background-image:linear-gradient(center bottom, @color1 0, @color2 100%);
  9.   background-color: @color1;
  10. }
  11. .postedBy:hover, .commentsLink:hover span { .linearGradient(#fa0, #f80); }

Elements can be nested in their parent selectors:

  1. .commentsLink,.commentsLink:visited {
  2.   position: absolute; top: 50%; right: 1em; height: 1em;
  3.   ...
  4.  
  5.   span {
  6.     ...
  7.     border-radius: 0.3em;
  8.   }
  9.  
  10. }

… and so can pseudo-selectors:

  1. .story {
  2.   padding: 0.5em 9em 0.5em @leftIndent;
  3.   border: 1px solid black;  border-bottom-width: 0;
  4.   background: #fff6f6;  cursor: pointer;
  5.   position: relative;
  6.  
  7.   &:hover { .linearGradient(#fc0, #fa0); }
  8.  
  9.   &:last-child { border-bottom-width: 1px; }
  10.    
  11. }

And you can do cross-browser CSS calculations today:

  1. .commentsLink,.commentsLink:visited {
  2.    ...
  3.   margin-top: -0.5em-@commentsLinkPadding;
  4.  
  5.   span {
  6.     ...
  7.     padding: 0em + @commentsLinkPadding;
  8.   }
  9.  
  10. }

Chrome Web Store

This is a full-screen, focused, app which therefore meets the criteria for Web Apps I outlined in Thinking In Web Apps. (It would be more so if it showed the actual stories and comments in the app too, but that’s something for later.)

So it made sense to submit to the Chrome Web Store. Fortunately, my colleague Paul Kinlan had the gall to attempt building a web app that packages up Chrome apps … and then he actually pulled it off! Appmator asks you for the address of your web app, asks a few other basic questions, and then makes a Zip file you can drag to your desktop and upload to the store. All in all, a 30 minute submission to the Chrome Web Store and a nice way for people to discover your web app. I would only recommend this for true “Apps” as opposed to general websites, and ideally those apps should be tailored to a full-screen experience.

Anyway, it’s on the store now – Hacker News landing page.

PhoneGap, PhoneGap Build, Apparatio

The app is NOT optimised for mobile at this time, but the cool thing about HTML5 is, for the most part, it “just worked” when I pointed iPad and Android phones to it. Some things need improvement, but this is good to see.

For exploration purposes, I decided to build it as a native mobile app anyway. I was lucky enough to receive beta invites for PhoneGap Build and Apparatio, two web services which let you do PhoneGap without actually installing anything on your PC. I built this app with both products.

Apparatio, which I used previously, worked nicely and I was able to get a native Android app.

PhoneGap Build supports GitHub like Apparatio, but also allows uploading a zip file. I actually had a problem pointing it at my GitHub repo (as with Apparatio, it needs to provide clearer instructions on exactly what form of URL is required). After I uploaded the zip file, it showed me a dashboard of 4 packages being built, and just went ahead and built each of them. Nice and simple!

Android, WebOS, Symbian, Nokia. Conspicuous by its absence is iOS, which Apparatio does support.

DropBox on my Macbook and Galaxy made it easy to copy the APK downloads to my Galaxy and install it. The Apparatio one took some time to download initially, but worked fine. The

Other Notes

Block-level “a” element, NOT. HTML5 makes it possible for “a” elements to be block-level, i.e. to include other tags including other “a” elements. This would be ideal for the Hacker News Reader UI, where the entire story block is a link to the story itself, but the block also contains links to comments and authors. It turned out to be legal in modern browsers, but with blatantly wrong layout, as someone else found earlier. Shame as I had to introduce considerably more JavaScriptCoffeeScript and CSSLess.

InnerHTML, Templating, and Live(). Seems like every project I do these days, I’m building dynamic content with innerHTML, as opposed to DOM manipulation. The first reason is I’ve become accustomed and satisfied with templating, and see it as a growing trend thanks to language-agnostic formats like Mustache as well as server-side JavaScript. (Though in this case, it’s a pure browser-side app.) So make a template and stick it on the page with innerHTML (or jQuery’s .html() ). The second reason is jQuery’s live() command makes it easy to handle events against the newly formed elements, which was previously a pain with innerHTML().

Setting text size. As you can see, text size varies with the number of points a story has. The relevant line appears in the template:

font-size:<%= Math.log(Math.log(Math.max(s.points,10))) %>em;

Using a log scale ensures a story with 2000 points isn’t 2000 times bigger than a story with 2 points. To dampen the effect further, which I think is important in mobile displays, I used a double-log and applied a minimum threshold of 10 points.

Future Things

There was actually an itch to be scratched here, beyond trying out various tech. Specifically, I’ve been wanting a mobile HN reader that would: (a) tweet; (b) quickly mark for instapaper reading, and ideally when I’m offline. (It would show the latest stories it saw when online, and cue them up for later…in general, I wish more offline apps would support cueing things like Tweets and Read Laters for when you’re back online.)

Fin.

So is this the Web App of 2015 or not?

There are definitely elements here that are not in wide use now, but will be in wide use by 2015. The whole “write once, run many” aspect of HTML5 is just getting wheels. It’s now clear that Apple won’t dominate the landscape by 2015, so regardless of their ever-fluctuating stance, HTML5 will be able to power the apps of the majority of smartphones and tablets…not to mention the possibility of apps on TV, cars, watches, washing machines, etc etc etc. (Can you tell it’s been CES week?)

And with HTML5 being able to power these apps, we’ll need ways to fit them into the App ecosystem, and that’s where PhoneGap and friends fit in. As I’ve said in various places, I always found it painful to have to set up Eclipse, PhoneGap SDK, and so on just to make a native app from HTML5. These are the things HTML5 developers don’t want to do, and the PhoneGap team is well aware of it, hence their PhoneGap Build effort. Apparatio provides relief in the same way and we can expect the same from others, especially so in light of Heroku’s high-valuation acquisition bringing attention to the whole idea of cloud programming. GitHub is also a vital component of this vision becoming reality. The next step will be to automate deployment into the stores, hopefully something that app-hungry stores will be happy to facilitate.

The Chrome Web Store is a related concept aiming to “app-ize” we apps. Mozilla is investigating a similar idea, and we’ll see a lot more of it in the next few years too. Some people say “but it’s just a bookmark”, an understandable reaction, but I think people are starting to get it now. It should only be an app if it really is an app, ie. if the underlying URL is really a media-rich, focused, app rather than a big collection of information and hyperlinks. And the Web Store is not just a place where you can buy and install apps; it’s also a directory where you can find all the cool apps on the web, with screenshots and reviews and comments to help you decide if they’re worth trying out.

Offline is important in the app story too (although this app doesn’t (yet) do any offline). You don’t type in URLs when you’re on a plane, but you do click on app icons to launch them. So offline web apps need an app-like presence to meet user expectations.

How about those languages, CoffeeScript and Less? CoffeeScript seems promising and I’ll definitely be using it more. At the same time, I’m weary because I feel like JavaScript may be “good enough” and CoffeeScript becomes a maintenance problem if others need to see your code. But the leap is not a big one.

As for Less, I’m more convinced it’s the way to go. We nowadays have an absurd proliferation of “-webkit-” “-moz-” “-o-” “-msie-” prefixes and the various syntaxes to go with them. It’s for good reason, but it’s also as much an affront to the DRY principle as any agilist could ever fear, and it’s unfortunate the standards don’t provide better support for dealing with this sort of thing. Likewise, the need for variables/constants and calculations. Less allows for all of that, and in a way that will work on legacy browsers even when some of these features do come about. So, yes, I’ll be committing to Less in the future.

What’s very cool about both Less and CoffeeScript is the JavaScript frameworks. It’s ideal for starting off a project, and when performance gets to be an issue, you can easily switch to the compiled version after that.

Finally, I’ll mention that templating is a design pattern that’s also going to be big in 2015. There’s much more framework support these days and it’s easy to use the same templates on the browser and the server.

Events Last Week: Web Fonts, Social Design Patterns, BT Dev Day, Real-Time Javascript

Last week saw a confluence of excellent events. In the same week as a house move, it proved to be a week of much learning and little sleep. I’d hoped to do a better write-up, it never happened, a combination of being too busy and new MAC BATTERIES SUCK, meaning the lappy couldn’t last through the whole session. But fortunately, I have some links to point to. Here’s a quick summary anyway, along with the linkage.

Web Fonts at London Web Standards

@otrops captured the live notes in glorious detail, as did Rob Crowther.

Ben is ideally placed to cover the brave new world of web fonts, being a web maker who studied fonts at uni. He walked us through the evolution of font hacks on the web: image with alt tag; CSS background image with text pushed off the page; rendering with Flash (SiFR); rendering with Canvas or SVG (Cufon, TypeFace.js), using JSON-based font spec data. It all leads up to the holy grail: @font-face.

Great, so we have @font-face, but issues remain: * The foundries – Mark Pilgrim, in no uncertain terms, complains the font vendors are stuck in the dark ages of the printing press, in their resistance to support @font-face. This seems to be changing with WOFF, a web-only format that seems to placate the foundries, who worry their fonts will be stolen. It seems more like a symbolic gesture, since the data could still be converted and in any event the print fonts could still be appropriated, but the foundries are feeling more reassured and making signs they will go along with it. * Performance issue – Bandwidth issues and Paul Irish’s “flash of unstyled text”, where the user notices the font change once the fancy @font-face font has been downloaded. * Compatibility – IE has long supported font-face, but with EOT format fonts, and that remains the case. You therefore need both types of fonts, and licenses will generally not give you both.

Social Design Patterns

I was, needless to say, psyched about this. Yahoo! has been the closest thing to a realisation of the inspiring design pattern vision of the mid-late ’90s. Patterns on the web, for both its own employees and the wider community to learn from and evolve. These are social design patterns mined by Christian Crumlish (@mediajunkie), in many respect the closest thing software has to an analogy of building architecture, where design patterns originally came from.

There are 96 patterns in all and I’m looking forward to poring through them. In these patterns are hundreds of people-years’ experience of observing real-world social systems. In my own pattern work, I’ve found it necessary to articulate the overarching design principles behind the patterns. Pattern languages should be opinionated, so it’s a good thing to make explicit your criteria for filtering design features. Christian has followed this model too, and identified 5 overarching principles:

  • Paving the cowpaths. Facilitating the patterns that are already happening, rather than imposing your own invented process. Also means evolving with your users, ev dogster started as photo sharing but evolved to social network.
  • Talk like a person.
  • Play well with others. Open standards, mashups, etc. “if you love something, set if free”
  • Learn from games.
  • game UI concepts
  • designing the rules, but ultimately letting the people who come into the space finish the experience themselves.*
  • Respect the ethical dimension.

See the wiki or the book for more details.

BT Developer Day

This was an internal conference for BTers in London covering a range of general tech trends, and also being a chance to get together and talk shop. The agenda included talks on Scala, Rails, Kanban, iPhone development, and even a lightning talk from @psd on the horrors and delights of APL.

I gave a talk on Embracing the Web, emphasising open standards and the supreme primacy of Konami Cornification.

Real-Time Javascript

At the Javascript meetup, a great talk on NodeJS and WebSockets. NodeJS is coming on thick and fast, and Makoto Inoue showed how the technology plays nicely with WebSockets. WebSockets are all about Comet-style interaction, so expect to see a lot more of this combo in the next couple years.

Luis Ciprian, visiting from Brazil, gave us an overview of XMPP and talked us through a real-time web app – a basketball score and conversation tracker – using XMPP.

Fin.

What’s the Maximum Z-Index?

Z-index is the CSS property governing how high in the stack an element is, if you visualise the elements as appearing in a 3D stack coming out of the page. The actual value of an element’s z-index doesn’t matter; just its value relative to other elements on the page. Elements with higher z-indexes appear on top of elements of lower z-indexes.

I was just designing a bookmark for Scrumptious (a TiddlyWeb powered tool to have discussions around websites; I’ll talk about it in a future article). And with a bookmarklet, I need it to appear above everything else on the page. So it needs a higher z-index than everything else. Maybe not the highest z-index possible, since there might be apps that need to sit above my app’s bookmarklet (Design For Extensibility). But I still need to know the maximum z-index.

It would be nice if the standards publshed the maximum allowed z-index. Every reference always makes a comment like “there’s no real limit”. For good reason too, since the W3C standards don’t really cover this. The CSS Spec (2.1) goes so far as to include an “Elaborate description of Stacking Contexts”, and it’s even called “zindex.html”, but even here, omits to pin down the max z-index value.

A handy summary was stated on StackOverflow (which has fast become the central resource for programming FAQs and a site I have quickly come to adore for its clear mission, clean design, and community feel):

So basically there are no limitations for z-index value in the CSS standard, but I guess most browsers limit it to signed 32-bit values (−2147483648 to +2147483647) in practice (64 would be a little off the top, and it doesn’t make sense to use anything less than 32 bits these days)

Looking further, I came across the most comprehensive summary of the situation, published recently. It also highlights the fact that it’s not just the maximum value we want, but what happens if we exceed it.

I made a simple test page to find these limits and figure out what happens when you exceed them.

Browser Max z-index value When exceeded, value changes to:
Internet Explorer 6 2147483647 2147483647
Internet Explorer 7 2147483647 2147483647
Internet Explorer 8 2147483647 2147483647
Firefox 2 2147483647 *element disappears*
Firefox 3 2147483647 0
Safari 3 16777271 16777271
Safari 4 2147483647 2147483647
Opera 9 2147483647 2147483647

So the best way would be to use browser detection and pick the max from there. But if not, use 2147483647.

The official olympics medal tally is broken. Let’s fix it.

This is how the official olympics medal tally looks:

Overall Medal Standings - The official website of the BEIJING 2008 Olympic Games

It’s not only the official tally, but the one linked from google each time you type “olympics” and terms like “australia olympics”. Thus making it an absurdly popular page at this time. As you can see, the design is reedeeeculous. The thing you want to see the most – total medal tally – is several miles away from the country. It’s good they’ve used alternative shading for odd and even rows, but even so, it’s still difficult to see the connection. Especially since the gold/silver/bronze tallies are shown in a different colour.

Did you notice even “open/mixed” gets preferential treatment? Look, I can’t even think of an open/mixed event at the olympics. Ballroom dancing? Friendly game of trumps? All I’m saying is, I’d rather see the headline figures first. I don’t know how many gazillion dollars the official IT contract went for, but this is what the tally should look like according to table design 101:

Overall Medal Standings - The official website of the BEIJING 2008 Olympic Games

(BTW I also pulled total to the front and emphasised it. Matter of opinion whether to go by total number versus number of golds.)

(The following images are just to record the fact it’s linked from Google since it won’t be linked much longer.)

olympics - Google Search

australia olympics - Google Search

CSS Coding Style and the Unbearable Tendency for People to Adore Whitespace in their Source Code

CSS coding style doesn’t get a lot of play. Most people are happy to stick with the convention of one property per line, like this:

  1. #score {
  2.   background: yellow;
  3.   width: 12em;
  4.   border: 1px solid orange
  5.   padding: 2em;
  6.   margin: 3em 0;
  7.   display: none;
  8. }

I, for one, can’t stand that style. I’m heavily biased towards information-dense coding styles, which don’t have much whitespace. People mechanically argue “oh but whitespace is so important etc” as if we were designing a modern art installation. Well, whitespace is indeed essential, but you have to discriminate between a touch of elegant whitespacing for the sake of clarity, and “oh dear! My 80-column row seems to have just 12 characters on it. Come to think of it, every row on my 30-inch Cinema Display has 12 characters on it.” Seriously, I don’t know why anyone would use an 80-column terminal anymore, unless they enjoy coding on their iPhone. I tend to think 120 or 160 is ideal; any more than that and most people won’t be able to see the whole thing without moving their head. Anyway, I’ll be conservative and assume 80 columns. The average end column in the above code snippet is roughly 15, which means in your scrawny 1975 80-column terminal, you’re filling 20% of it with information and 80% with whitespace.

There’s an old figure that says the average programmer codes 10 lines per day. It’s obviously not a very accurate figure and maybe it was meant to include all the non-programmers on the project or something, but the point is interesting, as there’s probably some reasonably consistent LOC per developer figure (obligatory mutatis mutandis caveat). Seizing on this historical figure, Bruce Eckel said a while ago (paraphrasing) “if I only get 10 lines a day, I want them to be good ones”.

That’s why I favour information-dense coding styles. As a programmer, you’re supposed to be an expert user who spends all day in front of the same system. This is a typical example of a situation which demands a “Sovereign Posture”. It’s an expert system. When people long for glorious pastures of whitespace, they’re ignoring the fact that with sufficient practice, they’ll be virtually as proficient at reading and writing a more information-dense style, and vastly more efficient by having so much more code available at any time. It’s the same reason why Real Programmers commit to learning Unix and Vi or Emacs; if you’re going to spend decades working in this environment, why wouldn’t you spend a few days committing to the most efficient tools available?

For the record, I still have plenty of whitespace in my programs, but when there is a decision to be made between one popular convention and another, I almost always go for the one which reduces whitespace. I have enough faith in programmers’ pattern-detection skills to know that in time, they will be fine with either style, but the one with less whitespace will always give them more bang for their Cinema Display buck.

Back to CSS. Here’s how I’d format the above snippet:

  1. #score { background: yellow;  border: 1px solid orange;
  2.              width: 12em;  padding: 2em;  margin: 3em 0;
  3.              display: none;
  4. }

What I do is group similar attributes on each line. I’m pragmatic about the precise rules. If it’s just a handful of properties, I’ll stick them all on the same line. If there’s more than that, then typically I’ll have one line for appearance (colour, fonts, etc.), another for layout, and possibly more for other things like display settings or detailed positioning. You also don’t need whitespace between each rule either, so you can often end up with a whole sequence of related one-liner rules:

  1. /******************************************************************************
  2.    SCOREBOARD
  3.  *****************************************************************************/
  4. #scoreboard { background: black; color: white; }
  5. #homeTeam, #awayTeam { color: pink; text-align: right; position: absolute; }
  6. #homeTeam { top:20px; left: 120px; font-size: 8em; }
  7. #awayTeam { top:80px; right: 120px; font-size: 5em; }
  8. ...
  9.  
  10. /******************************************************************************
  11.    ARENA
  12.  *****************************************************************************/
  13. .player { color: #f99; }
  14. .runner { color: #99a; }
  15. ...

This format is not only denser but also easier to comprehend as related properties are grouped together. The typical one-line-per-property format tends to include a random jumble of properties; rarely does any thought go to the order in which the properties appear.

Another thing that helps with CSS brevity is learning shorthand formats. Use “border: 1px solid orange” instead of “border-width: 1px; border-style: solid; border-color: orange”. Use “margin: 3em 0;” instead of “margin-left: 3em; margin-right: 3em;”, and so on.

Tables – The Secret Behind Every Simple CSS Form

Tableless forms are painful. Every time I start trying to create them, I wonder why I am going through the motions. Some vague sense that it will be “more accessible” and I’ll be able to tick an abstraction of a “web standards-compliant” box. But really, these table-less constructs are supposed to make page authoring easier, not harder. In the case of forms, table-less CSS makes it much harder.

Here are some examples of popular blog articles explaining how to create table:

CSS-Only, Table-less Forms (Jeff Howden) “Most of the CSS-only, table-less forms available suck.” He’s talking from an aesthetic perspective, not programming perspective whose suckiness I speak of here. What he does though, is show how to make a pretty form. The rub is over 300 lines of standard-formatted CSS, let alone the HTML. He does a good job, and I have no reason to question that the 300 lines is required; it’s a sad reflection of what’s required to make a neat form, albeit a fairly complex one.

A List Apart on Accessible Forms A more pedestrian tutorial on the basics of table-less forms. Weighing in at a mere 46 lines of CSS.

Using a table and just a handful of CSS lines, you can achieve pretty similar stuff. It won’t get an accessibility auditor’s magic tick, even though it will probably be quite accessible. It won’t be a semantically valid structure either. That won’t actually bother your users or any modern search engine, but if the thought scares you, you should get started with those floats and clears. For all these problems, you’ll be rewarded with one great benefit: you’ll be able to build it in a matter of minutes.

For typical forms where you want to be agile and get the thing published, stick with tables.