HTML5 Audio on Android: DOA

This Android bug with HTML5 audio is awful. After a phone call or SMS, it resumes playback EVEN IF the audio was paused and EVEN IF the browser isn’t active. I just added a +50 bounty to this question as I still can’t figure how to prevent playback from happening.

Try it yourself on Android Browser:

Meanwhile Chrome audio is so temperamental it shuts down when the screen turns off, a critical flaw which no-one is prepared comment on ( much for open web standards.

And you wonder why native apps are eating HTML5’s lunch. Even with packaging from PhoneGap and it’s building apps on a house of cards. Until the default Android runtime is Chrome, and Android Chrome gets up to parity with Mobile Safari and beyond, there’s not much point using HTML5 to develop anything serious on Android, not when the native platform keeps running ahead on turbo mode.

Cross-posted and modified from G+

Graceful Degradation of Links

I made a bit of rookie error on a recent update. Suggestions for best practices are usually presented as fait accompli, but actually come from iterations in many cases. So I’d like to share how this one evolved. The actual refactorings were small, but it took a day of background thinking before the light bulb went off.

The feature “ajaxes in” some content when the user requests it.

I call this component a “midi” (bigger than a simple button or line of content, smaller than a full page.) It acts as a kind of preview, where the user can open the full page by clicking on the “tablet” title on the top-left.

Just a span

I begin thinking about the request controls as simple spans, like etc, because I’m getting away from the usual channel “tablet” control. Tecnically, the Ajax handler could just parse the title of the using the span’s innerHTML, but that would be error-prone and inflexible. For one thing, it would have to infer the owner as “featured”, and that would make the component less general-purpose. So I embed the path as a data attribute:

<span data-path=’/featured/comics/midi’>comics</span>

Not bad. Now we just need to Ajax-request /featured/comics/midi and drop the content into this div. A one-liner using jQuery replaceAll() or similar.

A real link

I don’t deploy yet. I go to bed and test on iPad and realise this sucks for touch. With a real link, tablets will confirm it’s a link when you press down on it. iPad, for example, will show a grey background and if you long-hold, open options to Open In New Tab, etc. I could try faking it with hover styles, etc., but it’s unnecessary when I could just make this thing a link. So I do this:

<a href=’/featured/comics/midi’>comics</a>

Much better on touch devices now.

No, a real, real, link

Okay, but wait a sec. What if the user actually clicked on the link, or a search engine bot followed it? The link would take them to an unstyled block of content that’s supposed to appear on a page. Well, I could try to detect XHR and format it nicely. But there’s a better way:

<a href=’/featured/comics’>comics</a>

Just link to the actual thing the user is trying to preview. The JavaScript now adds “/midi” manually when performing the hijack. So the “/midi” link never appears on the site. Just as it shouldn’t.

Eeedjit. Why didn’t I do this from the start?!!

On the one hand, I made a basic error by not doing it from the start. On the other hand, I think it’s a good example where the solution changes over time as you re-conceptualise the problem. I simply wasn’t thinking about the “request controls” as links, and I was thinking if the user wants to open up a link in a new window, they can request a preview first, and then open it. But of course, users will indeed want to open in new window, right-click to copy the link, etc. That’s really one of the great benefits of a HTML5 history architecture like this, where the links are real and not Ajax-era hashbangs. It’s just that I didn’t see it that way from the start.

Web Vs Native at State of the Browser 2

(via Steve Workman)

I was at State of the Browser 2 yesterday, an event comprising reps from the browsers. I’m happy to be part of this event as I think it’s valuable for the web as a whole for devrels to get together with developers in this way. The browsers do spend a lot of time talking to each other about specs etc in meetings and mailing lists, but at State of the Browser, they’re facing the developers. So straight up, thanks to the organisers for doing a great job running this great event again.

Thankyou for the sketchnotes UBelly 🙂

Slides for my keynote talk on Web vs Native are here. I’ll highlight the four challenges of the web which

In order of increasing threat, I mentioned:

  • UI Low threat. A lot of the capabilities are already in place and we can already do decent UIs if not “gorgeous”/”sexy” like Path or Paper.

  • Offline Medium threat. DHH wrote his famous You’re Not on a Plane argument in the desktop era. Mobile is way important these days, connectivity remains sketchy, and 3G is expensive for many. The pure offline scenario may matter less, at least for many people in developed nations, but latency matters a lot to everyone. HTML5 does have offline technologies, but browser support is extremely fragmented and there are many debates about what to use where.

  • Device Integration Medium threat. Web needs permissioned access to camera, contacts, etc. But my bigger concern is peripheral aspects like single sign-on, notifications, Android intents. These things, for the most part, are not possible in web apps. There are signs that’s changing as the speakers yesterday highlighted, e.g. Chrome’s adding Web Intents, IE’s adding native notifications like the OSX native notifications I mentioned. But it’s really early days, and I don’t see anyone talking about single sign-on for web apps, which is hugely concerning considering how personal in nature smartphones and native apps are.

  • Background Processing High threat. This doesn’t get much play, but is something I’ve been thinking about since writing this and listening to the related Jason Grigsby podcast. With modern smartphone apps, we see the long-anticipated trend of software that acts as intelligent agents. An app is not just something you open, interact with, and close. Through its smartphone vehicle, the app serves as an extra brain, extra set of eyes and ears, extra communication agent. With you at all times, proactively scanning the environment for anything useful. Sucking down content and syncing with servers. Notifying you when anything particular important happens. Web apps are shut out of this game. They are useful as long as the user is looking at them. Out of sight, out of mind. Or more generously, as long as they are still open in a tab, but they may have restricted functionality in mobile background tabs to preserve battery life. Chrome has done some work here with background apps, but it’s really early days and I don’t see anyone thinking about this problem in mobile space.

I also mentioned monetization and competing standards as additional threats, only reason I didn’t cover them in detail is time. I did mention a little of it in the recent bonus HNPod episode on HTML5 vs Native and we had a Twitter conversation about it yesterday.

Remy blogged all the morning talks and raised some questions about each.

Is the point: browsers don’t matter – the web does…?

The underlying assumption is that the web matters more than any individual browser.

Should the browser just be the webview?

No. Browsers add a lot of value beyond the web view. One of many examples is customisation via preferences and extensions.

“You’re not on a fucking plane” – but then do all devs know how to build apps like gmail where it’s insanely quick because they know how to work the mobile device?

Agree. It’s hard right now. And even harder if you wish to use the same core app for both online and offline (as well as desktop and mobile).

AppCache is not a replicatement (sic.) for localStorage – far from it.

Definitely not.

Is there a larger problem that the browser (and a pro) exposes data if the user wants to get to it. It makes SSO harder because of security, etc?

Yes, but just like camera access, geolocation, etc, you can handle it with permissions. If HTML5 doesn’t stay competitive with native on SSO, background apps, etc, it’s not going to be a modern platform for apps. There’s enough UI widgets already, it’s these peripheral aspects — those where security is an issue — where native is surging ahead. You can either do basic websites without app-iness or you can do apps which use the full range of possibilities available in a modern device and operating system.

Web vs. Native seems like two issues: browser and the web. Browsers being the limitation

Both as we’d want web standards too for whatever the browsers offer developers. But definitely down to the browsers and possibly the OSs when you consider SSO for example.

The panel I moderated. Devrels from four browsers and the forbidden fruit. (via james_smith88)

The Boot2Gecko Developer Experience: An Interview with Mozilla’s Jonathan Nightingale

A surprise bonus of last week’s MWC trip was the coincidental launch of Boot2Gecko, Mozilla’s operating system based on Firefox (Gecko being Firefox’s underlying layout engine and B2G being the unofficial brand name for now). They made a joint announcement with Spain’s Telefonica (O2 and GiffGaff’s parent company) with the expectation to release a commercial offering this year (no commitments yet though).

Continuing my “a conference is worth more than 140 characters” resolution, I had a chance to sit down with Mozilla’s Senior Director of Firefox Engineering, Jonathan Nightingale and understand some of the technical issues around the new OS.

Key points from the video, as well as speaking to some of the other Mozillians:

  • The device could be very cheap, $60 for a SIM-free device is a figure I heard. Needless to say, if they can achieve a price point like that, it will be music to carriers’ ears and simultaneously light up the HTML5 developer community. At 10:00, Jonathan mentions that Telefonica sees the opportunity to produce a smartphone that’s “interactive, smooth, high quality, with a good app selection, that is one-tenth the cost of an iPhone”. From what I’ve heard, this is because of two factors: the target hardware is open and patent-free, and the HTML5 runtime is built over a thin Linux core, so various layers are eliminated.
  • It boots fast, about 14 seconds (I thickly say 4 seconds in the video but I was counting from the splash screen…my argument is invalid). Bearing in mind this is a very early concept, the final version will hopefully be even faster, though it’s possible extra services may make it slower too.
  • Everything is HTML5. The launcher, dialler, camera, gallery, et al. And what’s more …
  • … On the dev build, as Jonathan demos, View Source is available everywhere! On all the apps, and that includes those “system” apps above (launcher, dialler, etc).
  • The Mozilla Marketplace is not exclusive to B2G. It will run on other devices where Firefox runs, like Android. (It turns out that Android apps can be permissioned to add multiple URL shortcuts to the Android launcher, so once a user installs the market, they can install apps directly on the launcher.) This is a little like the Chrome Web Store, which is the app distribution mechanism for ChromeOS, but also works on regular Chrome across the different OSs it runs on.
  • Mozilla’s keen to cultivate an ecosystem of multiple marketplaces with different verticals and business models. They offer their own marketplace, but will happily embrace others.
  • No immediate plans for extensions or a NodeJS service layer like WebOS runs, but Moz is very open to feedback via the standard channels.

PPK argued in last week’s Web Ahead we may well see a shift away from Android in the next year as carriers come to terms with Google’s Motorola acquisition. It’s not for certain, but I did hear people echo this view at MWC. Boot2Gecko will be a key part of the current movement among the smaller OSs to embrace HTML5 developers. And if the price point means developers can easily get their hands on these devices, as opposed to the usual suspects who are awarded freebies by marketing departments, it stands a real chance in this market.

HTML5 developers should also check out Christian’s Boot2Gecko write-up for more info, as well as the official Boot2Gecko Wiki.

HTML5 Full Screen Mode: Quick Notes

Just been playing with full-screen mode in Chrome, which lets any element become full-screen (not just video, as I think it was envisioned in earlier days). Wanting to get this working nicely on mobile devices, I’ve also done some experimenting with graceful degradation / progressive enhancement as it applies to full-screen mode.

Basic Version

Although you can full-screen any element, I decided to full-screen the entire body, then use a kind of classy HTML to show what needs to be shown in full-screen mode. (Mainly because I’m using a component that wasn’t immediately working when I full-screened it directly.)

I’m using a full-screen toggle element, here’s the CoffeeScript:

  1. $('#fullScreen').click (ev) ->
  2.     if document.webkitIsFullScreen then document.webkitCancelFullScreen() else document.body.webkitRequestFullScreen()

Note that you cancel on document (that’s the only thing you can cancel on), but you set it on any element (though you actually can’t set it on document!). Also, note that the user could manually hit escape to exit, so don’t think that you’re always in control of full-screen state. Hence the webkitIsFullScreen check instead of trying to maintain state in a flag variable.

Following the Classy HTML pattern, the CSS here is based on a new pseudo-selector which gets applied to the body element. We can easily decide what to include in full-screen mode. In this case, as the SCSS below shows, I’ve simply elevated the map element above everything else, but knock yourself out.

  1. :-webkit-full-screen {
  2.   #map {
  3.     position: absolute;
  4.     z-index: 2000;
  5.     top: 0;
  6.     left: 0;
  7.     width: 100%;
  8.     height: 100%;
  9.   }
  10. }

