Archive for December, 1969

How well do browsers support CSS Selectors?

The last couple of days have been busy for me. I've spend most of my weekend on tweaking and adding test cases for the CSS Selector compatibility tester. The test comprises of 513 different test cases for each of the 43 selectors. These selectors range from the simplest CSS 1 selectors to the latest CSS 3 selectors.

Before I reveal the results I must explain first that if a browser passes a test, it is not a guarantee that the browser is 100% compatible with the specification. There may be edge cases that are not covered by these test cases. I will continue to add more test cases in the future and I will also look into the ability to perform more dynamic tests. In a later version of the CSS Selector test it would also become possible to test if the browser correctly updates the selectors if the DOM is changed by Javascript.

Also I must note that even a single failed test case will result in a failure for a particular selector. This will skew the results a bit. For example: if you look the number of selectors that pass, Firefox may seem close to Konqueror, but in reality Firefox has not implemented 7 selectors at all, while Konqueror has implemented all, but fails 5 selectors because of a single bug.

The results

Browser Version CSS Selectors Testcases
Internet Explorer 6 10 / 43 243 / 513
Internet Explorer 7 13 / 43 271 / 513
Opera 8.5.4 19 / 43 273 / 513
Opera 9.0.2 26 / 43 292 / 513
Safari current 28 / 43 299 / 513
Firefox 1.0.8 32 / 43 308 / 513
Safari nightly 33 / 43 319 / 513
Firefox 1.5.0.7 36 / 43 314 / 513
Konqueror 3.5.4 38 / 43 508 / 513

As you can see there is currently not a single browser that fully supports the tested CSS selectors. Only Konqueror comes close, it only fails the last 5 selectors because of a bug. It should be no surprise that Internet Explorer 6 performs the worst in this test. It even fails one of the most basic CSS 1 selector: the class selector.

Internet Explorer 7, Opera and Safari seem to contain a couple of bugs in their CSS selector implementations. All three could score a lot better if they would solve these bugs. Firefox is the only browser in which I could not detect any bug in their implementations.

An overview of the bugs in the various browsers

Internet Explorer 7

E[attribute] Fails because it does not consider an empty attribute to be a proper match for the attribute existence selector
E[attribute~=value]
E[attribute!=value]
Fails because it compares the value using a case sensitive comparison algorithm. In a HTML document most attributes values should be treated in a case insensitive way.
E[attribute^=value] Fails because it tries to do an exact match… It should look if the attribute value begins with the string specified in the selector.
E[attribute$=value] Fails because it tries to do an exact match… It should look if the attribute value ends with the string specified in the selector.
E[attribute*=value] Fails because it tries to do an exact match… It should look if the attribute value contains the string specified in the selector.
:first-child Fails because it considers comments as children. So if there is a comment before the first real child, it will not match the right element.

Opera 9

E[attribute=value] Fails because it does not do an exact match. Instead it will check if the attribute value contains the specified string.
E[attribute^=value] Fails because it does not try to match the specified string with the beginning of the attribute value. Instead it will check if the attribute value contains the specified string.
E[attribute$=value] Fails because it does not try to match the specified string with the end of the attribute value. Instead it will check if the attribute value contains the specified string.
:lang() Fails because it only looks at the first characters of the language. The language is either a regular string or two components separated by a dash. In the first case it should do a comparison with the whole string, in the second case it should do a comparison with the whole first component.

Konqueror 3.5.4

E[attribute~=value]
E[attribute!=value]
E[attribute^=value]
E[attribute$=value]
E[attribute*=value]
Fails because it compares the value using a case sensitive comparison algorithm. In a HTML document most attributes values should be treated in a case insensitive way.

Safari

:last-child Fails because it also matches elements that are not the last child of a parent element. Apparently this selector is evaluated during the composition of the DOM tree. Every element is at one stage the last child of a parent element.
:only-child Fails because it also matches elements that are not the only child of a parent element Apparently this selector is evaluated during the composition of the DOM tree. Every first element is at one stage the only child of a parent element.
:lang() Fails because it does not detect the language property that is inherited from parent elements.

Want to test for yourself?

Well, you can head over to css3.info and test for yourself. Joost de Valk just opened up the test to the public.

Javascript based CSS selector compatibility tester

Joost de Valk let me know that I won the CSS3 summer contest over at css3.info. I created a Javascript based CSS selector compatibility tester. It surprised me a bit because I never thought my entry was a serious contender – it just created it to see if it could be done.

The basics turned out to be very simple to do, but getting it to work on more than one browser was a bit more work. The idea is that a small Javascript object loads a number of small standalone testcases in iframes and tests the embedded CSS is properly evaluated. It basically uses a CSS selector to set a background color and tests if the computed style contains the expected background color. It is also possible to do negative tests, which is also important to properly tests the behavoir browsers.

I’m still tweaking it a bit, but Joost will make the code public in a couple of days over at css3.info.

Enabling the debug menu on Safari for Windows

