Thursday, July 15, 2010

Rotating table headers now in 4 of the top 5 browsers

Update May 3, 2012. Demo link fixed. + Firefox 14+ (Aurora, Nightly) no longer skews text. Apparently the CSS Working Group have recently decided that Webkit behavior was better and Mozilla has fixed their code. I think this was a bad decision, but that is how things stand. Other stuff seem to be happening in the CSS WG with regards to skew and I have unfortunately been unable to keep track of this. Note that skewX does not seem to be in jeopardy, though.

A little more than a year ago I wrote about a technique I have developed to rotate table column headers. (If you have not, you had better read that article to understand this one correctly.) Back in May 2009, this could be done in Firefox 3.5 and Safari 4. Now browsers have evolved and it's doable in all major browsers, except Internet Explorer. So, with Firefox, Chrome, Safari and Opera all supporting this, has the time arrived to use this on production sites?

The sad answer is no, there are still a few issues to that needs to be sorted out in my opinion. First of all, one really can not ignore Internet Explorer, and even if we can rotate content using -ms-filter, that is not an optimal solution. I have also seen reports that these filters will not work in IE9 in its strictest standards mode. Removing them, while not adding CSS transformation, gradients and a few more things, will make it near impossible to achieve true cross platform effects. I hope that won't be the case, though. (More thoughts on this in my conclusion.)

Updates to my code

The full demo is at keryx.se/lab/rotating-th/rotate-th-2.html

Today I revisted my code. The first thing I did was simply to slam on -o- prefixed rules, identical to all -moz- rules. The result looked like this. Click the image to see it in full size.

Screenshot of Opera, firefox and Chrome, showing bad alignment

Not nice. Firefox, Opera and Chrome (the 3 browsers I could test on my Linux driven Thinkpad) all got the horizontal position differently. Admittedly, Chrome got a slightly different rule, thanks to a Webkit CSS filter. But this worked as intended in my tests one year ago. My code was largely experimental and not really calculated anyway, so I was not surprised that it broke. It was intended as a proof of concept, not as production ready code.

Before I started to investigate the differences in earnest, I tweeted, and soon Faruk Ateş chipped in and had some helpful thoughts. First we removed my line "top: 1em" for all browsers. Note, that it must be removed. Manually setting it to 0, will still mess things up in Firefox. I suppose that's a bug, since the calculated value is 0 with that line removed…

The line that was removed:

th > span > span {
    …
    top: 1em;
    …
}

Stability issues

Next problem, subpixels. I had used the em unit to set heights and widths. But 1.3em is not the same in all browsers. In my code it's 23.4 pixels in Firefox, but only 23 in Opera and Chrome. The latter two does not translate ems into subpixels. At least not on Linux and Windows. So I made some changes to the code, to use pixels almost everywhere.

th > span > span {
    …
    padding: 9px;
    height: 23px;
    width: 120px;
    …
}
td {
    padding: 5px;
    text-align: right;
    width: 36px;
}

All values above were set in ems in my original version. Now I was getting close to a working version. There was one thing that bugged my designer eye – and I am really not a designer. The line in between table columns did not align perfectly with the column header lines in Firefox. Once again, this was a sub-pixel problem. So I added this rule, explained in the comments:

th > span > span {
    …
    position: absolute;
    left: -0.5px; 
        /* 
          So far only Firefox does subpixel positioning = 
            ignored by Opera, Chrome and Safari.
          But they got this right (visually) in the first place.
          This rule puts the rotated span exactly in place for Ffox
          (tested on Linux and Windows July 2010)
        */
    …
}

Should Opera and/or Webkit add support for subpixel positioning, it is my hope that it will affect their rendering just like it does in Firefox. But this is a fragile hope!

Webkit text skew (not a) bug

Update May 3, 2012. Firefox 14+ now treats text the same way as Webkit.

To make the text as legible as possible it is skewed back to being non-skewed. Let me explain. There are three spans. The outermost is simply an anchor for the middle one, where the real magic happens. That span is rotated and skewed. That leaves the text a bit… skewy(?) To remedy that, I use a third span, only used to skew the text back again.