And no, it’s not just for Webkit…go check out MDN’s full-screen docs for more info.

Graceful Degradation Version

But what if there’s no full screen mode? We can still make that full-screen toggle useful by expanding content to max out the browser screen, even though the browser itself can’t switch into full screen mode. So here’s another crack at it, where we use the true Classy HTML pattern, i.e. instead of styling according to the built-in full-screen pseudoselector, we make our own “fullScreen” class. If the document is in either :-webkit-full-screen or “fullScreen” state, we’ll max out the important content.

  1. fullScreenEnabled = (typeof(document.webkitCancelFullScreen)!='undefined')
  2.   $('#fullScreen').click (ev) ->
  3.     if fullScreenEnabled
  4.       if $('body:-webkit-full-screen').length
  5.         document.webkitCancelFullScreen()
  6.       else
  7.         document.body.webkitRequestFullScreen()·
  8.     else # oh well, at least we can big up the content inside the browser
  9.       console.log('full not enabled')
  10.       if $('body').hasClass('fullScreen')
  11.         $('body').removeClass('fullScreen')
  12.       else
  13.         $('body').addClass('fullScreen')

The style is exactly the same as before, just with two selectors involved. Something like this, in theory:

  1. :-webkit-full-screen,.fullScreen {
  2.   #map {
  3.     position: absolute;
  4.     z-index: 2000;
  5.     top: 0;
  6.     left: 0;
  7.     width: 100%;
  8.     height: 100%;
  9.   }
  10. }