I’ve been playing a bit with the new Safari for Windows and found a way to activate the debug menu that Mac OS X web developers were already used to.

You can enable the debug menu by editing the Preferences.plist file which you can find in the C:\Documents and Settings\Your Username\Application Data\Apple Computer\Safari directory. It’s just an XML file. Use your favorite text editor to open it.

Then add the following key at the bottom, just before the final </dict> and </plist> elements:

<key>IncludeDebugMenu</key>
<true/>

Then restart Safari and you're done!

One more thing… Safari for Windows

I was going to write an article about the WebKit platform on Windows. About how the development of Swift has stalled and that the developer decided to move to the Mozilla Gecko engine while WebKit becomes more stable.... I was going to write about Apollo Adobe AIR and how you could use the build-in WebKit engine to easily build your own WebKit based browser in less than 30 lines of code. I was going to write about that Adobe already did the hard part and build a very basic browser called Scout...

I guess I can start all over. Steve Jobs just announced that Apple will bring Safari to the Windows platform. A public beta is available for download now.

The importance of a Windows browser based on WebKit – the rendering engine used by Safari - should be apparent for every web developer. If you wanted to make sure your site works on Safari and if you don’t own a Mac you had to rely on friends or one of those screenshot services. Alternatively you could use Swift or Scout for testing the basic functionality and rendering of the WebKit engine.

Testing for Safari has just become a whole lot easier and cheaper. You do not need to own a Mac any more to test how Safari renders your site. Nor do you have to work with some buggy or limited substitute. You can now test your sites in the real thing – Safari for Windows.

Some screenshots:

I’m back

I have been neglecting my weblog for a while. It's not that I haven't had any ideas or events to write about. On the contrary, life has been extremely busy lately. On April 27th I got married – which took a lot of preparation but was definitely worth it. I also moved out of my old apartment and my wife and I are now living in a brand new house of our own. Things are finally settling down and I hope to get a bit more time to work on some of the ideas I had over the last couple of months.

I also met Scott Switzer, the leader of the Openads project, last April. He flew in from London and he explained how the project was doing in my absence. Openads is a continuation of phpAdsNew for which I was the project administrator and lead programmer back in 2001 up to 2003. We talked about a lot of interesting subjects and it still amazes me that this little project that I was involved in grew into something this big.

We also talked a bit about the current user interface of Openads – which hasn't changed at all over the last couple of years. Scott told me that most of the users that are also familiar with competing products favour the interface of Openads, simply because it is easy to use and still very powerful. Unfortunately it has also become technologically dated. When I was involved, we used to mix the PHP code with the HTML. Fortunately a lot of work has been done on separating the code from the user interface. But still, if you look at the HTML code, I can't help but feel a bit of shame.

Layout tables, spacer images, in-line Javascript event handlers– after looking at the code it definitely feels like I have been transported back to a time when standards were still an utopian idea and Internet Explorer was still the reigning champion of the World Wide Web. Unfortunately these problems are not only visible to the developers.

A regular user does not care what technology is behind the interface that he uses. He does not care that the HTML does not validate. Sometimes he may not even know what HTML is. He only cares about the end-result and in the case of an user-interface, the usability. What determines the usability? Well, one thing is the layout – and that is still pretty good for Openads - but also the speed of the application. A regular user certainly cares about the 'snappiness' of the interface. If an interface feels slow it interrupts your workflow and stops your train of thought.

By moving over to a CSS based layout you can easily strip off half of the HTML, perhaps even more. All of those spacer images are also not necessary any more. And by using CSS we can also eliminate most of the images we are currently using for the graphical design. Next we can drop all of the in-line Javascript and event handlers from our HTML code and move them to lightweight external files that automatically attach the right event handlers to the correct DOM nodes. Finally we can do away with all of those different image files by creating one large file that contains all of our icons and use the CSS sprites technique for showing an icon. All techniques that are quite common today, but were still largely unknown (to me) when I created the original interface.

My estimate is that we can reduce the data that is transmitted for every screen in our interface by at least three-quarters. Now imagine what we can do for certain screens if we also started using AJAX for loading datasets.

Our main navigation is currently using a table that is essentially a collapsed tree that can be expanded. If you want to find a banner you expand the advertiser that owns the banner and then find the correct advertising campaign and expand that to reveal the actual banners. Every time you expand or collapse an item a whole new HTML page is retrieved from the server. This is certainly not necessary any more. We can could easily use AJAX for loading only the information that needs to be inserted into the table when we expand an item. For collapsing an item we could simply temporarily hide it, and if we need to expand it later on, we can make the hidden data visible again, without having to load the exact same data twice.

When I talked to Scott, we also spoke about getting involved with Openads again. I haven't made a decision yet, but I do kind of look forward to the prospect of working again on the interface. It's something I spend a lot of time on previously and it is still something I am proud of – even though I have some mixed feelings about the technical implementation. Even if it turns out that for some reason I will not get back involved, Scott certainly left me with the feeling that I left the project in very good and capable hands.