th > span > span {
    …
    -moz-transform: rotate(-65deg) skewX(25deg);
    -o-transform: rotate(-65deg) skewX(25deg);
    -webkit-transform: rotate(-65deg) skewX(25deg);
    -moz-transform-origin: 0% 0%;
    -o-transform-origin: 0% 0%;
    -webkit-transform-origin: 0% 0%;
    …
}
th > span > span > span {
    /* Rotate the text back, so it will be easier to read */
    -moz-transform: skewX(-25deg);
    -o-transform: skewX(-25deg);
    -webkit-transform: skewX(-25deg);
    /*
      Safari and Chrome won't skew back, so the above
      line is actually redundant right now
      (checked July 2010 on Linux and Windows)
    */
}

I suppose this is a Webkit bug, that needs to be filed. This image illustrates the problem. The red line shows the actual angle of the stroke in the letter "l" (small "L"). The green line shows what angle it was supposed to be.

Text is still skewed in Safari

Screenshot of my table from Safari on a Mac, graciously provided by Matthew Irish. This problem affects all Webkit based browsers, on Windows, Linux and Mac.

Opera text blurriness and zoom bug

Opera gets the skewiness right. (Being a non native English speaker, I love the word skew and will jump at every opportunity to skew it!) However, Opera looses the smoothness of the text, once it has been rotated. It will look blurry. The following image compares Opera to Firefox. The text is not perfect in Firefox either, though.

An even bigger problem with Opera is that it really will mess the text up when zooming the page, to the point where it becomes totally illegible. The image below is zoomed to 300 % and one can not read the text at all, since the bottom (=left) margin has widened and pushed the letters on top of each other.

Messed up text in Opera when zoomed

Gaps between cells in Firefox

The image above illustrates another problem in Firefox, perhaps also caused by subpixel positioning. At some zoom levels small gaps appear between the cells. Note that we are not drawing lines on the actual table cells but a box around the edges of a span. We are just visually emulating rotated table headers.

From previous testing I also found these gaps also when not zooming the page. One has to be really precise in the measurements to fix this. Right now I basically get the visuals right by having the line from one cell on top of the line from the previous cell.

If I'd fine tuned my technique, I think these gaps could be avoided. Not drawing both lines both left and right (= top and bottom in CSS) and extending the top (= right) line a bit might do the trick.

On subpixels

A small aside: It might seem like subpixel positioning is all bad. I believe it generally is a feature, not a bug. I wish all browsers could agree on Firefox' behavior. But in this context it seem to be problematic. I will ping a few people at Mozilla and see what their take on this is.

Conclusions and some thoughts about the future

Please see the top note about things being unstable in CSS WG, when it comes to skew.

I really think there should be a CSS-rule that would make this super easy. Rotating column headers is a really common technique in spreadsheet programs like Excel and LibreOffice Calc. I use it all the time. It would be a great feature for Google and Zoho Docs and similar on-line products. So far, however, the CSS Working Group and browser vendors have shown very little interest.

All browsers display an issue of some kind with my current technique:

  • Killing: Bad rendering of the text in Opera, especially when zooming.
  • Bad: Gaps in Firefox between the cells, when zooming.
  • Slightly annoying: Skewed text in Safari and Chrome (and probably Firefox 14+).

Internet Explorer 9 is a big question mark. My current idea is to capability detect for CSS transforms and replicate this behavior in SVG, if available, or using -ms-filter as a third option. That should cover all bases = MSIE 6-9, Firefox 3.5+, Opera 10.51+, Safari 4+ and Chrome (always at the latest version, at least until it comes to the corporate environment – a subject worthy of a blog post by itself).

Having to limit oneself to pixels as a unit and fixed width for the columns is a major obstacle. For this reason, as well as the Internet Explorer problems, I think that the only sane way of doing this at the moment and the foreseeable is using JavaScript. Perhaps this could be my first official JQuery plug-in. (Please feel free to beat me to it!)

Friday, July 9, 2010

No browser supports HTML5 yet. Part 2. Technology.