But in practice, for some hair-pulling reason, non-webkit browsers will ignore that entire rule, so I had to duplicate it:

  1. :-webkit-full-screen {
  2.   #map {
  3.     position: absolute;
  4.     z-index: 2000;
  5.     top: 0;
  6.     left: 0;
  7.     width: 100%;
  8.     height: 100%;
  9.   }
  10. }
  12. /* As DRY as mud...but I found this duplication required */
  13. .fullScreen {
  14.   #map {
  15.     position: absolute;
  16.     z-index: 2000;
  17.     top: 0;
  18.     left: 0;
  19.     width: 100%;
  20.     height: 100%;
  21.   }
  22. }

Now the full-screen toggle works for all browsers. But full-screen enabled browsers get the nice bonus of busing out of the browser tab and taking up the entire desktop.

(Again, I confess, this is me messing around with webKit only for now. The graceful degradation stuff does work with Firefox of course, though it could do more than just that. I haven’t used full-screen on Firefox simply because there are other components not working on Firefox, and this post is based on practical experience. It’s well-supported on both Firefox though as well as Chrome.)

HTML5 App Themes Are Coming

There are plenty of premium theme markets out there. Many are for vanilla websites, where they provide you with the entire HTML, CSS, and JavaScript, while some are for specific frameworks, e.g. WordPress themes aplenty.

