5 posts on Browsers

Exactly how much CSS3 does your browser support?

2 min read 0 comments Report broken page

This project started as an attempt to improve dabblet and to generate data for the book chapter I’m writing for Smashing Book #3. I wanted to create a very simple/basic testsuite for CSS3 stuff so that you could hover on a e.g. CSS3 property and you got a nice browser support popup. While I didn’t achieve that (turns out BrowserScope doesn’t do that kind of thing), I still think it’s interesting as a spin-off project, especially since the results will probably surprise you.

How it works

css3test (very superficially) tests pretty much everything in the specs mentioned on the sidebar (not just the popular widely implemented stuff). You can click on every feature to expand it and see the exact the testcases run and whether they passed. It only checks what syntax the browser recognizes, which doesn’t necessarily mean it will work correctly when used. WebKit is especially notorious for cheating in tests like this, recognizing stuff it doesn’t understand, like the values “round” and “space” for background-repeat, but the cheating isn’t big enough to seriously compromise the test.

Whether a feature is supported with a prefix or not doesn’t matter for the result. If it’s supported without a prefix, it will test that one. If it’s supported only with a prefix, it will test the prefixed one. For properties especially, if an unprefixed one is supported, it will be used in all the tests.

Only stuff that’s in a W3C specification is tested. So, please don’t ask or send pull requests for proprietary things like -webkit-gradient() or -webkit-background-clip: text; or -webkit-box-reflect and so on.

Every feature contributes the same to the end score, as well as to the score of the individual spec, regardless of the number of tests it has.

Crazy shit

Chrome may display slightly different scores (1% difference) across pageloads. It seems that for some reason, it fails the tests for border-image completely on some pageloads, which doesn’t make any sense. Whoever wants to investigate, I’d be grateful. Edit: Fixed (someone found and submitted an even crazier workaround.).

Browserscope

This is the first project of mine in which I’ve used browserscope. This means that your results will be sent over to its servers and aggreggated. When I have enough data, I’m gonna built a nice table for everyone to see :) In the meantime, check the results page.

It doesn’t work on my browser, U SUCK!

The test won’t work on dinosaur browsers like IE8, but who cares measuring their CSS3 support anyway? “For a laugh” isn’t a good enough answer to warrant the time needed.

If you find a bug, please remember you didn’t pay a dime for this before nagging. Politely report it on Github, or even better, fix it and send a pull request.

Why did you build it?

To motivate browsers to support the less hyped stuff, because I’m tired of seeing the same things being evangelized over and over. There’s much more to CSS3.

Current results

At the time of this writing, these are the results for the major modern browsers:

  • Chrome Canary, WebKit nightlies, Firefox Nightly: 64%
  • Chrome, IE10PP4: 63%
  • Firefox 10: 61%
  • Safari 5.1, iOS5 Safari: 60%
  • Opera 11.60: 56%
  • Firefox 9: 58%
  • Firefox 6-8: 57%
  • Firefox 5, Opera 11.1 - 11.5: 55%
  • Safari 5.0: 54%
  • Firefox 4: 49%
  • Safari 4: 47%
  • Opera 10: 45%
  • Firefox 3.6: 44%
  • IE9: 39%

Enjoy! css3test.com Fork css3test on Github Browserscope results


Exploring CSS3 text-shadow

5 min read 0 comments Report broken page