In the first post I questioned the perception that a particular browser supported HTML5, whereas other browsers do not, according to some misguided fan boys. I pointed out that browser vendors are quick to claim that a particular feature is supported, when in reality that support is half-baked and far from complete. And that is not a good thing!

History repeating itself

My main gripe with browser vendors not using solid shipping criteria for stable versions, but releasing flawed and incomplete implementations of HTML5, is that it may lead to flawed and incomplete web sites. The message from Google, Apple and numerous others is not, go forth and experiment, but go forth and use. Today! Knowing very well that the HTML5 input range in Chrome or Safari is not accessible, they still encourage actual real world usage. Knowing very well that Chrome exposed the JavaScript form validation API only, and had no real constraints for invalid data, the implementation was shipped – and lo, it looked good in the support charts!

So what happens when the spec changes? And what happens when real world usage will make needed spec changes not an option? Being responsible is way more important than being first. But once again, that does not look as cool on the support charts…

By putting half baked implementations into non-beta software Chrome and Safari actually do harm to the web. Why are we cursing Internet Explorer 6. It was not for lack of innovation and standards support when it first shipped. It is because that standards support was buggy and incomplete – that's right, it was half baked. And now we see Chrome and Safari releasing unfinished implementations as well.

In one way, we are at a better place right now. Chrome is aggressive in its updating of itself and Safari versions also have relatively short shelf life. But when real world web sites appear that lock in to today's versions and break when bugs are fixed, things will not look so rosy any more.

And please consider this. Back in the earlier 90's Netscape released new versions at an equally frantic pace. The web year was supposed to be five months and every web year should mean a major update to Netscape navigator. So JavaScript shipped even long before the implementation was mature, and because of this we are still stuck with some really bad api's and bugs, that could have been squashed given a few more months of time, can not be squashed, because sites soon depended on them to work correctly. As long as Chrome was a niche browser it might not have mattered, but now that it has received a descent and well earned market share, it will matter. (Not to mention the mobile space, where Webkit based browsers are ubiquitous.)

Exhibit A: Web forms

Web forms are really the starting point for all things HTML5. In spite of that fact, it is not until now that work has begun in earnest to implement all new cool form features. Except for Opera, of course, who implemented most of this a few years ago!