A huge gap in the market remains: Apps. Having trawled through a bunch of these — admittedly some months ago — I concluded the closest thing was some system admin templates for systems like CPanel. Yet every day, hobbyists and startups are creating thousands of apps. Not on the same scale as marketers are churning out WordPress blogs about <insert-niche-here>, but still, big enough to warrant art-less developers not having to cobble together their own look-and-feel for a v1.

A big part of the problem is lack of standardisation. HTML5 apps pretty-much have any arbitrary page structure and class names. The HTML5 semantic tags may have helped here to standardise on entities like “section” and “article”, but it’s not clear how many developers are using those elements. And I’m sure some, like me, are just using them as class names for divs (for improved compatibility), while others are using the actual tags, and some are doing the Right Thing by using both. Where WordPress themes can assume a lot about page structure, HTML5 app frameworks cannot.

In other words, HTML5 suffers from a lack of conventions. WordPress is not the only example of the power of conventions. Witness the vibrant marketplace of Rails gems, which can support powerful styles of reuse because they are able to build on conventions. Likewise, jQuery and Backbone plugins.

This will change soon because of two great frameworks: Twitter Bootstrap and HTML5 Boilerplate. These are becoming very common frameworks for HTML5 developers to get started and will soon be combined if this issue happens with Boilerplate 2.5. It will build a Bootstrap kickstart for Boilerplate. That’s a real Bootstrap.

You can start to see Bootstrap apps sprout like weeds across the web, marked by their characteristic Twitter-like black navbar. It’s a genius framework and one I’ve benefitted from immensely. But the problem is, for something called Bootstrap, it surprisingly doesn’t include any HTML at all. So that navbar is actually what people are mostly cut-and-pasting from the docs and examples. The lack of standards makes it hard to produce themes. There’s already a premium theme site out there, but it proves my point. If you look at the markup, it’s wide and varied, even for the navbar.

I’m hopeful the Boilerplate combination will rectify that situation. If apps can move towards a common page structure and naming conventions, a world of themes will blossom.


The Non-Visual Web

Looking Forward