I consider CSS3’s text-shadow one of the most exciting CSS3* properties, which offers us a lot more effects than it’s name suggests. Of course, it can be used for creating drop shadows for text, and it carries out that task very well, but it’s inherent flexibility allows it to be also used for glow effects, outlines, bevels, extruded text, inset text, fuzzy text and many others (until browser bugs and backwards compatibility come into play… :(). This post is about various findings of mine (and others’, where a source is provided) regarding this property, including browser bugs and inconsistencies, effects that can be achieved with it, compatibility woes etc.

Browser support

  • Opera 9.5+
  • Firefox 3.5+
  • Safari 1.0+
  • Google Chrome

text-shadow syntax

The syntax is fairly simple:

text-shadow: <offset-x> <offset-y> <blur-radius> <color>;

There are some variations (the color could be first instead of last, the blur radius can be omitted if it’s equal to zero and the color may be omitted if it’s the same as the text color) and you may include multiple comma delimited shadows.

You may read more about the syntax in the official specification.

How it works

It helps if you imagine the algorithm for drawing the text shadow as follows:

  1. Create a (most of the times differently colored) clone of the text and place it behind the text.
  2. Move it according to the X and Y offsets (positive values move it to the right and bottom respectively)
  3. If a blur radius is specified and it’s > 0, blur it accordingly (the specification doesn’t mention the blurring algorithm to be used, so each browser vendor may choose any blurring algorithm they prefer, and judging by my experiments, it seems they took advantage of this freedom). In all cases however, the bounding box of the blurred text can extend no further than the bounding box of the original text plus (+) the specified blur radius on each side.
  4. Repeat for the rest of the shadows, if more than 1 are specified. The order in which shadows are drawn seems to be a subject of debate, judging by the wording of the specification and the various existing implementations.

The experiments

You will find the experiments I performed here. I tried to come up with (or find) interesting uses of the property. I also tried to make some of them “pretty”, so they could be useful to others, but given the fact that these were primarily created for testing purposes, this wasn’t achievable for all of them. Next to each experiment is the CSS used to produce the effect (directly fetched from the <style> tag via JavaScript). You’d better not view it with IE until you read below or you might have some freaky nightmares tonight :P

Screenshots from various browsers: (mouse over the thumbnails to see which browser was used for each one)

[gallery link=“file”]

Browser bugs and inconsistencies

Apparently, some browser bugs were exposed in these experiments:

  • Opera 10 and Safari don’t display the shadow when the text color is transparent (demonstrated in Experiment #5). Opera 9.6 doesn’t seem to support transparent as a text color, so it ignores it.
  • When the text color is RGBA, Safari applies transparency to the shadow, equal to the Alpha component (demonstrated in Experiment #8).
  • Opera paints the shadows in the order they were specified, whereas all others use the reverse. According to the current version of the specification, Opera is the only correct one, but I doubt that web designers will give her credit for it :p (Experiment #8)
  • Google Chrome uses a crappy blurring algorithm (Experiments #5 and #7)
  • Safari and Chrome don’t default to the text color when no color is specified in text-shadow, but to transparent. (Experiment #2)
  • Opera is seriously messed up when it comes to transparent shadows, as demonstrated by Experiment #9. I can’t even describe the bug (try messing with the text-shadow value a bit and you’ll see why…). Luckily, I can’t think of a single case where a transparent text-shadow would be useful :P
  • You can see a bit of the shadow in Google Chrome even if the offsets and blur radius are all 0 (Experiment #9). I’m not sure if this is a bug, but it’s inconsistent with the other implementations.
  • Even if you ignore the bugs above, there are slight rendering variations when multiple blurred shadows are involved (or they are more apparent in those cases), as demonstrated by experiments #2, #6 and #7.

Firefox’s implementation seems to be the clear winner here…

A note about the above observations: When no version number is mentioned, 3.5 is implied for Firefox, 10 for Opera and 4 for Safari and Chrome.

Alternatives to text-shadow

IE Filters

As you might have noticed, I have managed to completely avoid mentioning Internet Explorer up to this point. It’s no surprise that our dearest browser doesn’t support the text-shadow property. However, it does support some filters (DropShadow and Shadow) that could be used to provide a very small subset of the different kinds of text shadows, although they severely mess up the font anti-aliasing (just like all IE filters). Also, if the parent or siblings of the text node in question have backgrounds or borders an extra element is needed to enclose the text node (you’ll see in the experiments why…). For these reasons,  I highly doubt whether they are worth it and I don’t use them personally. However, if you are interested you can see a brief demonstration of these two filters in Experiments #3 (DropShadow) and #6 (Shadow, actually 4 of them).

The :before pseudo-element

This could be used instead of the text-shadow, when the blur radius is 0, since browser support for the :before pseudo-element is better than browser support for text-shadow (even IE8 supports that, yay). Here is a thorough (although slightly outdated) tutorial on this technique. However,this workaround severely hurts separation of presentation and content/structure, since the content has to be duplicated in the CSS. Repeating something greatly increases the chance that the two copies become inconsistent, since people tend to be forgetful. Also, you have to know in advance the exact height of the text (in lines), another maintenance headache. For these reasons, I don’t use this workaround either.

In my humble opinion, the text shadow is usually just icing on the cake and not something crucial to the design, so it doesn’t hurt if it won’t show in some old and/or crappy browsers. It degrades gracefully in most cases (ok, you’ll have to wait a few years before using it in ways that don’t) so it doesn’t hurt usability/accessibility either. It’s just one of the little treats I like to offer to visitors that were smart enough to use a decent browser. :-)

Epilogue

text-shadow is a very flexible property, with probably the best browser and editor – even Dreamweaver acknowledges it’s existence! – support among all notable CSS3* properties. It also degrades gracefully most of the times (the experiments above shouldn’t be considered “most of the times”! :P ) and this is why it’s probably also the most widely used CSS3* property.

I think it could be improved even more by allowing for the inset keyword (just like inset box-shadows – sadly only Firefox 3.5 supports those at the time) and a fourth parameter could be used to enlarge or shrink the shadow (currently the only way to enlarge it is by blurring it, which isn’t always desirable) although it would complicate the shorthand (the blur radius would probably become required – so that the browser can tell them apart). However, a separate property could be used to solve that (text-shadow-size?). I guess we could combine the :before technique, with transparent text color (in the :before pseudo-element) and a text-shadow for that to imitate such an effect (I can elaborate if this seems obscure) although I haven’t actually tried it (however, even if it works, it’s too much of a hassle).

Anyway, I guess it’s too late for such suggestions, so let’s focus on what we actually will get (?) which is more than sufficient :-)

______________________________________________________________

*Actually, it was originally proposed for CSS 2.1, but it was dropped due to lack of implementations (basically only Webkit supported it)

Articles, Browser Bugs, Browsers, Chrome Bugs, CSS, CSS Properties, Experiments, Opera Bugs, Safari Bugs, Text Shadow, WebKit Bugs
Edit post on GitHub

On native, single-input, multiple file uploads

2 min read 0 comments Report broken page

If you are following the current news on web development, you probably heard that the new Safari 4 has a great feature: It natively allows the user to select multiple files via a single input control, if you specify a value for the attribute multiple:

<input type="file" multiple>

or, in XHTML:

<input type="file" multiple="multiple" />

You might not know that Opera supported multiple file uploads for a while now, based on the earlier Web Forms 2.0 standard in a slightly different (and more flexible) format:

<input type="file" min="1" max="9999″ />

Can we use those currently?

Sure we can, but we should provide fallbacks for the other browsers. Using these features will put pressure on the other browser vendors to implement them as well and generally, native is always better.

How can we find out whether the browser supports them?

Opera

Opera supports accessing those min and max properties as properties of the element. So, it’s quite trivial to check whether Opera-style multiple inputs are supported:

var supportsMin = (function(){
	var fi = document.createElement('input');
	fi.type = 'file';
	return fi.min === '' && fi.max === '';
})();

Safari 4

In Safari 4 the check would be equally simple, if it supported accessing the multiple attribute as a property. Then we could easily check whether it’s boolean and conclude that Safari-style multiple inputs are supported:

var supportsMultiple = (function(){
	var fi = document.createElement('input');
	fi.type = 'file';
	// The second check is probably redundant but what if in the future an implementor
	// decides to make the file inputs to handle multiple selections by default?
	// Yeah, it's not likely, but it's not entirely impossible.
	return fi.multiple === false || fi.multiple === true;
})();

However, that’s currently not the case. The good news are that I reported this as a bug today, and the Webkit team fixed it, so it will be possible in the next Webkit nightly!

Combining the two

You can easily combine these two together with the workaround you prefer:

// Create a file input that allows multiple file selection
var fi = document.createElement('input');
fi.type = 'file';

if(fi.multiple === false || fi.multiple === true) { fi.multiple = true; } else if(fi.min === ‘’ && fi.max === ‘’) { fi.min = 1; fi.max = 9999; } else { // Our preferred workaround here }

What about Mozilla?

Ok, we all know that IE will probably take years to implement similar functionality. But usually, the Mozilla team implements new and exciting stuff quite fast.

As it turns out, there is a relevant ticket sitting in their Bugzilla for a while now. If you want them to implement it, vote for it so that it’s priority increases.

If they do implement it in the way suggested, the code posted above will work for that too, without any changes - The advantages of feature detection baby! ;)

Articles, News, Browsers, Feature Detection, HTML, JS, WebKit, WebKit Bugs
Edit post on GitHub

20 things you should know when not using a JS library

5 min read 0 comments Report broken page

You might just dislike JavaScript libraries and the trend around them, or the project you’re currently working on might be too small for a JavaScript library. In both cases, I understand, and after all, who am I to judge you? I don’t use a library myself either (at least not one that you could’ve heard about  ;) ), even though I admire the ingenuity and code quality of some.

However, when you take such a brave decision, it’s up to you to take care of those problems that JavaScript libraries carefully hide from your way. A JavaScript library’s purpose isn’t only to provide shortcuts to tedious tasks and allow you to easily add cool animations and Ajax functionality as many people (even library users) seem to think. Of course these are things that they are bound to offer if they want to succeed, but not the only ones. JavaScript libraries also have to workaround browser differences and bugs and this is the toughest part, since they have to constantly keep up with browser releases and their respective bugs and judge which ones are common enough to deserve workaround and which ones are so rare that would bloat the library without being worth it. Sometimes I think that nowadays, how good of a JavaScript developer you are doesn’t really depend on how well you know the language, but rather on how many browser bugs you’ve heard/read/know/found out. :P

The purpose of this post is to let you know about the browser bugs and incompatibilities that you are most likely to face when deciding againist the use of a JavaScript library. Knowledge is power, and only if you know about them beforehand you can workaround them without spending countless debugging hours wondering “WHAT THE…”. And even if you do use a JavaScript library, you will learn to appreciate the hard work that has been put in it even more.

Some of the things mentioned below might seem elementary to many of you. However, I wanted this article to be fairly complete and contain as many common problems as possible, without making assumptions about the knowledge of my readers (as someone said, “assumption is the mother of all fuck-ups” :P ). After all, it does no harm if you read something that you already know, but it does if you remain ignorant about something you ought to know. I hope that even the most experienced among you, will find at least one thing they didn’t know very well or had misunderstood (unless I’m honoured to have library authors reading this blog, which in that case, you probably know all the facts mentioned below :P ) . If you think that something is missing from the list, feel free to suggest it in the comments, but have in mind that I conciously omitted many things because I didn’t consider them common enough.

DOM

  1. getElementById('foo') also returns elements with name="foo" in IE and older versions of Opera.
  2. getElementsByTagName('*') returns no elements in IE5.5 and also returns comment nodes in all versions of IE (In case you’re wondering: DOCTYPE declaration will count, Conditional comments will not).
  3. getElementsByClassName() in Opera (even Opera 10 Alpha) doesn’t match elements with 2 or more classes when the one you’re looking for is not the first but it’s also a substring of the first. Read the discussion between me and John Resig on the latter’s blog post mentioned below if this seems a bit unclear.
  4. There is no element.children collection in Firefox 3-. You have to create it yourself by filtering the childNodes collection if it doesn’t exist.
  5. If your code involves preformatted elements (for instance if you are making a syntax highlighter), beware when setting the innerHTML of those: IE won’t preserve line breaks (\r\n s) and whitespace. You have to use outerHTML, which will actually replace the element so you should find a way to obtain a reference to the newly created one in case you still need to perform stuff on it.
  6. To get the dimensions of the viewport, standard compliant browsers use window.innerWidth (and innerHeight) whereas IE uses document.documentElement.clientWidth (and clientHeight).
  7. To get the scroll offsets of the current page, standard compliant browsers use window.pageXOffset (and pageYOffset) whereas IE uses document.documentElement.scrollTop (and scrollLeft).
  8. To make matters worse, in both cases above, you need to use document.body instead of document.documentElement when in Quirks mode.

John Resig (of the jQuery fame), recently posted a great presentation, which summarized some browser bugs related to DOM functions. A few of the bugs/inconsistencies mentioned above are derived from that presentation.

Events

  1. When using IE’s attachEvent() the this reference inside the callback refers to the useless window object
  2. eventObject.target is eventObject.srcElement in IE
  3. eventObject.stopPropagation() is eventObject.cancelBubble = true; in IE
  4. eventObject.preventDefault() is eventObject.returnValue = false; in IE
  5. There are many more event object incompatibilities for specific events (the ones above are for all events). Take a trip to QuirksMode for more information.
  6. IE leaks horribly (especially IE6) in various cases.
  7. If you register the same event handler X times, IE fires it X times.
  8. Determining when the DOM is ready is a complete mess. Firefox and Opera 9+ support the DOMContentLoaded event, Safari doesn’t but you can check it’s document.readyState property and in IE document.readyState is unreliable and you should either inject a deferred script, either poll the DOM untill there are no errors or use an external behavior file. Of course you could always just put a script tag at the bottom of the page, just before the body closing tag, which will fire all attached handlers which is actually the best approach in terms of which way fires earliest (but not too early) according to my tests, but that hardly qualifies as unobtrusive…
  9. (edit, thanks Sobral!) The Event object is not passed as a parameter to the callback but resides in window.event in older versions of IE

Type detection

  1. The typeof operator is almost useless:

    • typeof null == 'object'
    • typeof new String('foo') == 'object'
    • typeof [] == 'object'

    Use Object.prototype.toString instead.

CSS

  1. Although most CSS properties are converted to their JavaScript equivalents in a standard way (characters after dashes are Uppercase, others are lowercase, the dashes get removed), float is an exception: It’s converted to cssFloat in most browsers and styleFloat in IE. Check which one exists and use that.
  2. Getting the current (computed) style of an element is another complete mess. IE uses element.currentStyle[propertyJS] whereas standard compliant browsers use document.defaultView.getComputedStyle(element, null).getPropertyValue(propertyCSS). And as if this wasn’t enough, there are various problems associated with specific properties or browsers, like:
    • IE returns the cascaded values and not the computed ones (for instance, it might return ems for a property that was specified in ems, and not pixels). Dean Edwards has thought a very clever hack to workaround this and didn’t even blog about it (it’s simply a comment in a blog post of Erik Arvidsson’s!).
    • Any hidden (via display:none;) element, yields a width/height/top/right/bottom/left value of zero.
    • auto or normal might be returned for properties that are left at their defaults. For instance, IE does this with width/height for elements that don’t have dimensions explicitly set via CSS.
    • In most browsers, shorthands (like border) will yield a blank string. You’d have to use the most specific property (for instance, border-left-width).
    • Colors will be returned in different formats across browsers. For instance, IE uses #RRGGBB whereas Mozilla uses rgb(red, green, blue).

So, what now?

Never, EVER use a browser detect to solve the problems mentioned above. They can all be solved with feature/object detection, simple one-time tests or defensive coding. I have done it myself (and so did most libraries nowadays I think) so I know it’s possible. I will not post all of these solutions to avoid bloating this post even more. You can ask me about particular ones in the comments, or read the uncompressed source code of any library that advertises itself as “not using browser detects”. JavaScript Libraries are a much more interesting read than literature anyway. :P

Are the facts mentioned above actually 20?

I’m not really sure to be honest, it depends on how you count them. I thought that if I put a nice round number in the title, it would be more catchy :P


Silent, automatic updates are the way to go

2 min read 0 comments Report broken page

Recently, PPK stated that he hates Google Chrome’s automatic updates. I disagree. In fact, I think that all browser vendors should enforce automatic updates as violently as Google Chrome does. There should be no option to disable them. For anybody.

But what about the user’s freedom of choice?

This might sound a bit facist at start, but imagine a world where all browsers would get automatically updated, without the possiblity of an opt-out. If you went online, you would be bound to have the very latest version, regardless of how computer (i)literate you were (Many — if not most — home users that don’t upgrade are like that because they think it’s too difficult for their computer expertise level). Sure, if you were a developer you wouldn’t be able to test a website in older browser versions. But why would you need to do so? If everybody had the latest browser version, you would only develop for the latest version and perhaps for the next one (via nightlies and betas, that could still be separate in that ideal world).

Imagine a world where your job wouldn’t have to involve tedious IE6 (and in a few weeks, no IE7 either), Firefox 2, Opera 9.5 and Safari 3.1- testing. A world where you would spend your work hours on more creative stuff, where you wouldn’t want to bang your head on the wall because you know you did nothing wrong but the ancient browser that you are currently testing in is just incompetent and YOU have to fix it’s sh*t. A world where the size of your Javascript code (and the JS libraries’ code) would be half its size and constantly decreasing as new browser versions come out. A world where you would only have 1 CSS file in most websites you develop. A world where you wouldn’t feel so bad because IE8 doesn’t support opacity, border-radius or SVG, because you would know that in 1-2 years everyone would have IE9 and it will probably support them. A world where designing a website would be as much fun as designing your personal blog.

Doesn’t such a world sound like a dream? Would it harm anyone? Users would browse a much lighter and beautiful web, with a more feature-rich and secure browser. Developers would work half as much to produce better results and they would enjoy their work more.

What about corporate intranets and abandoned sites that won’t keep up?

Oh come on, that isn’t a good enough reason to not make that dream come true! Companies and individuals could be allowed to have an older version of the browser installed as well. They still wouldn’t be able to opt out from the automatic upgrade, but they could apply somehow to have an older version of the browser in the same system as well. Similarly to what happens now with browser betas. People would use the older version to access corporate intranet applications and obsolete sites and the latest version to surf the web. I may be overly optimistic, but I think that if a user had both versions of a browser installed, (s)he would prefer the latest wherever (s)he can. Perhaps another step towards enforcing that would be if the OS prevented an older browser version from being set as the default browser, but I guess that would be too hard to do, especially if the browser in question is not the OS default one.

Other people who agree with me

What’s your opinion?