The work to get the HTML5 additions to web forms into Webkit is tracked in bug 19264. The work to get it into Gecko is tracked in bug 344614 and on a wiki planning page. The most important part being the shipping criteria. (I subscribe to these bugs to keep myself informed, but then perhaps I don't really have a life…)

I could go on and explain details about what is lacking in browser A, B or C, but I will not make this blog post any longer than necessary. Look at the tracking bugs and see for yourself. At the moment neither Webkit nor Gecko (nor Opera) is nowhere near having a complete HTML5 web forms support. They all lack some features and they all lack accessibility. (The Webkit bug is a bit deceptive, since it does not seem to list all features like the Mozilla bug does.)

Exhibit B: Sectioning elements

Some new HTML5 elements seem really easy to understand. They are not hooked into browser behavior, JavaScript API's or some other esoteric behind the scenes weirdness. They just seem to be turbo-charged divs, divs with real semantic meaning. Furthermore, they are a part of the HTML5 spec that is reasonably mature and thus ripe for implementation in browsers.

Yes, there is one talked about crux. It is not super duper easy to differentiate between article and section. Perhaps the spec will need some further explanations, or perhaps that will be taken care of in the for dummies version.

But there is one further matter, a point that seem to be universally missed. Even by browser makers! And that is the fact that sectioning elements affect document outline and that should in turn be exposed to seeing users through varying sizes on the headings and to non-sighted users through their assistive technologies. Headings are used when scanning a page – both by sighted and non-sighted users. Being able to tell at what level a heading is, is therefore a critical part of any implementation.

The real deal breaker is not if you can set display: block on <article>. The real deal breaker is if you can easily set an <h1> within any sectioning element to resemble <h2>, or setting it to resemble <h3> if it's one step further down in the document hierarchy. Etc.

Being able to style a sectioning element is actually a bullshit claim. HTML5 mandates that one should be able to style any unknown element. That is, a browser vendor could claim that they support the <foobar>, <my_cat> and <steve_jobs_is_god> elements, since according to HTML5, they should! At least in the sense that they make those elements part of the DOM and therefore styleable through CSS.

-moz-any() to the rescue (somewhat)

The only browser to have any reasonable way of styling headers, depending on how deeply nested they are within sectioning content, is Firefox 4, currently in early beta only. This is done through the brilliant any() selector, being implemented, as it should, with a vendor prefix, until all details are agreed upon.

(The hardest part to figure out, before this can go CR, is how this selector should handle specificity. What happens if you mix type, class and id selectors inside one parenthesis?)

Nevertheless, try and write the following CSS selectors so that they work in any browser but Firefox 4:


h1 {}
h2, -moz-any(section, article, nav, aside) h1 {}
h3, -moz-any(section, article, nav, aside) \
    -moz-any(section, article, nav, aside) h1 {}

And so on. You will get tired of typing really quick.

Thus, only Firefox 4 can claim to support HTML5 sectioning elements in any usable fashion. The point of these elements is not that they should serve as styling hooks. We already have <div> for that. The point is that they should affect the styling of headers, and that's simply not doable in a generic fashion in any browser but Firefox – so far!

But Firefox also have a long way to go, since they've not begun on working on the accessibility side of this. Until support for the any selector is universal, these elements can only be used in experiments or with fallbacks, such as always using <h2> when one level down into sections, <h3> when two levels down, and so forth. Actually, this is current recommended best practice.

But by not using <h1> all the time, we are missing out on one of the main advantages of this new outline model, namely cut-and-paste-ability. We still have to re-calculate the heading level depending on what page a piece of content appears. E.g. a blog post might have its heading as <h1> on the dedicated page, but it should be <h2> on the home page of the blog. Sub-headings should be <h2> on the dedicated page and <h3> on the home page, etc.

Until there is universal and accessible support for headers within sections, support charts may say that the elements are implemented and marketing may make a big noise about their presence. But right now, the only way to use these elements is through scripted hacks.

And that, my friends (and all enemies I've made by posting these two posts) is a non negotiable fact.

Exhibit C: <hgroup> and <nav>

This is a no brainer. The point of <hgroup> is to hide the subtitle from the outlining algorithm. Thus there care only two requirements to call this feature supported. Make it available in the DOM. As explained above, that's the easy part. The hard part is the accessibility issue. When a blind user scans through a page by jumping between headers, an <hgroup><h1 /><h2 /></hgroup> should be presented as exactly one heading, not as two. And it is a reasonable expectation that the subtitle is read out along with the main heading. In a perfect world even perhaps prefixed with the word subtitle to indicate that relationship. At least, when jumping to the next heading it should be skipped, since it really is not next, but part of the main heading.

In the same way, the nav element should be presented to blind users in a way that will let them skip over navigation or jump to navigation. (Also a no brainer, really.)

There is no browser on the market that supports thees behaviors. Indeed, to my knowledge, no browser even has begun working in earnest on this. But my point is not that browser X is better than browser Y. My point is that it is premature to claim support for this feature, when indeed one is missing the whole point of that feature.

So, is there no value in using these HTML5 elements?

There might be. First of all, they do no harm. And on that day when browser support really has been properly implemented, you will automatically get added benefits over using a div. Furthermore, they might be picked up by other software than browsers, or browser extensions, like Readability (I love it) and Safari Reader (technically not an addon, but a feature). Presently, this kind of functionality must rely on educated guesswork – some kind of software algorithm that analyzes the page and looks for ids, classes or patterns that usually would indicate the main content of a page. With HTML5 markup that algorithm will be simpler and therefore execute faster.

So this is my point. Knowledgeable web developers can use any HTML5 feature they like today. With progressive enhancement and graceful degradation, perhaps through JavaScript libraries. If you've come this far and think that I am discouraging any use of recent additions to the web stack, you are wrong. Just take reasonable care in how you do it, and do not trust browser marketing! One example of such care is to use WAI-ARIA everywhere, to address the accessibility issues. Since no browser offers built in accessible implementations of HTML5, we must resort to bolt on accessibility.

Browser support for HTML5 is not boolean, and neither should your usage of this be today. Thus can I use HTML5 is a stupid question. It is all about the how you use HTML5 and more specifically, what parts of it you use.

I am not a foe of HTML5 usage – but I am a friend of caution. After all, I'm over 40 years of age!


P.S. Firefox 4 does not look like Chrome, it looks like Opera! And of course there are several reasons behind Chrome's growth in market share.

Thursday, July 8, 2010

No browser supports HTML5 yet. Part 1. The rant.

Yes, you've read that headline correctly. There are so many websites that measure HTML5 readiness in one way or another, and so many marketing pitches that claim HTML5 support for browser X, Y or Z. But the crux of the matter is this. Supporting HTML 5, regardless of definition, is not a boolean proposition. I.e. It's not something you do or do not, it is something you do more or less.

This discussion will consist of two posts. The first is an anti-webkit fan boy rant, probably only useful as self-therapy for me. The second part is my technical discussion about the subject matter at hand.

Rant begins here

Whenever a major browser vendor releases a new version, or preview version, you can bet a month's salary on the fact that comments will appear on forums, Twitter or blog posts that asks does it support HTML5 (it used to be CSS 3). Some other browser is then hailed as if it does, usually Safari or Chrome, since they have either the most obnoxious marketing or the dumbest fan boys(?) And sometimes the comment is made complete in its stupidity by an argument that vendor X should just “use Webkit”.

I do not intend to throw cheap jabs at Webkit, in any incarnation, be it Chrome, Safari, Froyo, S60, Web OS, Nokia WRT, QTWebkit or WebkitGtk. Webkit is a really good rendering engine, or perhaps nowadays more aptly described as the core of a rendering engine. OK, maybe I'd like to throw a jab at Froyo and Adobe AIR for the dumb ass decision not to enable SVG, but that's beside my point, and not Webkit's fault at all.

Other comments like Mozilla is lazy or have stopped inventing are not hard to find either. But it's hard to claim that Opera is not inventing, so non Opera fan boys just tend to ignore them. After all, that makes it much easier to claim originality, even though one has just copied Opera.

I am not saying that Firefox is without it's gang of fan boys. Perhaps they are equally loud and obnoxious, but it's been a long time that they've been in my vicinity. (Or perhaps I am that fan boy?)

Source of confusion number one: Browser vendors

It is reasonable to expect the upstarts to be more aggressive in their marketing, but marketing tends to turn into blatant lies when exaggeration is becoming the norm. Consider this support chart for Safari 5 from Apple:

Apple claiming that Safari 5 supports several HTML5 elements

Source: http://www.apple.com/safari/whats-new.html [checked 2010-07-08]

Problem is, once someone has started to claim support for a feature, even though that support is half baked and incomplete, everyone else has to answer in kind, and claim support even when their implementations are equally half-baked. Or even worse, rush out such half baked implementations to the market to show everyone that they are also a leader.

(I'll explain why Apple's claims are false in part 2 of this discussion.)

Source of confusion number two: Well intended web developers

Why is this a source of confusion? Because we tend to put up demos of new cool technologies that are not really examples of best practice, e.g. even though transformations and transitions work in the latest versions of Firefox and Opera, many demos use the webkit prefix only. Heck, I've even seen demos of rounded corners, something that's been in Firefox since 2004 (3 years ahead of Webkit) that used the only the -webkit- prefix! (Yes, I know there are good examples as well.)

I am not surprised that Apple browser sniffs for Safari in their HTML5 demos – even though I am annoyed at such blatant disregard for best practice. After all, that's not technology, that's marketing. (And yes, I know there are a few things that one can do in Webkit based browsers only, such as CSS Animations (not transformations) – a technology still in need of a valid use case, BTW – and CSS perspectives, but that's also beside my point.)

When the WebGL Quake demo originally worked in Chrome only, thanks to flaws in the demo code, not in Firefox itself, it was claimed that Firefox was ”too slow”, even before such a claim could be tested. That was not marketing (I hope), that was developers not doing their job. And when someone is demoing reflections in Webkit, without at least discussing that Firefox can do the same thing, albeit with a different technique, which is more powerful, BTW, it might be lack of knowledge. But the lasting impression on readers, equally lacking in knowledge, is that Webkit based browsers are soo far ahead, when in reality they are not.

Another example is gradients. They first appeared in Safari and for a while they could not be demoed in any other browser. But since 3.6 Firefox supports gradients as well. Doing an gradient demo today using the webkit syntax only is not only bad practice because it is limiting the demo to a few browsers. It is also cheating oneself and one's audience of the syntax that is much more likely to be the upcoming final W3C standard. I.e. If you are limiting your demo to one syntax only, the Firefox version is the more future proof one, the one web developers really should be looking at in earnest.

A real problem caused by too many Webkit-centric demos on the web, is Microsoft contemplating supporting -webkit- prefixed CSS properties. Luckily they back paddled on that one, but it still serves as a nice illustration of the problem.

To alleviate this problem Mozilla has proposed a set of best practices for demos, that includes being as cross browser as possible, using graceful degradation ,etc. Read (at the end of the post) and learn, people!

Where innovation happens = everywhere

Even Internet Explorer, that I've cursed so many times, did tons of stuff already in the 90's that's only recently have been picked up by others. Yes, there is one big difference. The filters in IE were not being put forward for standardization, but was an attempt to embrace and extend, Microsoft of the 90's primary way of competing in unjust ways. But from a pure innovation standpoint, IE was first in doing many things.

And for all Webkit fan boys I have a home assignment. Please investigate where the following technologies were invented:

  • WebGL
  • HTML5 video and audio
  • Using any element as CSS backgrounds
  • Applying SVG effects on non SVG content
  • Full page zoom
  • Canvas text
  • Compiled JavaScript
  • Hardware accelerated SVG and Canvas
  • Audio Data API

Hint: The answer is not one and the same, but never Safari or Chrome.

I am not saying this to diminish the considerable achievements by Webkit browsers, but wishing for a Webkit monoculture is plain stupid. Just like it was plain stupid to wish for a Gecko based monoculture five years ago – when Webkit hardly was a blip on the radar and had tons of bugs (JavaScript in Safari 2 anyone?). And what if KHTML never had been developed? It could hjave happened since lots of people thought it would be better for Konqueror to switch to Gecko. Well, Webkit is based on KHTML, so if that advice had been heeded, we would not have had Webkit today.

End of rant – sort of

All of the above is not me saying Chrome is a bad browser. It is not. In some ways it's the best browser – but not in every way! My primary reason for not using Chrome in my daily work? I think monoculture is bad and even though I sympathize with Google using Chrome to push the competition into being faster, I do not want to see a world where one company is the dominant player at every tier of the web experience. Such power will inevitably corrupt, no matter how hard the company in question tries to avoid being evil. Add to that a leader that is absolutely clueless about integrity and that by far outweighs the fact that Firefox currently is a few milliseconds behind Chrome in some JavaScript benchmarks.

Oh, yes, I use Linux, so Safari is not an option at all. And Apple is every bit as evil today as Microsoft was in the 90's.

My primary reason for supporting non Webkit based mobile browsers like Opera or Fennec (Firefox) is not that they are clearly superior. In many ways they are not – and again in some ways they are! (At least they do SVG, Froyo!) But once again it comes back to this. Monoculture benefits no one in the long run. For a moment the idea might seem to be appealing – as when developing a specific web app – but holding on to such an idea in the long run is just showing lack of vision and lack of historical knowledge.

To round things off, here is a video (HTML5 video was an Opera idea) of WebGL in Firefox 4 – a technology invented mostly by Mozilla. (Oops! I just gave away two answers in my home work assignment.)

OK, therapy session is over. Glad to have gotten that off my chest. Tomorrow I promise to be productive!