7 years on from Ajax, we have our JavaScript-fu down and the APIs we could ever have dreamt of are baked into the desktop browsers of note. So what’s next for the web? The latest 5×5 podcast with Jason Grigsby is illuminating on future trends (as well as being a must-listen for all its practical advice):

Episode Homepage

Here I want to outline a few specific features which will challenge the boundaries of the web as we know it. And then I’ll explain how the web community can meet those challenges.

Tip of the Iceberg

In 2009, I gave a talk at London Web Standards on eight features of HTML5 you won’t see, features such as offline storage, geolocation, and history API.

That’s the tip of the iceberg of the tip of the iceberg. An example in this podcast is walking down the street and having your phone’s navigation system vibrate once if you should turn left, twice if you turn right. Another example mentioned in the podcast is a JavaScript vehicle API! webinos.vehicle.addEventListener (webinos.vehicle.NavigationEvent.DESTINATION_REACHED, handleDestinations, false); Checking fuel level, engine condition, etc. via a high-level API. And of course, there’s the whole medium of sound…this post was kicked off by a podcast after all!

The web has traditionally been a visual medium. As Jen Simmons observes here, even when it’s not visual, we use the word “Screen Reader” to emphasise its visual foundations. While it’s moved from text to images to fancy graphics and multimedia, those things are still visual elements on the page. Yet all of the above are not about elements on the page. That’s where technology is headed. So is it even sensible to handle these things through the web?

Model-View Separation

On a technical level, what makes the web incredibly powerful is the DOM concept. DOM is sync’d to UI. Update the DOM and it changes the user-interface. Change the UI and the DOM updates. The programmer doesn’t have to facilitate this bidirectional sync; it just happens.

Really, on a technical level, this is an incredibly important and overlooked aspect of HTML5. Too many HTML5 APIs are pure JavaScript functions and ignore the DOM altogether. For the web to thrive, vehicle APIs should not just be webinos.vehicle.addEventListener. The vehicle itself should be part of the DOM. If that sounds too domain-specific, that’s okay, because look at the work of Web Components. These guys are bringing about a world where anyone, or any community, can create a first-class <x-vehicle> element with its own look-and-feel.

Open Standards

Of course, at a higher level, the web is about open standards. That’s really what sets it apart from iOS, Android, and .Net. There’s no single vendor in charge. Something like the Java Virtual Machine comes close, but the web stack stands out as a more balanced control system. If there are to be standards for things like vehicle APIs, the web is attractive as the best stab at a neutral ground with real developer buy-in.

For this reason, the web can successfully move beyond the visual medium without losing what makes it the web in the first place.

Announcing Faviconist

faviconist screenshot

I have made a new Favicon generator, Faviconist. Since most favicons are just a letter with some colour theme, I found it crazy to have to open up a photo editor every time I wanted a new favicon. Or alternatively, it’s easy enough to convert an image with ImageMagick, but most images don’t scale down nicely to a tiny icon! So the aim here is not an editor as such, but a true “favicon generator”.

Using Faviconist

To create a favicon, it’s as simple as typing the first letter of your website. But you probably don’t want the default colour scheme, so it’s easy enough to tweak. Under the covers, Favicon has a concept of a “FillStyle” and both foreground and background are instances of FillStyle, so they have the same flexibility. You can have a solid fill style (just a single colour), a linear gradient, or a radial gradient.

For simplicity, Linear gradients don’t have stops (it’s just a linearly increasing spectrum from start to finish), though you can choose the direction. And in the same sprit of simplicity, radial gradients may only begin at some points, and their span is fixed. The guiding principle here is “YAGNI” – You Ain’t Gonna Need It. I’m catering for the 95% of people who don’t want to micro-design their icons; the rest will still need to resort to PhotoShop et al.

The preview images are PNGs, which can easily be downloaded directly. However, another gripe of mine is the whole thing of downloading to hard drive and uploading back to a server somewhere else. Hot-linking, aka “bandwidth theft”, is rightly a problem for the original image host…but it’s a shame the only way we can deal with it is to silo everything. (A parallel vision of the web, which might have almost succeeded and still might, saw it more as embedded content than a collection of copies and links.) In this case, it’s only favicons, so I’ll just say hot-link and be merry. When you click “Save Favicon”, it saves the icons on my server and you can just cut-and-paste into your own project.

I hope this is useful for quick hacks and hackathons, where favicons are often forgotten! These days Favicons are more useful than here. Of many reasons to use a favicon, things one might forget are: they’re used on third party sites like Google Plus, tabbed browsing is super-popular these days; if you don’t provide favicons, you’ll get 404s in your log files.

And here’s a little tip for you – don’t just use letters. Try special characters, and don’t just limit yourself to ASCII. You have the entirety of Unicode at your disposal!

How Favicon Works

Buzzword Bingo time. There are a number of technologies at work here:

  • HTML5 Canvas In the past, a site like this would have to be powered by the server – every change would require a long wait for the server to generate a new image. But now, we can do it in real-time, in the browser, using Canvas. The only server interaction is conversion to “.ico”; unfortunately, Canvas will output to PNG, but not ICO. And while a JavaScript ICO encoder is certainly a possibility, no-one has yet written one.

  • Canvas Text To draw text, Faviconist uses Canvas’s fillText method. e.g. context = canvas.getContext('2d'); context.fontStyle = '25px arial'; context.fillText('Yo!'). When Ace Editor effort got started (called Bespin), in the early days of canvas, text support was patchy. But now it’s very well supported.

  • MeasureText Library I thought Faviconist would be easy because I thought there would be simple metrics for fonts. Turns out canvas’s measureText() returns a “TextMetrics” object, and guess what TextMetrics contains:

interface TextMetrics {
  readonly attribute double width;

Huh? We can only find the text’s width, not its height. And as a I went down the path, I learned you can’t just say “draw this text with its top-left at (0,0)”. To center the font, as we do in Faviconist, we actually need to determine text offset as well – left and top.

So I built the MeasureText library. It works as a drop-in replacement (~shim) for the built-in HTML5 Canvas MeasureText mechanism, and also provides a new convenience function not requiring an existing canvas. It works by drawing the text and scanning the resulting bitmap to get a true representation of the metrics. Using this, and with a little geometry, it’s possible to center text.

  • Favicon Library Figured it would be cool to show a preview of the favicon by changing the site’s actual favicon! For which I used ye olde Favicon library, which I originally created via this blog and I’ve now officially moved to The library also incorporates a new “badge” feature, so you can show number of pending emails, etc. Go try the demo!

  • Font Selection You can choose fonts, with the fonts coming from the Google Font Directory. It wasn’t feasible load all fonts, so they’re loaded dynamically, but I wanted to show previews … so there’s a script to build a 38,000 pixel sprite map! It’s loaded after the page loads, with a canvas-based check to see if it loaded successfully (since it doesn’t work on Firefox). To show it in a dropdown, I used a fork of the Chosen library, a fork which retains the class of each option in the select list.

  • Chrome Frame Didn’t want to support IE6-IE8, so introduced Google Chrome Frame, based on the code in HTML Boilerplate, but increasing the version check from 6 to 8.

  • JavaScript Libraries Faviconist uses several useful libraries: jQuery, Underscore, Backbone, and jQuery Tools. And just to say, jQuery Tools is the very picture of Developer Experience heaven. Great explanations, many easy-to-follow demos, lots of options…and a CDN for the libraries.

  • NodeJS, Connect, Express The server is NodeJS running the Express-Connect stack. Considering that the app is almost all client-side, I spent a ton of time getting up to speed with this stack, partly due to performance optimisatins, and partly due to the next point …

  • Jade, Stylus, Kaffeine Being a fan of DRY, I’m very happy to be using higher-level abstractions of HTML, CSS, and JavaScript. I certainly am happy with Jade, with the exception of dropping in raw HTML script snippets. And Stylus is absolutely awesome. Kaffeine makes JavaScript much easier, though I’ve found it difficult to incorporate everywhere because the ecosystem is very much geared around CoffeeScript. e.g. Connect comes with a default CS compiler, Nodemon (a node watch-and-run-tool by Remy Sharp) supports CS, there’s a ton of doco about getting CS working with things. So that was really the biggest challenge. I mainly wanted Kaffeine because I’m not such a fan of significant whitespace, but the ecosystem’s preference for CoffeeScript did present challenges.

I hope you enjoy Faviconist. It’s a work in progress, so please leave feedback if you have suggestions.

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")
      span solid
      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%