Quantcast
Channel: Generated Content by David Storey

Get help faster, by reporting better issues

$
0
0

I have been spending quite a bit of time recently helping out with compatibility issues on sites such as StackOverflow and the MSDN forums. It is often difficult to give helpful advice, as the reporter doesn’t give sufficient details to debug the problem. Instead of repeatedly typing the same message in each thread, I’ve distilled some points here, that may guide you when reporting your web development woes. Taking some time to stop and think, and put yourself in the shoes of the person that will read your report, will help you create better reports, and you’ll receive faster and better quality feedback.

Avoid common issues

A few quick checks can spot the low hanging fruit that you may have overlooked:

  • Check the error console of your browser’s developer tool. Especially if it is a JavaScript issue.
  • Validate your HTML and CSS. Lint your JavaScript. It just takes a mismatched end tag, or missing semi-colon to wreak all sorts of havoc.
  • Problem in IE? Check the F12 tool to make sure your page is using the latest document mode. IE can default to using an earlier version of the engine.

Sharing your problem

If you are still having issues, it is time to look for help. Follow the next few steps to improve your chances of getting helpful feedback.

Step 1: Give a way to run the code you are having problems with

If you don’t give people a way to run your code, it can be very difficult to find the issue you are experiencing. An inline code snippet in the post often doesn’t help, as the issue may not even relate to that code, and it is not possible to experiment with the code to try out different theories.

At worst case, link to the actual page you are developing. If you really want to be helpful, make a reduced test case, which only includes the minimum amount of code that still exhibits the problem. For example, if the issue is with your login form, you can probably remove all the HTML around it and the CSS that doesn’t apply.

There are a number of online tools such as JSFiddle that allow you to host small snippets of code. If possible use one of these. This allows us to edit the code and link back to the result. Popular tools include:

Step 2: Concisely explain the issue you are having

No need to tell a story about what you ate for breakfast. Include the following details:

  • Short description of the issue. Keep it as short as a tweet if possible
  • Steps to reproduce the issue. Even if obvious to you
  • Result you are expecting
  • Actual result you are seeing
  • A screenshot if the issue is visual
  • The browser(s), version(s), and operating system (if applicable) where you’re seeing the issue
  • Any other essential supporting information

Step 3: There is no step 3

Sit back, relax, and wait for a reply. If you work out the issue before anyone replies, report back your findings. It saves someone wasting their time dealing with your issue, and will help anyone else that runs into the same problem as you.

Stumbled across a browser bug?

Often it isn’t your fault. It’s the browser. If this is the case, remember to report the bug with the browser vendor(s) in question. If they don’t know about the bug, they can’t fix it. Luckily, if you followed the steps above, most of the work has already been done, and you can copy and paste your excellent report into the bug tracking system of the browser vendor in question. But, remember to search first to see if the same issue has been reported.

Lea Verou has an excellent article on how to report browser bugs.

Here are the location of the bug trackers:


Finer grained control of hyphenation with CSS4 Text

$
0
0

CSS3 Text provides the ability to apply hyphenation to text, via the hyphens property. While this is all well and good, it doesn’t provide the fine grain control you may require to get professional results. For this, let me introduce to you CSS4 Text.

Applying bog standard hyphens

Many of you are probably aware of the hyphens property, and what it is used for. It has long been considered a bad practice to justify text on the Web due to the rivers it tends to leave between words. Hyphenation largely solves or reduces this problem. It is also easy to apply:

p {
    text-align: justify;
    			    			
    -webkit-hyphens: auto;
    -moz-hyphens: auto;
    -ms-hyphens: auto;
    hyphens: auto;
}

Also, remember to set the language (using the lang or xml:lang attribute, so that the browser knows which hyphenation rules to use.

You can also use the manual value, which will hyphenate words only when you specify it, using the soft hyphen (­), or regular hyphen.

Browser support is mixed. Firefox, Internet Explorer 10, and Safari support hyphenation, while Chrome and Opera don’t. Chalk one up for the differences between WebKit browsers list.

Problems with hyphenation

While hyphenation reduces the rivers flowing through your text, they lead to a different issue. That of ladders. In typography, ladders are when more than two hyphens appear in a row at the end of a line. It becomes visually distracting, and makes the text harder to read. Especially when using short line lengths, such as with multi-column layout.

Applying more control with CSS4 Text

The CSS4 Text specification (warning: work in progress) provides a number of ways you can optimise how hyphens are applied. While they are no substitute for manually typesetting and hyphenating your text, it does provide you with much more fine grained control, and can improve the readability of your justified and hyphenated text.

Limiting the number of hyphens in a row using hyphenate-limit-lines

The hyphenate-limit-lines property allows you to specify the maximum number of lines in a row that a word will be hyphenated. The general rule of thumb is that two consecutive lines is the ideal maximum:

hyphenate-limit-lines: 2;

This property is currently supported by IE10 and Safari, using the -ms- and -webkit- prefix respectively.

You can check out my hyphenate-limit-lines demo to see this in action. You will need to use one of the aforementioned browsers to see any difference between the two blocks of text. If you do not see three or more hyphens in a row for the first example, you can resize the width of the browser window. You should see that the second example never has more than two hyphens in a row.

demo showing hyphenate-limit-lines in action

Limiting the word length, and number of characters before and after the hyphen.

You usually don’t want shorter words to be hyphenated as it makes them harder to read. Similarly, you often don’t want too few characters left on a line before the hyphen or pushed to the next line after the hyphen. I don’t think there is a hard and fast rule for the ideal limits, and it is more based on what looks best for your content. I’ve seen a six character word limit, with three character minimum before the break, and two after, recommend. I’ve seen good results with this, but your milage may vary.

You can set these limits with the hyphenate-limit-chars property. It takes three space separated values. If all are set, the first is the minimum character limit for the word before hyphenation, the second is the minimum characters before the hyphenation break, and the last is the minimum characters after the hyphenation break. If the last value is missing, it is set to the same as the second. If only one value is supplied, the last two are set to auto. If the auto keyword is used (or implied), the user agent picks the best fit based on the current layout.

The following example sets a six character word limit, with three characters before the hyphenation break and two after:

hyphenate-limit-chars: 6 3 2;

Support is currently limited to IE10 only, using the -ms- prefix.

You can see this in action in IE10 in my hyphenate-limit-chars example. Again, resize the width of the window to see how each example behaves differently. I have manually underlined the words in the second example that have the potential to be hyphenated (six characters or more). They will not always hyphenate, as it may not be possible to apply the hyphenation break in a position that will leave enough characters before or after the break.

demo showing hyphenate-limit-chars in action

Setting the hyphenation zone

When using hyphenation, there is a specific zone that a word needs to fall in at the end of a line before it is considered for hyphenation. With the hyphenate-limit-zone property, you can manually specify the width of this zone.

Whether or not a word falls into the boundary is calculated before justification is applied (i.e. as if text-align: left was applied when using left to right languages). If a word falls into the hyphenation zone, no hyphenation will be applied on that line. If the last word on the line falls outside the zone, the word on the next line is brought up to the current line and hyphenated (unless any other hyphenation limits prevent it from doing so).

The hyphenation zone is specified using a length value or a percentage. In the following example it is set to 40px:

hyphenate-limit-zone: 40px;

Support is currently limited to IE10. Open the following hyphenate-limit-zone example in this browser to see it in action. I’ve hi-lighted where the zone would be in each example. In the first, third and fifth examples, no hyphenation zone is set, but it shows clearly which words would fall in or out of the zone before justification and hyphenation are applied.

demo showing hyphenate-limit-zone in action

Other, unsupported features

There are a couple of additional properties, that are not supported in any browsers currently.

The first is hyphenate-character. This accepts a string that specifies the character used to hyphenate. For example, the regular hyphen character (which is the default so doesn’t need specifying) can be set using:

hyphenate-character: "\2010";

I’m not sure why you would want to set a character other than the default one used by the language in question, but I guess there could be some use case if you’re getting creative.

The other unsupported property is hyphenate-limit-last. This specifies if hyphenation is applied on the last line of an element, column, page, or spread. The none keyword applies no restriction, the always keyword does not apply hyphenation on the last line of all the aforementioned cases. The spread keyword doesn’t apply hyphenation to the last line before a spread break, page restricts this to spread breaks and page breaks, while the column keyword restricts it to spread, page and column breaks.

hyphenate-limit-last: column;

Tying it all together

While each of the examples shown only use one of the hyphenate-limit-* properties, they can be combined to apply greater control. Unless you’re an hyphenation expert (I’m not), you can often get the bed results by experimenting with the various properties to suit you specific content. Different styling such as line lengths, justification, columns, word spacing, letter spacing, text size, etc. can have a big difference on how the text is hyphenated, and how much massaging you need to apply. Just remember not to go overboard with restricting hyphenation, or you’ll end up with the original problem you were using hyphenation to avoid; the large rivers of white space between words.

Vertical text with CSS 3 Writing Modes

$
0
0

Languages with latin-based writing systems such as English are typically written left to right, and from top to bottom. However, there is a whole different world of writing modes out there. CSS3 Writing Modes allows you to use these in your web sites. Read on to find out what you can, and can not use right now.

Introduction to writing modes

If you’re from anywhere outside of East Asia or the Middle East, it is likely that the writing mode your are most intimately familiar with is those that go from the left edge of the page to the right (line direction), and from the top of the page to the bottom (block direction). Examples of scripts that use this writing system include Latin (e.g. English, French, Spanish, etc.), Greek, Cyrillic (Russian, Ukrainian, Bulgarian, etc.), and Brahmic scripts such as Devanagari, Thai, Tibetan, and so on.

In the Middle-East (as well as North Africa, and Pakistan), the Arabic script is common, while in Israel the Hebrew script is used. Both of these scripts are written from right to left, rather than left to right as in Latin. What they do have in common with Latin scripts is that the lines progress down the page. If you look at a site set in Hebrew or Arabic, they tend to look like a mirror image of what one might expect if you come from a country that uses the Latin alphabet.

Things get a bit more complex when you look at CJK (Chinese, Japanese, and Korean), traditional Mongolian and other languages that can be written in vertical orientation. The key word is can. If you look at almost any Chinese or Japanese web site, you may notice that it is most likely written from left to right and top to bottom, just like Latin languages. While this is prevalent on the web, traditionally—and still in many printed publications—these languages were written with a line direction from top to the bottom of the page, and a block direction that goes from the right hand side of the page, to the left. Mongolian on the other hand uses the same top to bottom orientation, but the block direction goes from left to right.

I suspect one of the reasons why vertical text isn’t so prevalent on the web is that there hasn’t been high quality support for it in web browsers, and operating systems and applications in general. I would also guess there could be usability issues with scrolling. Vertical scrolling has traditionally been easier than horizontal scrolling, and you don’t want to keep scrolling up and down the page for each line. Multi-column layout on the web has similar scrolling issues. I’m mainly guessing though, as I’m not much more than a rookie in terms of when and how to use vertical rather than horizontal text in East Asian languages.

How to apply writing modes on the Web

In actual fact, we’ve been able to use vertical text longer than you might think. IE 5.5 added support for this feature, and support was upgraded in IE8. At the basic level, the support problem was that of other browsers. Things are a bit different now, as WebKit also has support. I suspect this is due to the demands of ePub for e-books, where WebKit is popular, and vertical text for the Japanese market is a key feature.

writing-mode

The property you need to use is writing-mode. The specification includes three values. While WebKit supports these values, IE support predates the latest version of the spec, and instead uses the values that were used in an older version and originate from SVG 1.1. While this isn’t ideal, they map well and work more or less in the same way.

IE supports the writing-mode property with the -ms- prefix (IE 8+) and without (since IE 5.5 when prefixes were not common), while WebKit requires the usual -webkit- prefix.

horizontal-tb

The horizontal-tb value is used for horizontal scripts with a block direction that goes from top to bottom. This is the default value, so you probably don’t need to specify it, unless you’re overriding a previously set value.

You’ll notice that the horizontal part of the keyword doesn’t specify the direction of the line of text. This can be set (if it hasn’t been already) by the good old direction property. Left to right uses the ltr keyword, and right to left uses the rtl keyword.

For IE there are two different values. Instead of using the direction property to specify the line direction, it is specified in the writing-mode value. left to right, top to bottom uses the value lr-tb, while right to left, top to bottom uses rl-tb.

Here is an example setting left to right, top to bottom text. I’ve included all prefixes, so it will also work if IE updates it’s syntax or Firefox adds support:


-ms-writing-mode: lr-tb;
-webkit-writing-mode: horizontal-tb;
-moz-writing-mode: horizontal-tb;
-ms-writing-mode: horizontal-tb;				
writing-mode: horizontal-tb;

While for right to left, top to bottom, the following code is needed:


-ms-writing-mode: rl-tb;
-webkit-writing-mode: horizontal-tb;
-moz-writing-mode: horizontal-tb;
-ms-writing-mode: horizontal-tb;
writing-mode: horizontal-tb;

direction: rtl; /* not specified as part of writing-mode property in standard syntax */

vertical-rl

This is where things get fun. The vertical-rl keyword is used to make the line direction switch in vertical mode, with a block progression from right to left. This is the value you will want to use for vertical layout in CJK languages. You do not need a direction property here as there are no known languages that uses bottom to top lines (unless you’re mixing scripts, such as embedding Arabic inside CJK text, but that is a whole different story).

IE supports this using the older tb-rl value:


-ms-writing-mode: tb-rl; 
-webkit-writing-mode: vertical-rl;
-moz-writing-mode: vertical-rl;
-ms-writing-mode: vertical-rl;
writing-mode: vertical-rl; 

vertical-lr

If you want to use vertical Mongolian text, you’ll want to use the vertical-lr value, or tb-lr for IE. Lines go from top to bottom like CJK languages, but they flow from the left to the right of the page.


-ms-writing-mode: tb-lr;
-webkit-writing-mode: vertical-lr;
-moz-writing-mode: vertical-lr;
-ms-writing-mode: vertical-lr;
writing-mode: vertical-lr;

Writing-mode demos

Demo of writing modes in action

You can see all four of these writing modes in action (if you’re using a modern version of IE or WebKit-based browser) in my writing modes demo. I’ve used English text in each example, but you should get the basic idea. The right to left example may be confusing though, as the text (except final punctuation and list markers) looks left to right, but right aligned. The reason is that when using Latin characters inside right to left text, they keep their left to right orientation. This is known as bi-directional text, or Bidi, but that is a discussion for another day).

Although vertical layout is primarily for languages that are naturally displayed in this orientation, Latin-based languages can also sometimes be used vertically. Usually due to lack of available space, or for stylistic reasons. Think of the spine of a book, labels on the 𝑦 axis of a graph, or those fancy vertical signs you see run down the side of theatres and other such establishments. In all but the latter case, each glyph is usually rotated 90° clockwise along with the line, so that it is displayed on its side, rather than its natural orientation. That is the default behaviour when using latin characters in vertical text using CSS.

Demo using vertical text to save space in a table heading

I’ve made a demo taking advantage of this behaviour, where I’ve rotated text in a table header to save horizontal space. View the writing-mode property support demo in WebKit or IE to see this in action.

One thing you should be aware of with the previous demo is that I had to add a span (or another element) inside the th for the vertical orientation to apply in WebKit. In IE this was not needed, but the header cell didn’t resize after rotation, leaving white space. I suspect it is a bug in both browsers, but with the way tables work, it is anyone’s guess (or at least, someone smarter than me about such things). The spec mentions that writing-mode does not apply to table rows, row groups, columns and column groups, but does not mention individual table cells. Adding an element inside the cell works in both browsers however, so this technique is viable if you don’t mind an extra element.

Demo of Japanese text in vertical orientation

Finally I’ve made a vertical text demo using Japanese text. Here you can see the vertical text writing mode used for it’s main intended purpose. Check out the Japanese vertical text demo in IE or Chrome.

The rules for vertical Japanese text are far more complex than I could ever hope to understand while working on this post, so there may be a number of issues that would look wrong to native eyes. After checking with Tomomi Imura, one such issue is with how the latin digits are rotated. In Japanese vertical layouts, these digits often keep their horizontal orientation, but with special rules, such as centring the glyph (central baseline in CSS terminology) rather than using the alphabetic baseline (the left edge of the line in top to bottom, right to left text). If two digits are found together, they are often combined side by side as if they were one glyph (know as tate-chu-yoko). While latin digits often keep their horizontal orientation, alphabetic glyphs can be rotated (as is the default) or keep their horizontal orientation. I’ve no idea what the rules are here, or if it is entirely stylistic. The main thing I have noticed is that runs of uppercase Latin characters are often set in the horizontal orientation, while lowercase characters are often in the sideways orientation. The next section will cover what we can and can’t do to correct these issues.

Changing the orientation of glyphs in vertical text

If you want to keep glyphs from scripts such as latin from rotating when in vertical mode, you can use the text-orientation property, with a value of upright:


-ms-writing-mode: tb-rl; /* old syntax. IE */
-webkit-writing-mode: vertical-rl;
-moz-writing-mode: vertical-rl;
-ms-writing-mode: vertical-rl;
writing-mode: vertical-rl; /* new syntax */
			
-webkit-text-orientation: upright;
-moz-text-orientation: upright;
-ms-text-orientation: upright;
text-orientation: upright;

This is currently only supported in WebKit browsers. You can check it out by viewing an updated version of the previous Japanese demo, using text-orientation: upright.

image

This property applies to all glyphs, but as Japanese characters are already in the horizontal orientation, you will only see a difference with the Latin characters.

As you may want to keep some non-Japanese characters in the default sideways orientation, it may be best to add spans around the glyphs you want to keep upright.

The eagle-eyed among you might notice an issue in WebKit browsers. While the digits are kept horizontal, they are still aligned to the alphabetic baseline, rather than centred to the central baseline. Chrome is also slightly clipping the text. Every glyph is also rotated, which is incorrect. Glyphs such as hyphens (-), and brackets and braces ({}()<>) should be left sideways, otherwise they look very odd.

While this is where support stops for this property in Safari, Chrome also supports the sideways and sideways-right keywords. The sideways-right value rotates the glyphs 90° clockwise when using vertical layout. This is the same as what is applied by default to horizontal scripts such as Latin. It will however also rotate glyphs that are usually displayed horizontally in vertical layout, which will probably look odd to anyone that can read those languages.

The currently unsupported sideways-left keyword rotates the glyphs 90° anti-clockwise. The text line is also rotated 180° as if the text is read bottom to top, instead of top to bottom. Think of how labels on the left hand side of the 𝑦 axis of a graph are often displayed.

Combining glyphs side-by-side in vertical text

While in vertical text glyphs progress down the page, rather than side by side, sometimes you may want to have two (or maybe more?) glyphs side by side, such as the aforementioned case where two digits are combined.

For that particular use case, we can use the following rule:


text-combine-horizontal: digits 2;

The digits 2 value (actually the 2 can be omitted, as it is the default), says that if two digits (U+0030–U+0039) or less are found in a row, combine them in the space used for 1 character (a width of 1em). Unfortunately, while this would solve our problem, it is not currently supported anywhere, to my knowledge.

The all keyword works the same way, but tries to apply it to the entire textual contents of the element. You can imagine that if you apply this to an element with more than a few characters, it is likely to not be able to do that. The spec says that it must try to fit the contents into 1em, but can use any method to do so. So I’m not exactly sure what would happen if the contents don’t fit. Craziness is my best guess.

The final value is none, which is the default. It is easy to imagine what this does (nothing, except default back to nothing if the element was previously doing something).

Some unexpected things to take into account when using vertical text

If you expect everything to work as if you just rotated the element and its children 90° using CSS transform rotate, then there are a number of things you should be aware about.

Height, width, and the box model

If you rotate an element 90° clockwise with a transform, the width of the element looks as if it is the height (width now goes from top to the bottom of the screen). With vertical text however, the width and height remain the physical width and height. That is, if you specify the width and height, the text lines will rotate when specifying vertical text, but the width and height of the element will stay the same.

Similarly, margin/border/padding-top will remain the physical top of the element, rather than the right side when an element is rotated 90° clockwise. A key difference here is margin collapsing. As text flows across the page, margin-left collapses instead of margin-bottom when using vertical-rl, and the right margin collapses when using vertical-lr.

The positioning properties such as top, right, bottom, and left also still refer to the physical edge of the element’s margin box. The top property still refers to the top edge, rather than switching to the physical right edge.

Text-align, vertical-align, text-decoration and floats

While the box model doesn’t rotate, text-align, vertical-align, text-decoration and floats do. Left aligned text will become top aligned, right aligned text will be bottom aligned. As you may have guessed by now, float: left will float the element to the physical top, while float: right will float to the physical bottom.

Vertical-align: top will align to the physical right of the cell when using vertical-rl and the physical left of the cell when using vertical-lr. Similarly, the underline value of text-decoration will be drawn along the physical left edge of the line box using vertical-rl and the physical right side when using vertical-lr.

Due to the above, the vertical-align property is unfortunately named, as are the left and right values of text-align and float. For text-align, two new abstract keywords have been defined, named start and end. The start value is the equivalent of left and end is the equivalent of right (except when using the right to left line direction (e.g. Arabic or Hebrew), where start is right, and end is left). This makes their use less confusing, as they always apply to the start and end of the line box, no matter what orientation is being used. These are currently only supported by WebKit and Gecko. Similarly the abstract values for top and bottom are over and under respectively.

All of this might be easier to understand with a diagram, so here you go:

Abstract and physical dimensions and directions

Flow relative directions

The following diagrams show the mapping between the flow relative abstract (yellow) and physical (green) directions, as well as the dimensions of the element. The physical directions always stay the same, while the logical directions change depending on writing mode, direction and text orientation.

horizontal-tb ltr (left to right, top to bottom)

horizontal-tb rtl (right to left, top to bottom)

vertical-rl (top to bottom, right to left)

vertical-lr (top to bottom, left to right)

Line relative directions

The following diagrams show the line relative physical (blue) and abstract (yellow) directions. You will notice that the physical line-relative directions do change when the text orientation is flipped from sideways-right to sideways-left.

horizontal-tb (top: ltr, bottom: rtl)

vertical-lr and vertical-rl

  1. text-orientation: sideways-right, direction: ltr
  2. text-orientation: sideways-right, direction: rtl
  3. text-orientation: sideways-left, direction: ltr
  4. text-orientation: sideways-left, direction: rtl

IE11: what we know and what we can speculate

$
0
0

A build of Windows–codenamed Windows Blue–was leaked onto the internet recently. What does this tell us about what is coming in IE11?

First a disclaimer: the information in this post all comes from public sources. I have not run the leaked build myself, and although I am helping Microsoft with the userAgents community, I have no inside knowledge of current or future plans for IE11. This post is a distillation of these various posts, and my personal opinion or speculation.

A new identity

The first news about IE11 was that it has a new user agent string:

Mozilla/5.0 (IE 11.0; Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C; rv:11.0) like Gecko

There are two significant changes to this string:

  1. MSIE has been replaced by IE
  2. A like Gecko token has been added

The former is clearly to avoid getting the code branch designed for IE when sites use browser sniffing (a practice that causes untold damage). These are almost certainly designed for older versions of IE, such as those that don’t support addEventListener or other standards-based features. IE is saying it no longer wants legacy IE code. It wants standards-based code.

The latter has caused some confusion. It was reported that IE is pretending to be Firefox. This is only partially true. It is correct that Gecko is the name of Firefox’s rendering engine, but like gecko was the token added by WebKit. The reason why WebKit added it, and now also IE, is sites often didn’t say “do you want the IE-specific code or the standards-based code?” They often instead said: “Are you IE or are you Gecko?” It is not a question of if you support the standard, but if you are called Gecko. Even though WebKit is widely popular (as is IE), these sites and practices still persist, so the token is still needed. IE is basically taking a page out of WebKit’s playbook, which is asking for the Gecko branch. What IE will not get with this string is the sites specifically sniffing out WebKit. I suspect it doesn’t want these, as these code paths probably often include WebKit specific code or prefixes. Especially on mobile sites. Pretending to be Gecko gives less risk of vendor specific code, as it is not a reliable way to detect just Gecko-based browsers due to WebKit making the same move.

Changing the UA string is not the only way current builds of IE11 are cloaking their identity. The appName property now returns Netscape rather than Microsoft Internet Explorer. WebKit and Gecko already do this. IE and Opera/Presto were there only ones that didn’t identify as Netscape, but as the latter is switching to Blink, everyone is now Netscape.

Finally on the identity front, IE11 is now cloaking support for document.all. If you use feature detection to detect support for this feature, IE, like Firefox, WebKit, and Opera, will say false. Why? Isn’t object detection the holy grail? Yes, but, developers were ::drumroll:: using object detection to browser sniff. What? While working on Opera compatibility, I’d often (more times than I can count) see code like this:

var isIE = null;
if (document.all) {
 isIE = true;
}

if (isIE) {
  // do some crazy IE specific stuff with ActiveX, or filters or so on
} else {
  // use standards based code
}

Now all of a sudden, if you support document.all, you are obviously IE and want to use totally non-related code. Cloaking support for document.all avoids this.

The other possibility is to remove support entirely, but sites would often use it without testing for support, and not have an alternative path, leaving sites broken. Cloaking generally gives you the best of both worlds, and is now an ubiquitous practice amongst browser vendors.

Update: IE11 now cloaks support for the ActiveXObject object, almost certainly for the same reasons as already outlined.

You have to bear in mind that all these changes happened in a leaked build of IE11. It could be that the developers are just experimenting to see if the identity changes break more than they fix. It should not be held as gospel that these changes will make it into the final version of IE11.

There is one key significance to all this. Microsoft is telling the world; IE has grown up, it is standards compliant and is capable of supporting the standards branch on sites. We no longer want the IE code paths. I’m inclined to agree. IE10 is a huge step forward, and IE11 probably will be able to go toe to toe with the competition in terms of standards support.

ES6 support

A few features from ECMAScript 6 (the next version of JavaScript) appear in the leaked builds:

__proto__

The __proto__ property was non-standard, and looks really ugly to my eyes. It references the prototype of the object. The spec represents this as [[Prototype]], but there was no standards-based way to access this. ES6 changes this by standardising __proto__.

IE11 now supports this feature, along with Firefox, WebKit and Opera.

WeakMap

A WeakMap is a key/value pair map, where the key is an object, and if there is no longer a reference to the key object, it will be available to be garbage collected. Due to this behaviour, WeakMap keys are not enumerable. One specific use case for WeakMaps is to keep references to DOM nodes. When a DOM node is deleted from the document, it can be garbage collected and thus automatically removed from the map. This can reduce memory requirements.

Support for WeakMap is included in IE11, Firefox, and behind a flag in Chrome.

Update: Set

Support for Set objects has appeared in the latest leak. A Set holds a collection of values, but unlike data structures like an Array, a Set can not contain duplicates. For an excellent look into Set objects, check out Nicholas Zakas’ blog post ECMAScript 6 collections, Part 1: Sets.

Support for Set includes IE11, Firefox, and Chrome (behind a flag).

Update: Proprietary Mozilla APIs

Along with __proto__ which was until it was recently standardised, was a proprietary Mozilla invention, IE11 has added support for __defineGetter__ in the latest leaked build. This is a legacy feature, which has been standardised as Object.defineProperty in ES5. Why add a legacy feature when there is a standard that replaces it? One reason: compatibility. There is a bunch of code out there that uses __defineGetter__ without a non-legacy IE fallback. One of the reasons Opera added __defineGetter__ is that some frameworks and sites (Atlas being one I remember) would use it to add functionality.

In the case of Atlas it implemented everything using legacy IE API, and the “standards” based path was basically a polyfill for Firefox using __defineGetter__ to implement those APIs. If you didn’t support it, you just received a broken site. Now, that was a pretty backwards was to develop, but the feature was (and probably still is) used extensively. I suppose the IE team are seeing similar issues to the Opera team did, especially now they’re changing the UA string and cloaking support for legacy IE features.

WebGL

If there was ever a poster child that trolls and haters would use to claim IE is still not a modern browser, it would be WebGL. I’m personally not convinced it is the most important feature for the average web developer, as it is a complex technology to learn and use, and the average web site generally doesn’t need 3D graphics.

On the other hand, where WebGL is useful, it is often critical. Games are an obvious example. With the recent announcement by Mozilla and Epic of porting the Unreal 3 engine to JavaScript with asm.js, the Web’s credibility as a gaming platform is only going to increase. It is going to become more important that Microsoft has a solution in this space.

The good news is that implementation of WebGL in IE11 is underway. It has to be enabled with a registry tweak, which isn’t all that surprising considered its unfinished state. There was initial confusion that it only supports IESL shaders (from DirectX), rather than the GLSL format defined in the spec (which has its roots in OpenGL). Fortunately that is not the case, and it is possible to get WebGL demos running, even at this stage.

However, it is important not to get ahead of ourselves. Until it appears in an official build it does not mean it is certain to land in IE11. Anything from the feature not being complete on time to security concerns could mean it is not included or disabled by default. I remember at Opera that WebGL was initially turned off as it was possible to blue screen of death Windows by visiting a page with WebGL content (I think due to issues with shaders). Safari also currently has WebGL disabled by default. However, if Microsoft are implementing WebGL, I’d be very surprised if the plan isn’t to include it.

Networking

The currently leaked build of IE11 has evidence for SDPY support, although it is not currently functioning. As such you should be especially careful about assumptions it will appear in any final build of IE11.

SPDY is a networking protocol originally proposed by Google, built on top of HTTP. Its main goal is to speed up page loading by reducing latency, compressing headers, and reducing the number of connections per client. While it is not a standard, it is being used as the starting point for a future HTTP 2.0 standard from the IETF.

SPDY is supported by Opera, Firefox, and Chrome, and looks like it will be coming to IE11.

DOM and JavaScript APIs

Mutation Observers

Traditionally if you wanted to monitor DOM changes you would listen for DOM Mutation Events. It is widely acknowledged that the design of Mutation Events is flawed, due to inherent performance issues. Because of these problems, Mutation Events are now deprecated.

As the functionality of Mutation Events is important, there is a glaring need for a replacement. Step up DOM4 Mutation Observers! IE11 includes this feature, joining Chrome, Safari 6, and Firefox. Opera will inherit support once it switches to Blink.

Full Screen API

Sometimes it is desirable to make a web page cover the entire screen, hiding the browser chrome. Playing videos is probably the most common use case, but gaming would be a close second. The Full Screen API enables this functionality.

IE11 looks like it is implementing this spec, with the requestFullscreen method currently supported in leaked builds. it is prefixed with the ms prefix. Presumably the rest of the spec will be implemented in future builds. The spec is also supported unprefixed in Opera, and prefixed in Safari, Chrome, and Firefox. Firefox currently supports and older draft according to caniuse.com, as does Safari 5.1 and Chrome 15–19.

Update: CSS

Flexbox syntax update

The good news is that Flexbox in IE11 has been updated to the latest version (and most likely final) version of the spec. The Flexbox syntax changed just before IE10 was released, so it supports an outdated syntax. I was hit by the same issue when writing the flexbox section of SmashingBook 3. The new syntax is currently supported by Opera 12.1, Chrome (prefixed), and is coming to Firefox in version 21. Safari (and current Firefox) still supports a version of the spec older than the IE10 version.

CSS Level 4 Selectors?

There is preliminary support for CSS Level 4 Selectors in the latest leaked builds, but they are currently non-functional, and I don’t know which are included. I’m looking forward to seeing an update to François blog post to see what they are.

No browser to my knowledge has extensive support of the new CSS Level 4 selectors, except those moved in from CSS 3 Basic UI. The spec itself is relatively immature.

transform-style: preserve-3d?

According to François Remy’s post referenced above, there is also preliminary support for transform-style in the latest IE11 build, but preserve-3d does not work yet. Presumably the plan is to have this supported (to the relief of authors of sexy demos everywhere) by the time IE11 ships.

What’s next?

Your guess is as good as mine at this stage. I can say what I’d like to see however. Adding support for transform-style: preserve-3d makes sense to round out 3D capabilities (Update: looks like this is underway). I’d love to see support for @supports from CSS Conditional Rules, as the sooner it is implemented cross-browser, the more useful it becomes. When I worked at Motorola, I pushed for this to be implemented by the WebKit team there, and it has now landed in WebKit. It is also supported in Firefox behind a flag, and in Opera 12.1. Support for border-image would also be nice. Additional codecs such as WebM would be great, but I’m not holding my breath.

As WeakMap has been implemented from ES6, I’d not be totally shocked if more of that spec is implemented. Especially considering TypeScript prototypes some up and coming features (Update: Set is now also supported). Similarly, MS’ CU-RTC-Web prototypes at least hints something could be implemented. As does the Device Orientation prototype. This would be very nice for mobile and tablets. I guess we’ll find out more at //Build/ in San Francisco.

When?

There is no definitive public release date, but we do know from executive interviews that Windows Blue will be released by the end of the year, and there will be a preview by the end of June. Presumably IE11 will be part of that release.

Thanks to François Remy and Rafael Rivera for digging into the leaked build and releasing some of its secrets. And again to François for further updates on later builds.

Internet Explorer 11 preview

$
0
0

The first preview of IE11 has just been released. Let’s see what is new so far. I’ll update this post as more information becomes available.

The user-agent string

The new user-agent string for IE11 is as follows:

Desktop:
Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko
Experience formerly known as Metro:
Mozilla/5.0 (Windows NT 6.3; Win64; x64; Trident/7.0; Touch; rv:11.0) like Gecko

The Touch token is only included when used on a devices that include a touch screen.

CSS

HTML5, DOM4 and associated APIs

The following are now supported:

Web Graphics

The big news with IE11 is that WebGL is supported and enabled. Despite IE getting a lot of flack for not supporting WebGL, it looks like it beat Apple to the punch. WebGL is disabled by default in Safari.

Some new features of Canvas 2D Level 2 have been added, including image smoothing, the even-odd fill rule, and dashed lines.

Media

IE 11 supports the MPEG Dash (Dynamic Adaptive Streaming over HTTP).

Network

SPDY/3 is now supported. I was expecting it to be branded as HTTP 2, but this is not the case so far.

JavaScript/ES6

Support for the following ES6 features can be found in IE11 (via Kangax’s support tables and MS JavaScript documentation):

IE11 also supports the ECMAScript Internationalization API.

Performance

  • More of IE11 is hardware accelerated, using DirectX 9
  • Previous pages are cached for near instantaneous flipping through your browser history
  • Pages are prefetched and pre rendered (like Chrome) for faster page loads (if the browser guesses right)

Windows Integration

  • There are further live style sizes and further capabilities for what you can include in a live tile.
  • Numbers in a web page can have click to call enabled. I don’t know if this is just done by heuristics, or if you can add something special to the markup.

Test scores

Test scores have to be taken with a huge bucket of salt, as they just cover a subset of features (for example HTML5 test doesn’t include many of the APIs above, and CSS3 test doesn’t cover CSS2.1, CSS Level 4, or many of the specs supported by IE like Grids, Regions, and Exclusions), and are sometimes incorrect (WebKit incorrectly parses things it doesn’t support like background-repeat). With that said, this is how IE11 preview performs on various popular tests:

HTML5 Test:
355 and 6 bonus points (up from 320)
CSS3 Test:
61% (up from 54%)
Rng.io:
Passed 476 tests (up from 465 passes)

Variables and Constants in ES6

$
0
0

The humble var keyword has been with us since the very beginning of JavaScript. With ECMAScript 6, we’re gaining new ways to declare variables and even constants. Now that browser support is starting to improve, I’d like to take the opportunity to run through what we have now, what is coming up on the horizon.

If you have any experience with JavaScript, you probably know at least something about variables and scope. You’ll know that to define a variable you use the var keyword:

var aNewVariable = null;

You’ll probably also know that a variable is in the global scope if declared outside of a function, and the local scope if declared inside a function:

var globalVariable = "Global";

function aFunction() {
	var localVariable = "Local";
}

What may confuse you at first, if you come from a background in C-like languages–such as Java–is that local variables in JavaScript have function scope, rather than block scope. That is, variables behave as if they are hoisted up to the top of the function. Variables defined in a block, such as the body of an if statement, can be accessed from the enclosing function. They can even be accessed before the variable is declared:

function aFunction() {
   // sets the variable defined in the do/while block
   blockVariable = "Not global";
    
    do {
        var blockVariable = 1;
    } while (false);
    
    // 1 as can access variable inside block;
    console.log(blockVariable); 
}

While this slightly confusing behaviour can be useful, block level scope also has its place. Previously, there was no way to achieve this in JavaScript, except applying “hacks” such as including the code you want to be block level inside a self executing function. With ECMAScript 6 (ES6 for short), that will change, with the introduction of the let keyword.

Block level scope with let

Variables declared with the let keyword work in a similar way to those declared with var, except they use block level scoping instead of function level. If we adapt the previous example to declare blockVariable with let, and run it in browser that supports the keyword (more on that below), you’ll see that two different variables will exist: one inside the do/while block, which has block level scope, and a global property (it isn’t exactly a variable) outside of the block.

function aFunction() {
   // creates new property on the global object
   blockVariable = "property of the Global object";
    
    do {
        let blockVariable = 1;
    } while (false);
    
    // "property of the Global object" as can’t access variable inside block;
    console.log(blockVariable); 
}

One place where let seems immediately useful is when initialising a for loop. Due to variable hoisting, it is often recommended to define your initialiser (often called i) at the top of the function. However, this divorces the variable from the loop somewhat, and it personally feels a bit strange. Using let will give you the best of both worlds:

for (let i = 0; i & 10; i++) {
	//do stuff
}
As with anything ES6, browser support is where things fall a bit flat at the moment. IE11 has just implemented it by default. Firefox has had let for a long time, but you have to enable JavaScript 1.7 mode (let was formally Firefox specific) using type="application/javascript;version=1.7". With it becoming more common practice to remove the type attribute when using HTML5, this feels a little odd now, but I’m sure this requirement will change as ES6 matures.

For Chrome, things are a little more tricky. First you need to enable experimental JavaScript features in ”chrome://flags/”. Then it seems to only work if you are using strict mode: "use strict"; as the first statement of the script or function. It is not supported in Safari or Opera (technically, it would be supported in Opera 15 if you enable the experimental flag, but there is currently no way to do this).

Declaring constants with const

As well as variables, many languages have the concept of constants. That is, variables where you can not change the value once it has been initialised. JavaScript lacks this ability, although if you have an object, you can freeze it using Object.freeze in ES5.

With ES6, we will get this ability directly with the new const keyword. As you would expect, once you have declared a const, the value can’t be changed:

(function () {
	const CONSTANT_VARIABLE = "Foo";

	/* should print "foo" to console */
	printValue(CONSTANT_VARIABLE);
	
	/* Try to change value. Should fail */
	CONSTANT_VARIABLE = "Bar";
	
	/* should still print "Foo" to console, not "Bar" */
	printValue(CONSTANT_VARIABLE);

	function printValue(val) {
    		console.log("Value of CONSTANT_VARIABLE is " + val);
	}
})();

You’ll notice I’ve made the identifier all uppercase in the example above. I prefer to name constants this way, as it is consistent with how constants are named in host and native objects.

One thing to be aware of with const in ES6 is that they share the same block level scoping as let. This is different from how they were originally defined in JavaScript 1.7, and implemented in Firefox, where they have function scope, the same as var. IE11 uses block level scoping, as does Chrome, but only when you use strict mode and enable the experimental flag. Unfortunately, Opera, Safari, and Chrome without the flag only support const if you don’t use strict, so support is mutually exclusive here.

The other thing you should be aware of is that Presto-based Opera and Safari 6 both support const but treats it exactly like var. That is, it isn’t a constant at all; you can change the value. I’ve not managed to test Safari 7, but the latest WebKit nightlies work as in the ES6 spec.

Browser support

As mentioned, the key drawback of using const and let is the browser support. Until older browsers die out and flags get enabled by default, the keywords are mostly just useful when making installable apps that target certain platforms; such as FirefoxOS or Windows 8.1 apps.

The table below shows the current support level for the last release and nightly/preview release of the 5 major browsers. As there is various levels of support for const, I’ve broken it down into three rows: if variables can be declared using the const keyword without throwing an error, if the value stays constant, and if they have block level scope. If only the first is supported, the browser treats a const the same as a regular var.

FeatureIE 11IE 10FirefoxChromeOpera 15Opera 12.1WebKit NightlySafari 6
letYesNoJS 1.71Flag2/strict3NoNoNo
recognise constYesNoYesYes, !strict4!strict4!strict4
constant constYesNoYesYesNoYesNo
block level constYesNoNoFlag2/strict3NoNoNo

Compatibility notes

  • Firefox currently needs to be in JavaScript 1.7 mode to support let. This can be enabled by using type="application/javascript;version=1.7" on the script element.
  • Chrome requires experimental JS features to be enabled.
  • Only supported when in strict mode: "use strict";
  • Chrome without experimental JavaScript enabled, Safari, and Opera only supports const when not in strict mode. When experimental features are enabled, Chrome supports const both in regular and strict mode.
Note: I’m much more comfortable with HTML and CSS than ECMAScript, so please forgive me if I’ve made glaring errors, or terminology mistakes. Please let me know and I’ll update accordingly.

On Lawn Mark, and accusations of cheating

$
0
0

There was a recent article on Softonic claiming “Microsoft’s browser benchmark cheats, gives IE 11 speed crown”. I attempted to comment on the article, but it seems that they are being eaten by the site’s comment system. Instead, I’m posting it here, as I think there are some important inaccuracies that need highlighting. After all, “cheating” is a serious allegation.

The evidence doesn’t seem to back up the claims of cheating that are levelled in this article.

The accusation in the article states:

What they found was that Lawn Mark 2013 was improperly setting the smallest timeout value (setTimeout) improperly for the competition. While IE11 was allowed a “0” value for setTimeout, the competition was set to the standard 4 milliseconds.

If we check the code, instead we’ll find the following:

window.requestFertilization = (
    function ()
    {
        return window.setImmediate ||
                window.msSetImmediate ||
                window.mozSetImmediate ||
                window.oSetImmediate ||
                window.webkitSetImmediate ||
                function (bagOfFertilization) { window.setTimeout(bagOfFertilization, 0); };
    }
)();

We will see that

  • IE uses window.setImmediate not setTimeout(0)
  • All vendor prefixes are used for setImmediate, so any browser that implements this API will get the same code as IE10+
  • If browsers do not support setImmediate (currently, it is only supported in IE, and Node.js), it is given setTimeout with a value of 0, not 4 as stated above. i.e., the test gives Chrome the code that this article is claiming is given to IE11.

Now, it is true that Chrome uses a value of 4ms for setTimeout, as that is what the HTML5 spec says the minimum value setTimeout should be clamped to:

If the currently running task is a task that was created by the setTimeout() method, and timeout is less than 4, then increase timeout to 4. – HTML5 Spec

It is also worth pointing out that setImmediate used by IE (and prefixed for other browsers if they support it, as mentioned above) is a proposed W3C standard. Node.js also implements this spec, and there has been positive noises about it from respected people in the JavaScript community, such as Nicholas Zakas, and Domenic Denicola. Even Douglas Crockford uses it in one of his Monads & Gonads presentation.

So the crux of the matter is that IE supports setImmediate while other browsers do not, and thus the other browsers use setTimeout as a polyfill. Is this polyfill valid and honest? Chrome engineers seem to think not, but lets look at that.

It is certainly not completely unreasonable to use setTimeout at polyfill. For example, when debating if setImmediate should be added to WebKit/Blink, a Chromium engineer was skeptical suggested:

Shim it as “setTimeout(…, 0)”. That will be the same effect as setImmediate in most places (we only clamp when timers are nested several layers deep). – jamesr@chromium.org

This shows that:

  • It likely isn’t a crazy fallback to use, as Google themselves are suggesting it.
  • There probably is a use case for implementing setImmediate after all.

It is claimed, by Tony Gentilcore from Google, that the test runs intentionally slow in non-IE browsers because of an incorrectly used polyfill, and that the MDN documentation for setImmediate suggests a better polyfill. This makes it sound like this better polyfill (using postMessage instead of setTimeout is something that is clearly obvious and easy to find. It sounds like IE is ignoring this better suggestion.

Even ignoring that Google had in the past suggested the same fallback as IE used in the benchmark, if you check the history of said MDN page, you’ll see that the suggested polyfill was only added, by Paul Irish of Google, on the 27th of June of this year. The IE11 preview came out one day earlier on the 26th. Unless Microsoft have invented a time machine, it is implausible that they were ignoring this advice. It now doesn’t seem as obvious as it once did that IE is cheating, and purposely ignoring a better polyfill.

One can also debate if using postMessage actually is a better polyfill than setTimeout. For one, postMessage is a very different API than setImmediate. setTimeout is a much more obvious drop in, with a similar API signature, and something that will be more familiar to developers; they’re both timer based APIs.

It also seems like a hack to me to use postMessage in such a way, avoiding the normal security checks used by that API. The polyfill linked in the MDN article even mentions this:

It’s quite the abuse, using a cross-document messaging protocol within the same document simply to get access to the event loop task queue, but until there are native implementations, this is the best option.

While using postMessage will speed up Chrome, it has negative implications for UI responsiveness. IE also becomes less responsive when using postMessage over setImmediate.

In summary, I don’t think there is any evidence to back up accusations that the IE team was cheating when creating the Lawn Mark benchmark, and it isn’t even cut and dry whether using postMessage is the most appropriate fallback. Indeed, the clearest take away from this seems to be that there is a valid use case for setImmediate after all.

ECMAScript Internationalization API

$
0
0

If you have ever tried to write an application that supports multiple languages, I’m sure you will agree that it can be a complicated process. While there are obvious issues, such as translating the text, there are also differing conventions between countries on how things like dates and numbers are formatted, or how letters are sorted. Even just between the different versions of English, there are issues that crop up, such as how being British, I may understand the date 10/07/2013 differently than my American colleagues.

It is these latter cases that the ECMAScript Internationalization API aims to address. It is a companion spec to ES5.1 and above, that adds language sensitive functionality to JavaScript. It is influenced by established internationalisation APIs in Java and .NET.

The three areas that the current version one of the spec handles are strings, numbers, and dates. It does this by making a number of existing methods of the String, Number, and Date objects locale aware (that is, you can pass in a locale as an argument), and providing an Intl object that provides further localisation functionality.

Specifying a locale

First things first, when dealing with localisation, you need to specify the language and other conventions that will be used. This is called the locale. It is slightly more complicated than just specifying the language, as you can optionally specify the country or region (this is commonly used for English to indicate the difference between American and British English, or any of the various other versions used throughout the world), the writing system, calendar, and so on.

The string used to specify the locale is called the language tag. This is defined in IETF BCP47. Anyone that has written HTML has almost certainly encountered this. It is the value you give to the lang attribute (or xml:lang in XML/XHTML).

<!DOCTYPE html>
<html lang="en-GB">
    …
</html>

As many of you may have not used the language tag beyond the basics, I’ll cover some of the details here that you may need to know.

The components of the language tag are called sub tags, and are separated by hyphens.

Language sub tag

The first sub tag is the language sub tag. This can be either a two letter language code from ISO 639-1, or a three letter language code from ISO 639-2, ISO 639-3, or ISO 639-5. By convention, the language sub tag is written in lowercase.

It is recommended to use the ISO 639-1 two letter (often called Alpha-2) code if it exists for the language in question. Most major languages still in use today have an assigned Alpha-2 code. Examples include en for English, es for Spanish, de for German, ar for Arabic, and so on.

If the language isn’t included in ISO 639-1, you can use the Alpha-3 code from ISO 639-2 through 5. Examples of languages represented by an Alpha-3 code that have localisations provided in Windows (and thus supported by IE11) include Hawaiian (haw), Mohawk (moh), and Cherokee (chr).

While languages that are represented by an Alpha-2 code also have an assigned Alpha-3 code (such as eng for English, or spa for Spanish), IE11 treats it as invalid. Blink (the rending engine for Chrome and modern versions of Opera) on the other hand converts them to the Alpha-2 code when translating the specified locale to the canonical form.

Script sub tag

The optional script sub tag specifies the writing system used by the language in question. This uses the ISO 15924 four letter code. It is convention to write the script sub tag in title case.

For most languages, the script sub tag is not needed, as it is only written using one writing system. For example, English is exclusively written using the Latin alphabet, so specifying en-Latn (English using the Latin alphabet) would be redundant. Internally, the browser will just strip off the Latn sub tag when producing the canonical form of the language tag.

Some languages, however, use two different writing systems. An example of this is Serbian, which can be written using Latin (sr-Latn) or Cyrillic (sr-Cyrl).

While IE11 supports both, Blink only supports Serbian written in Cyrillic, and thus converts sr-Cyrl and sr-Latn to sr. While I suspect that Blink does support the script sub tag, it doesn’t provide any locale that uses it that I could find. IE11 supports multiple scripts for Serbian, Bosnian, Uzbek, Azeri (all Latin and Cyrillic); and Tamazight (Latin and Tifinagh), and Inuktitut (Latin and Syllabics).

Region sub tag

The region sub tag is optional, and specifies the country or regional variation of the language specified in the language sub tag. You can specify the region using either the ISO 3166-1 alpha-2 code, or the UN M.49. The ISO 3166-1 alpha-3 code is unsupported. By convention, the region sub tag is written in uppercase.

The Alpha-2 code should always be used over the numerical UN code, except in one situation; when you want to specify a geographical region. ISO 3166-1 only specifies individual countries, while UN M.49 has codes for continents and regions.

Most regions do not have a locale assigned to them; after all, what data would be used for en-021 (English as used in North America)? Conventions differ between the US, Canada, never mind the other countries. There is one key exception; es-419 (Spanish as spoken in Latin America). Many apps do not want to provide a different locale file for every country in Latin America for cases where conventions do not differ between the individual countries. Therefor the Latin American region is a useful catch all. It is supported by both IE11 and Blink. The only other language/region combination that I could find that is supported (only in IE) is en-029 (English as spoken in the Caribbean).

If you use a UN region code and it isn’t supported, it is stripped out by the browser and it will likely fall back to the base language. Blink also does this if you specify a UN country code (for en-021 it uses en rather than converting it to en-US), while IE11 rejects it as an invalid language tag, and falls back to the next locale in the list, or the default locale.

Be aware that you may get unexpected results if there is no locale provided for the combination of language and region. While IE looks to support an impressive array of locales, Blink is fairly lacking. For example, no English locales except US and British English are supported in Chrome, so if you specify en-AU for Australian English, it will fallback to en, which uses US English conventions. For numbers this is probably fine, but for dates there will be a lot of confused users.

As far as I could tell, Blink only supports different country variations of Spanish, Portuguese; and US and British English. No country specific version of French, German or Arabic are provided.

Extension sub tags

The language tag allows for extensions to add further locale-based behaviour. The extension that is relevant to the ECMAScript Internationalization API is “BCP 47 Extension U”, defined in RFC 6067.

The U extension is a single u token, which is followed by one or many keywords. They keywords specify things such as the number system, currency, calendar, and so on. A keyword consists of a two character “key” sub tag, that defines what property of the locale is being set, and zero to many three to eight character “type” sub tags, that sets the value. The structure is defined by the Unicode BCP 47 Extension Data section of Unicode TR35.

The actual keys and types are defined in XML files linked from the Unicode CLDR Project‎. These are being continuously updated, but the idea is existing keywords will never be removed. The latest trunk can be found at http://unicode.org/repos/cldr/trunk/common/bcp47.

By convention, extension sub tags are written in lowercase.

The relevant keywords are as follows:

Calendar

Setting the calendar can be achieved by using the ca key. An example of using the Buddhist calendar with the English locale would be en-u-ca-buddhist, where en is the language, u is the unicode extension, and ca-buddhist is the keyword, where ca is the calendar key and buddhist is the calendar type.

Collation

The type of ordering and sorting of strings is specified in the collation XML file. There are numerous keys, which I will cover later in this post.

Currency

The currency can be set using the cu key and a three letter currency code based on ISO 4217.

An example of setting Great British Pounds when using the American English locale and the Gregorian calendar, would be en-US-u-ca-gregory-cu-gbp. The Gregorian calendar is the default, so would not be needed, but is used for illustrative purposes to show more than one keyword at once.

The cu key is not supported by the Internationalization API, but it can be set using the options object (more on this latter), using the same values as specified in currency.xml.

Numeral system

The numeral system key is nu. All types in the CLDR numbers list are valid except native, traditio, and finance.

I’m not sure if the types are based on an existing standard. Some do seem a bit odd; for example the numerals commonly called Arabic numerals (or Hindu numerals), i.e. 1234567890, are called latn. This sort of makes sense, as we now use them with the latin alphabet, but they’re also used with the Greek and Cyrillic alphabets. What are commonly called Eastern Arabic or Arabic–Indic numerals (i.e. those used in many modern standard arabic locales) is called arab.

Timezone

The timezone key is tz. The type is a shortened version of the time zone code from [IANA Time Zone database]. They are based on UN/LOCODE with the space removed between the country and city codes.

Currently, by spec, it is not possible to set the timezone using the U extension keyword, but it works in Blink anyway.

Localising content

There is no way to globally set a locale using the Internationalization API. Instead, there are three objects that handle localisation duties for strings (Collator), numbers (NumberFormat), and dates (DateTimeFormat). These share a common parent Intl object.

One way to localise a string, number, or date is to use the relevant object’s constructor, passing in the locale, and any options. This works in a similar way for each type:

var locale = "en-GB",
    localeDate = new Intl.DateTimeFormat(locale),
    localeNumber = new Intl.NumberFormat(locale),
    localeString = new Intl.Collator(locale);

If you do not pass in a locale as the first argument, it will default to the user’s default locale. In my case, this would be en-GB.

In the example above, I just supplied one locale. Instead, it is possible to pass an array of language tags. If the first is not supported (and stripping off sub tags doesn’t lead to one that is), it will move to the next in the list until it does match a supported locale, or gets to the end and uses the default locale. In the following example, the language codes for Norwegian and Danish are specified. IE11 supports Norwegian, so it is chosen, but in Blink, it is not supported, so Danish is used. The latter uses the same collation and formatting rules as Norwegian, so it is a good plan B.

localeNumber = new Intl.Collator(["no", "da"]);

You can pass in an options object as the second argument to set specific formatting options. Each type has its own options, so I will cover them in their respective sections.

Working with localisation objects

Many of the methods that you will commonly use are shared between the three types of objects. There is also a common property for specifying how locales are matched.

Testing if a locale is supported

It can be important to test if a locale is supported, as otherwise unexpected results might ensue. Unfortunately, there is no list of supported locales that you can fetch. Instead, you have to pass an array of locales to query if they are supported. You do this with the supportedLocalesOf method. It will return an array with unsupported locales removed.

As there is no global locale, you will have to test each object individually to see if a locale is supported. In the following example, I am testing if the locales are supported for DateTimeFormat. You can call the same method on Collator and NumberFormat.

var supportedDateLocales = Intl.DateTimeFormat.supportedLocalesOf(["en-GB", "en-US", "ar", "de", "bs-Cyrl", "haw", "sma-NO"]);

There is an important note here on how locales work. If the full locale is not supported, the user agent will strip off sub tags until it finds a locale it does support. This is called the “lookup” algorithm. At the time of writing, IE11 supports the en-AU (Australian English) locale, but Chrome/Blink does not. Thus, IE11 will use en-AU while Chrome will use en. However, if you test if the locale is supported, both will return en-AU:

console.log(Intl.DateTimeFormat.supportedLocalesOf(["en-AU"));
// "en-AU", even though Chrome uses en.

It will only remove a locale from the array if there is no fallback that is supported. In the first example, neither sma-NO or sma are supported by Chrome, so it will not include it in the returned array.

While Chrome does not normalise the locale to the actual value it is using, IE11 does. Thus, if we test for en-DE (German English doesn’t really exist outside of British comedies like ’Allo ’Allo), IE will return en.

This situation is a bit unfortunate, as IE behaves in a way I’d expect, but supports a lot of locales, while Chrome doesn’t support many country specific locales, but behaves in a way that makes it difficult to tell if it really used the correct locale. This is especially an issue for dates and locales such as Australian English, where Chrome will fall back to en and use the US date format. Without handling this case, there will be a lot of confused users for the first 12 days of each month.

Accessing the locale, and the formatting and collation options

Once you have created an object for formatting or collation, it can be useful to query which locale is being used (especially as it may not be the one specified) and the options that are set. This can be done with the resolvedOptions method. It returns an objects with the specified options. These can then be accessed as you would with any other properties of an object.

var locale = "en-GB",
    numFormat = new Intl.NumberFormat(locale),
    dateFormat = new Intl.DateTimeFormat(locale),
    collator = new Intl.Collator(locale); // print options object to the console. Unset options are not included
    
var options = numFormat.resolvedOptions();
console.dirxml(options); // access individual options
console.log("Style: " + options.style);
// same method exists for dateTime and collator, but returns different options

console.dirxml(dateFormat.resolvedOptions());
console.dirxml(collator.resolvedOptions());

Demo showing the use of resolvedOptions

There is one thing that is important to note. Some options are dependent on the value of other options. If an option is not relevant to the formatting, it will not be included in the object returned. An example of this is the currency property of the NumberFormat object. This is only used if the style object has a value of currency.

Changing the locale look up method

Previously, I described how the browser (or user agent) processes the language tag to find a supported locale. The lookup method that I described can be changed by setting the locale­Matcher property. The method I described can be set using a value of "lookup". The default is actually not this but "best fit". This leaves it up to the user agent to come up with a custom algorithm that can provide better matches. An example could be falling back to en-GB instead of en if en-AU is specified, and not supported. As far as I can tell, both IE and Blink just use the regular lookup method when "best fit" is specified.

Formatting using the locale

To format numbers and dates based on the current locale and formatting options, you use the conveniently named format method:

localeNumber.format(1000.15); // 1,000.15 with default formatting
localeDate.format(new Date()) // 23/8/2013  with default formatting

Demo showing the use of the format method

This is where you can see the true power of the Internationalization API. Across the various locales that browsers support, there is a lot of data that you’d have to capture yourself if you wanted to format using the correct conventions.

We hit this exact problem when I was working on Opera Dragonfly. For the Resource and Network Inspectors, I naïvely wanted the data, such as the size of the resource, to be a more human friendly value. A number such as 12,000,000 is much easier to understand at first glance than 12000000. However, it was pointed out to me that while English uses commas as a thousand separator, languages such as French use a space. Other languages use a point and so on. As JavaScript didn’t (until now) provide a built-in way to do this, it would have been a lot of extra work (and research into the correct conventions) to support a relatively minor enhancement (in the grand scheme of things).

Collating using the locale

Searching and sorting strings is somewhat similar to formatting numbers and dates. Instead of using the format method, you use the compare method.

When sorting an array, you can pass this as an argument of its sort method:

var letters = ["b", "a", "c"],
    collator = new Intl.Collator("en");
    letters.sort(collator.compare); // ["a", "b", "c"]

Demo showing the use of the compare method

Formatting and collation options

So far we’ve seen how to create a localisation object by specifying the locale, and using the default options. We’ve also seen that some options can be set using the unicode u extension to the locale.

It is also possible to set a full range of options when constructing the localisation object. This can be achieved by passing in an options object as the second argument of the relevant constructor function, and also by specifying language tag extensions. In the following sections I will describe these options for the NumberFormat, DateTimeFormat, and Collator objects in more detail.

Number formatting options

Beyond the locale, the NumberFormat object has the following internal properties that represent formatting options:

numberingSystem

The numberingSystem property sets the type of numerals used when formatting the number. Unlike the other options, this can only be set via the Unicode u extension to the language tag, using the nu keyword. The valid types can be found in numbers.xml.

new Intl.NumberFormat("en-u-nu-beng").format(100000.10); // ১০০,০০০.১ using Bengali digits

Demo showing the numberingSystem being set via the nu Unicode extension

useGrouping

When the useGrouping property is truthy, the locale dependent grouping separator is used when formatting the number. This is often known as the thousands separator, although it is up to the locale where it is placed. The ‘useGrouping’ is set to true by default.

 // 100 000,1
new Intl.NumberFormat("ru", { useGrouping: true }).format(100000.10);

// 100000.10
new Intl.NumberFormat("en", { useGrouping: false }).format(100000.10); 

Demo setting the useGrouping property

style

The style property sets the style of number formatting. It can either be the string "decimal" (the default), "currency" or "percent".

decimal

When a number is formatted as a decimal, the decimal mark is replaced with the most appropriate symbol for the locale. In English this is a decimal point (“.”), while in many locales it is a decimal comma (“,”). If grouping is enabled the locale dependent grouping separator is also used. These symbols are also used for numbers formatted as currency or a percentage, where appropriate.

 // 100,000.10
new Intl.NumberFormat("en", { style: "decimal" }).format(100000.10);

Demo using the decimal number formatting style

percent

When formatting using percent, the number is multiplied by 100 and the correct symbol for the percentage symbol is added in the correct position for the locale used. This is often a percent sign (“%”), sometimes with or without a space between the number, but in Arabic and Farsi it is the appropriately named Arabic percent sign (“٪”).

// Chrome: "50%", IE: "50 %"
new Intl.NumberFormat("en", { style: "percent" }).format(0.5);

Demo using the percent number formatting style

currency

If the style is set to currency, there is a requirement that the currency property also needs to be specified. This is because the currency used is not dependent on the locale. You may be using a Thai locale, but dealing in US Dollars, for example.

When formatting as currency, the formatting rules for currency are used. This is often the same way as how a decimal number is formatted, but some countries–including Switzerland–use different formatting rules for currency. The correct currency is then added to the formatted string following the options specified by the currency and currencyDisplay properties.

new Intl.NumberFormat("en", {
         style: "currency", 
         currency: "GBP"
     }).format(100000000.59)); // £100,000,000.59

Demo using the currency formatting style

currency

The currency property specifies the currency that will be used when formatting the number. The value should be a ISO 4217 alphabetic currency code. These are the same values specified in the Unicode cu extension.

Note that the currency can not be set as part of the language tag, as the Internationalization API ignores the cu extension.

When formatting a currency, it does not convert the value of one currency to another. It merely adds the correct symbol, name, or code of the currency specified, and adds formatting rules related to that currency, such as the number of decimal places (if any).

new Intl.NumberFormat("en", {
     style: "currency", 
     currency: "JPY"
  }).format(100000000.59)); // "¥100,000,001"

Demo using the Japanese Yen currency

Note, in the previous example, IE rounds the value as Japanese yen no longer has a subunit. Chrome leaves the decimal place intact.

currencyDisplay

If the number is using currency formatting, the currencyDisplay property specifies if the currency will be displayed using its symbol (e.g. $ for US dollars, £ for Great British pounds, and so on), the ISO 4217 currency code, or the currency name. These correspond to the values symbol, code, and name respectively.

The currency symbol and name will be localised to use the conventions of the language specified in the locale, where appropriate.

var spondoolies = 100000000000;

//  "QR100,000,000,000" Symbol is QR in English
var qatariSpondooliesEn = 
        new Intl.NumberFormat("en", {
            style: "currency", 
            currency: "QAR",
            currencyDisplay: "symbol"
         }).format(spondoolies)); 

//  "ر.ق.‏ ١٠٠٬٠٠٠٬٠٠٠٬٠٠٠" Symbol is ر.ق in Arabic
var qatariSpondooliesAr =
        new Intl.NumberFormat("ar", {
             style: "currency", 
             currency: "QAR",
             currencyDisplay: "symbol"
        }).format(spondoolies));

Demo showing the use of currencyDisplay

minimumIntegerDigits

The minimumIntegerDigits property sets the minimum number of digits before the decimal place (known as integer digits). The number is padded with leading zeros if it would not otherwise have enough digits. The value must be an integer between 1 and 21.

// 000,010.1
new Intl.NumberFormat("en", { minimumIntegerDigits: 6 }).format(10.10); 

Demo showing the use of minimumIntegerDigits

minimumFractionDigits

The minimumFractionDigits property is similar to minimumIntegerDigits, except it deals with the digits after the decimal place (Fractional digits). It must be an integer between 0 and 20. The fractional digits will be padded with trailing zeros if they are less than the minimum.

 // 0.100
new Intl.NumberFormat("en", { minimumFractionDigits: 3 }).format(.1);

Demo showing the use of minimumFractionDigits

maximumFractionDigits

The maximumFractionDigits property follows the same rules as minimumFractionDigits, but sets the maximum number of fractional digits that are allowed. The value will be rounded if there are more digits than the maximum specified.

var mxFr1 = new Intl.NumberFormat("en", { maximumFractionDigits: 1});

console.log(mxFr1.format(.42)); // 0.4
console.log(mxFr1.format(.99)); // 1

Demo showing the use of maximumFractionDigits

minimumSignificantDigits

The minimumSignificantDigits works as a pair with maximumSignificantDigits. It specifies the minimum number of significant figures that are used when formatting the number. It must be an integer value between 1 and 21. If the number has less than the specified minimum significant figures, the fraction digits will be padded with trailing zeros.

If minimumSignificantDigits and maximumSignificantDigits are specified, they override minimumIntegerDigits, minimumFractionDigits and maximumFractionDigits.

maximumSignificantDigits

Complementing minimumSignificantDigits, the maximumSignificantDigits property sets the maximum number of significant figures. if there are more significant figures than the maximum specified, the number is rounded to the number of specified significant figures and the remaining significant digits are replaced with zeros.

var mn1Mx3 = new Intl.NumberFormat("en", { 
    minimumSignificantDigits: 1,
    maximumSignificantDigits: 3
});

console.log(mn1Mx3.format(1.501)); // 1.5
console.log(mn1Mx3.format(25499.99)); // 25,500

Demo showing min and max significant digits

Date and time formatting options

Date and time formatting works much the same way as number formatting, but includes its own specific options.

Beyond the locale, the DateTimeFormat object has the following internal properties:

numbering­System

As with NumberFormat, the numberingSystem property can only be set with the Unicode u extension to the language tag, using the nu keyword.

It works in exactly the same way as forNumberFormat, except that it sets the numeral system used in the date.

calendar

The calendar property sets which calendar is used when formatting the date. For most locales, this will be the Gregorian calendar (gregory in Unicode CLDR), but some countries use alternative calendars. There are also a number of calendars that are still used for specific situations, such as religious holidays or official documents.

As an example, Thailand uses the Thai solar calendar (buddhist), which uses the same day and month as the Gregorian calendar, but the year 0 starts from the beginning of the Buddhist Era (545 BC), rather than the Christian Era.

The calendar property uses the ca keyword from the Unicode u extension of the language tag. It also can not be set via the options object.

For valid values see the calendar.xml file from Unicode CLDR.

time­Zone

While there is a tz keyword to specify the time zone offset in the language tag, it is not currently used in the ES Internationalization API.

Instead, the time zone can be set using the timeZone parameter of the options object. While Unicode CLDR defines a number of values in timezone.xml, the spec only requires that the utc value is supported. If timeZone is undefined, the time zone of the user’s host environment (i.e. that used by their OS or browser) is used when formatting the date (but timeZone remains undefined per spec). Other values should throw an error.

var utc = new Intl.DateTimeFormat("en", { 
    timeZone: "utc",
    hour: "numeric"
});

console.log(utc.format(new Date()));

Demo setting the date to use UTC time zone

While the current version of the spec only supports utc and the user’s current timezone (when timeZone is undefined), there is a conformance clause that “allows implementations to accept additional time zone names under specified conditions.” Chrome takes advantage of this, by also accepting additional time zones. It does not support the field names specified in timezone.xml, but instead supports the the IANA time zone names, which are more widely used than the CLDR equivalents, and are listed as alias values in that file. Version two of the specification will specify this behaviour.

As well as allowing the time zone to be specified, Chrome also reports the user’s current time zone using IANA zone name when timeZone is undefined:

// same behaviour when explicitly set as undefined, or option is not set.
var format = new Intl.DateTimeFormat("en-GB", {
    timeZone: undefined
});

// IE: undefined, Chrome: America/Los_Angeles (if in PDT/PST time zone).
console.dirxml(format.resolvedOptions().timeZone);

Demo showing differing behaviour between IE and Blink when timeZone is undefined

var format = new Intl.DateTimeFormat("en-GB", {
    timeZone: "Antarctica/South_Pole"
});

// Chrome: Antarctica/South_Pole, IE: outside valid range
console.dirxml(format.resolvedOptions().timeZone);

Demo showing the timeZone being set to the South Pole’s time zone

time­ZoneName

The timeZoneName property sets how the time zone name will be displayed. It can either be set to long or short. The former should use the name of the time zone, while the latter should use its abbreviated name. If this property is not set, it is not included in the resolved options, and no time zone indicator will be included in the formatted date string.

This is the theory, but in practice, IE never shows the time zone name, even though it sets the option correctly.

Chrome does show the time zone name, but it doesn’t show exactly as I’d expect. When using short it displays the correct time zone abbreviation for US time zones, with the caveat that it uses the generic form, rather than the standard or daylight savings form. If you live on the West Coast of the US (or specify "America/Los_Angeles" in Chrome), it will include the token PT when using the en locale, rather than PST or PDT, depending on the time of year.

If you’re elsewhere, the names seem a little strange to me. For example, in the UK we usually use “GMT” or “BST” (in summer), as can be seen in the CLDR Timezones chart, but Chrome will use United Kingdom Time when timeZone is set to "Europe/London". As well as not being time zone name I’d expect, it isn’t the abbreviated form, and is inconsistent with how time zones are named for the US. Now imagine that you want to format a date using a time zone such as CET, used by many countries. If I choose "Europe/Paris" (there is no generic Europe/Central or equivalent that I could find, either in timezone.xml or that is supported by Chrome), Chrome will display “France Time”. That is going to feel odd for someone in the Spain, Norway, or any of the other countries in the central European time zone.

Then there is the long form. The CLDR Timezones chart uses the full name of the timezone, such as Pacific Time, while Chrome shows the GMT offset: GMT-07:00. Outside of the US, the long form will be shorter than the short form.

I suspect these issues with Chrome are because time zone support is experimental, beyond support for UTC. With IE not showing the time zone name at all, this is certainly a property that can not be relied upon yet.

Time components: hour, minute, and second

The time is not shown by default, and the hour, minute, and second properties are absent if not set.

All three can be set to either "2-digit" or "numeric".

If the hour is displayed, it will either use the 12 or 24 hour clock, depending on the locale.

The "2-digit" value does what you’d expect; formats that component of the time using two digits, just as you’d likely see on a digital watch:

var timeFormat = new Intl.DateTimeFormat("en-GB", {
    hour: "2-digit",
    minute: "2-digit",
    second: "2-digit"
});

console.log(timeFormat.format());

Demo setting the hour, minute, and second to two digits

In Chrome however, only one digit will be used for the hour if the time is before midday and the 12 hour clock is being used.

For the "numeric" value, one digit will be used for the hour where possible (the same as described above for Chrome when "2-digit" is specified). I’ve not noticed any difference for the minute and second properties in IE, while in Chrome the "numeric" value is not supported for any time related properties; they remain set to "2-digit".

hour12

The hour12 property specifies what time notation is used for formatting the time. It accepts a boolean value, where true uses the 12-hour clock and false uses the 24-hour clock (often called military time in the US). This property is undefined if the hour property is not used when formatting the date.

Much of the world uses the 24-hour clock by default in written communications, with some notable exceptions, including North America, and India. Many countries use both systems interchangeably, so IE and Chrome don’t always agree with each other on the default value for this property.

If the 12-hour clock is being used, there is an internal hourNo0 boolean property that specifies if the hours go from 1–12 (true) or 0–11 (false). This sounds like the hour counts up like a zero indexed array, but it is not quite like that. In some locales midnight is 00:00 (British English does this), while in some locales (such as American English), midnight is 12:00. The hours from 1 a.m. to 11:59 p.m. are the same.

weekday

The weekday property specifies how the day of the week is formatted. If absent, it is not included in the date formatting.

The valid values are narrow, short and, long, indicating the length of the string used. In alphabetic languages, narrow will usually use one character for narrow, while short will use an abbreviation (Wed for Wednesday in English), and long will use the full name of the day.

 // W if Wednesday
new Intl.DateTimeFormat("en", { weekday: "narrow" }).format()

Demo showing a narrow weekday

One fairly major issue with using weekday in Chrome is that many supported locales do not include a localised string. Instead a digit that represents the day of the week is shown. For Wednesday, this is 4, based on Sunday being the first day of the week.

era

The era can be be included in the formatted date using the era property. It accepts the same narrow, short, and long values, with the same definition, as the weekday property, and is also absent if not used in formatting.

For modern dates using the Gregorian calendar, the era: “AD” (using short in English) or “Anno Domini” (inlong` form) is rarely used, but it is more important for some calendar systems. The Japanese calendar has an era (called nengō) that changes at the start of the reign of a new emperor.

While IE supports the era property, it does not include it in the formatted string, no matter which value is used.

day, month, and year

It is fairly self explanatory what these properties do. All three accept "2-digit" and "numeric", which will be familiar from the time-specific properties. Also in keeping with those properties, they are absent if not used in formatting the date.

The month property adds three additional values: narrow, short, and long. They behave in the same way as for weekday; the 8th month in the en locale is formatted as Aug using short, and August using the long value.

In many locales, the day, month, and year properties are used by default if no options (other than the locale) are specified when constructing a new DateTimeFormat object. They are also used by default when the era property is set without any other date specific properties.

The order of these properties differ depending on the locale. The most common is little-endian: day, month, then year. The next most common is big-endian, with the most significant component first: year, month, then day.

var locales = ["en-GB", "en-US", "hu"],
    length = locales.length,
    dateFormat = null;

for (var i = 0; i < length; i++) {
    dateFormat = new Intl.DateTimeFormat(locales[i], {
        year: "numeric",
        month: "long",
        day: "numeric"
    });
    console.log(dateFormat.resolvedOptions().locale + " " + dateFormat.format());
}

Demo for formatting the date, showing different order depending on locale

The US is a significant outlier, with its month, day, year format. This could cause confusion with the default numeric-style month format, as any locale using the en language sub tag with an unsupported region sub tag will fall back to the US format. In IE the major English speaking locales are covered, but in Chrome, only en-GB and en-US are supported.

If you’re targeting English speaking users from other locales, I’d recommend specifying the month using short or long to mitigate this issue, or use en-GB for date formatting.

String collation options

As well as the locale, the Collator object contains the following internal properties that can be set via language tag extensions or the options object:

usage

The usage property specifies what action will be performed on the list of strings. if the property is set to search it will check to see if a string matches, while sort will sort the list of strings in the order specified by the locale and other options.

These two values are also specified in the co Unicode extension, but these are ignored in the Internationalization API.

In the following example, I am sorting an array of characters based on the order specified by the English and then Swedish languages. In English, where diacritics are not used for the most part, any character with such marks are sorted after the base character. Thus the Swedish characters “å” (LATIN SMALL LETTER A WITH RING ABOVE) and “ä” (LATIN SMALL LETTER A WITH DIAERESIS) are sorted after “a”. In Swedish, these characters, along with “ö” (LATIN SMALL LETTER O WITH DIAERESIS) are standard letters of the alphabet, that appear in the order mentioned after “z”.

var str = "qwertyuiopåasdfghjklöäzxcvbnm".split(""),
    locales = ["en", "sv"],
    length = locales.length,
    sorter = null;
    
for (var i = 0; i < length; i++) { 
    sorter = new Intl.Collator(locales[i], { usage: "sort" });
    
    console.log(sorter.resolvedOptions().locale + ":\t" +
        str.sort(sorter.compare));
}

Demo showing the sort order differences between English and Swedish

The situation is the same in Danish and Norwegian with the “æ”, “ø”, and “å” characters (except that Chrome, and thus ironically Opera, don’t support the Norwegian locale). If you need to sort using Norwegian sort order, it is best to use an array for the locale, with Danish as a fallback.

collation

The remaining types specified in the Unicode co extension are valid in the Internationalization API.

These types tailor the sort order. One example of a collation type is trad. This stands for traditional collation. In some languages, the sort order has changed, and this property allows you to tailor the sort order to use the older style. One language where this is relevant is Spanish. Traditionally there were two unique compressions (that is, two letters that get treated as one) that are being phased out; “ch”, which sorts between “c” and “d”; and “ll” between “l” and “m”.

var str = ["cherry", "llama", "apple", "lychee", "date", "cranberry"],
    locales = ["en", "es-u-co-trad"],
    length = locales.length,
    sorter = null;
    
for (var i = 0; i < length; i++) { 
    sorter = new Intl.Collator(locales[i], { usage: "sort" });
    
    console.log(sorter.resolvedOptions().locale + ":\t" + 
        str.sort(sorter.compare));
}

Demo showing traditional sort order in Spanish

In the above example, “cherry” should be sorted after “cranberry”, and “llama” (what you’ve never head of the llama fruit?) should be after “lychee” when using the Spanish locale with traditional sorting.

In IE11, you can also set the collation type via the collation property of the options object, but this is not valid in Chrome, or by the specification.

Another example is the phonebk type. This uses the ordering as found in phone books, and other such lists of names. If you’re an English speaker, you may wonder what the difference is between this and the regular rules for collation, but in German there is an important difference.

A number of names that use characters with umlauts can also be spelt in the expanded form, where an “e” is added after the base character. Thus, some people may be called “Müller”, while other may be “Mueller”. As both are variations of the same name, it would be preferable for both names to be found together in a phone book. For this reason, when using the phonebk type, any characters with an umlaut are collated the same as if they were in their expanded form. In the following example, “Häßler” (Haessler) comes before “Hamman”, while “Müller” and “Mueller” are interchangeable, so are sorted by first name:

var str = ["Mueller, Peter", "Hamann, Dietmar", "Müller, Gerd", "Müller, Thomas", "Häßler, Thomas"],
    locales = ["de", "de-u-co-phonebk"],
    length = locales.length,
    sorter = null;
    
for (var i = 0; i < length; i++) { 
    sorter = new Intl.Collator(locales[i], { usage: "sort" });
    console.log(sorter.resolvedOptions().locale)
    console.log(str.sort(sorter.compare));
}

Demo using German phone book ordering

There are a number of other options. Many of these are related to Pinyin ordering, but also dictionary (dict) style ordering–primarily used in Sinhala–phonetic for sorting based on pronunciation, and so on.

ignorePunctuation

There are times when you are comparing or sorting strings that you want to ignore any punctuation; perhaps you want to treat words with typographic quotes and straight quotes as the same (say, “can’t” and “can't”), or match both the hyphenated and non-hyphenated form of a name. You can achieve this by setting the ignorePunctuation property to true in the options object:

var ignore = [true, false],
    locale = "en",
    searcher = null;
    
for (var i = 0; i < ignore.length; i++ ) {
    searcher = new Intl.Collator(locale, { 
        usage: "search", 
        ignorePunctuation: ignore[i] 
    });

    console.log(searcher.compare("Helena Bonham Carter", 
        "Helena Bonham-Carter"));
}

Demo showing search, ignoring punctuation

Be aware that this is all or nothing; it will ignore all punctuation used by the locale in question.

The equivalent Unicode extension key is ka, but this is not supported as part of the language tag in the Internationalization API.

sensitivity

Sometimes you may want to be more or less strict when collating strings. Let’s take an example; search for “naïve” in your favourite search engine, then use the browser inline search functionality to look for “naive”. It will likely (unless you’ve changed the settings) match all cases of the original search term too. One of the reasons for this is that it is easier for the user, rather than having to force them to learn how to type the diacritic, or using copy and paste.

The sensitivity property allows you to customise this behaviour in your own app. It has four possible values:

base

Strings are only unequal if the base letter is different. If the base letter has a diacritical mark, or is a different case, it will still be equal.

 // equal
new Intl.Collator("en", { 
    usage: "search", 
    sensitivity: "base" 
}).compare("a", "å");
accent

Strings are unequal if the base letter or the diacritical mark are different. Strings with different cases will be equal.

// unequal
new Intl.Collator("en", { 
    usage: "search", 
    sensitivity: "accent" 
}).compare("a", "å"); 
case

Strings are unequal if the base letter or case are different. If the diacritical mark is different it will still be equal

// unequal
new Intl.Collator("en", { 
    usage: "search", 
    sensitivity: "case" 
}).compare("a", "A"); 
variant

Strings will only be equal if the base letter is the same. Changes in letter, case, or diacritical marks will be considered unequal.

An example of all these in action can be found in this sensitivity demo

One thing to bear (🐻) in mind is that while in some languages (say English), a letter with a certain diacritical mark may be considered the same letter, in others that combination may be considered a different base letter. The letter “å” is a different letter to “a” in Denmark and Norway:

 // equal
new Intl.Collator("en", { 
        usage: "search", 
        sensitivity: "base" 
    }).compare("a", "å");

 // unequal
new Intl.Collator("da", { 
        usage: "search", 
        sensitivity: "base" 
    }).compare("a", "å");

Demo showing difference in base letters between English and Danish

The equivalent Unicode key to the sensitivity property is ks, but this has different, less obvious types, and it is also ignored by the Internationalization API.

numeric

The numeric property enables and disables numeric sorting. If it is enabled, numbers (or even numbers represented as strings) are sorted in numerical order. That is, 10 will come after 9. On the other hand, if it is disabled, they are lexicographically ordered: 10 will come after 1 and before 2.

It is possible to set the numeric property either as a property of the same name in the options object, or using the Unicode extension kn key in the language tag. Using both methods, true enables numeric sorting, and false disables it.

var nums = [0, 2, "4", 6, 8, 1, 3, 5, 7, 9, 10, 47, "-5"],
    collator = new Intl.Collator("en", { numeric: true });

// ["-5", 0, 1, 2, 3, "4", 5, 6, 7, 8, 9, 10, 47] 
console.log(nums.sort(collator.compare));

Demo showing numeric sorting

An implementation is not required to implement the numeric property, but it is supported by both IE11 and Chrome/Blink.

caseFirst

If you are sorting a language that uses a bicameral script (Latin, Cyrillic, and Greek, among other), you need to take into account case order. In something like a dictionary or phone book, there is little difference if a letter is upper or lower case, while in Unicode, and the default sort order in JavaScript, majuscule letters come before minuscule.

The Internationalization API provides the caseFirst property for specifying the behaviour that you want. It can either be set via a property of the same name in the options object, or via the kf key in the language tag.

The valid values come directly from the types defined in the collation.xml Unicode extension. They are as follows:

upper

Upper case letters are sorted before their lower case equivalent.

var nums = ["A", "b", "C", "c", "a", "B"],
   collator = new Intl.Collator("en", { caseFirst: "upper" } );

// ["A", "a", "B", "b", "C", "c"] 
console.log(nums.sort(collator.compare));
lower

Lower case letters are sorted before their upper case equivalent. The same array as above would result in ["a", "A", "b", "B", "c", "C"].

false

This is the default value, and provides no special case ordering. Using the English locale, this is the same as if "lower" was specified. Note that "false" is a string, rather than a boolean.

You can try out all three values in the caseFirst demo

Using existing Number, Date, and String methods

You may be aware that in ECMAScript, the Object prototype has a toLocaleString method, and that Array, Date, and Number override this with their own implementation. And also, that the Date prototype provides the toLocaleDateString and toLocaleTimeString methods. While these could be useful, they accepted no parameters, and thus could only be used for the user’s current locale.

In much the same way that the Internationalization API allows you to pass a locale and options Object as arguments to the NumberFormat, DateTimeFormat, and Collator constructors, it also extends the already existing locale aware methods to include these two parameters:

// Show the hour in Chinese
console.log(new Date().toLocaleTimeString("zh", {
    hour: "2-digit"
}));

// Show the date in Turkish
console.log(new Date().toLocaleDateString("tr", {
    day: "2-digit",
    month: "long",
    year: "numeric"
}));

// Show a number in Arabic as Brazilian real
console.log(new Number(12345677).toLocaleString("ar", {
    style: "currency",
    currency: "BRL",
    currencyDisplay: "name"
}));

Using existing locale aware methods with locale and options

When to use each approach?

At the end of the day, which approach you use is up to you, and your use case. Using the existing methods are more concise, but if you are localising more than one piece of data with the same locale information, you will have to pass the locale and options each time. When using the Collation and formatter objects, you can set this up once and keep reusing it.

Wrap up

Phew, congratulations for sitting through all that, if you’re still here. I hope this gives you enough information to be able to dive deep into the Internationalization API, and start to add some locale awareness to your apps. You’ve seen how numbers and dates can be formatted using the local customs of individual languages and countries. You’ve also seen how strings can be collated using these customs, and vary degrees of strictness. You’ve also probably come to appreciate, if you didn’t already, how much work it would take to roll your own if localisation functionality is not built in.

While this API is designed for localising apps and sites, there are a number of formatting and collation options that may prove useful even when your app will never be translated; things such as formatting numbers and currencies correctly, to improving sort order or relaxing the strictness of search matching when punctuation or accented characters are used.

Work has already begun on the 2nd version of the Internationalization API. Currently including expanded Time Zone support (using the IANA time zone name), and Locale sensitive case conversion.

The API is clearly a first step along the road to adding full localisation support to JavaScript, but it already covers a lot of use cases. I know it would have been helpful for issues I’ve seen in the past with developing multi-language apps.

Appendix A: locale support

This appendix includes support tables for the language, country, and script tags that make up the locale, in each browser that supports the Internationalization API at the present time. This list may not be exhaustive, as there is no way via the API to return a full list of supported locales. Blink also doesn’t normalise the locale when testing directly via supportedLocalesOf(). Notable missing locales include those that contain a language, script and country code.

IE and Blink differ on how they support locales. In Blink (at least for Chrome and Opera, on both Windows and Mac), the supported locales come from the engine itself. That is, all browsers and OS combinations tested support the same locale list. In IE, the locale list comes from the underlying operating system. Therefore, IE11 on Windows 7 and Windows 8.1 support a different set of locales. Don’t worry though, windows 8.1 only adds locales; it doesn’t taketh away.

Note: I have added Firefox support to the tables below, but have not yet updated the post accordingly. You currently need to use a special build of Firefox Nightly with the Internationalization API enabled. Regular release and nightly builds do not currently have it enabled.

ISO639-1BlinkIE11/Win 8IE11/Win 7Firefox Nightly*
aaNoNoNo
abNoNoNo
afYesYesYes
akYesNoYes
amYesYesYes
anNoNoNo
arYesYesYes
asNoNoNo
avNoYesYes
ayNoNoNo
azYesYesYes
baNoYesNo
beYesYesYes
bgYesYesYes
bhNoNoNo
biNoNoNo
bmNoNoYes
bnYesYesYes
boNoYesYes
brNoYesYes
bsYesYesYes
caYesYesYes
ceNoNoNo
chNoNoNo
coNoYesNo
crNoYesYes
csYesYesYes
cuNoNoNo
cvNoNoNo
cyYesYesYes
daYesYesYes
deYesYesYes
dvNoYesNo
dzNoNoYes
eeNoNoYes
elYesYesYes
enYesYesYes
eoYesNoYes
esYesYesYes
etYesYesYes
euYesYesYes
faYesYesYes
ffNoYesNoYes
fiYesYesYes
fjNoNoNo
foYesYesYes
frYesYesYes
fyNoYesNo
gaYesYesYes
gdNoYesNo
glYesYesYes
gnNoYesNoNo
guYesYesYes
gvNoNoYes
haYesYesYes
heYesYesYes
hiYesYesYes
hoNoNoNo
hrYesYesYes
htNoNoNo
huYesYesYes
hyYesYesYes
hzNoNoNo
iaNoNoNo
idYesYesYes
ieNoNoNo
igYesYesYes
iiNoYesYes
ikNoNoNo
ioNoNoNo
isYesYesYes
itYesYesYes
iuNoYesNo
jaYesYesYes
jvNoYesNoNo
kaYesYesYes
kgNoNoNo
kiNoNoYes
kjNoNoNo
kkYesYesYes
klNoYesYes
kmYesYesYes
knYesYesYes
koYesYesYes
krNoNoNo
ksNoNoYes
kuNoYesNoNo
kvNoNoNo
kwNoNoYes
kyNoYesNo
laNoNoNo
lbNoYesNo
lgYesNoYes
liNoNoNo
lnNoNoYes
loNoYesYes
ltYesYesYes
lvYesYesYes
mgYesYesNoYes
mhNoNoNo
miNoYesNo
mkYesYesYes
mlYesYesYes
mnNoYesNo
moYesNoNo
mrYesYesYes
msYesYesYes
mtYesYesYes
myNoYesNoYes
naNoNoNo
ndNoNoYes
neNoYesYes
ngNoNoNo
nlYesYesYes
nnYesYesYes
noNoYesNo
nrNoNoYes
nvNoNoNo
nyNoNoNo
ocNoYesNo
ojNoNoNo
omYesYesNoYes
orYesYesYes
osNoNoNo
paYesYesYes
piNoNoNo
plYesYesYes
psYesYesYes
ptYesYesYes
quNoNoNo
rmYesYesYes
rnNoNoNo
roYesYesYes
ruYesYesYes
rwYesYesYes
saNoYesNo
scNoNoNo
sdNoYesNoNo
seNoYesNo
sgNoNoYes
shNoNoNo
siYesYesYes
skYesYesYes
slYesYesYes
smNoNoNo
snYesYesNoYes
soYesYesNoYes
sqYesYesYes
srYesYesYes
ssNoNoNo
stNoYesNoNo
suNoNoNo
svYesYesYes
swYesYesYes
taYesYesYes
teYesYesYes
tgNoYesNo
thYesYesYes
tiYesYesNoYes
tkNoYesNo
tlYesNoNo
tnNoYesNo
toYesNoYes
trYesYesYes
tsNoYesNoNo
ttNoYesNo
twNoNoNo
tyNoNoNo
ugNoYesNo
ukYesYesYes
urYesYesYes
uzYesYesYes
veNoNoNo
viYesYesYes
voNoNoNo
waNoNoNo
woNoYesNo
xhNoYesNo
yiNoNoNo
yoYesYesYes
zaNoNoNo
zhYesYesYes
zuYesYesYes
Supported ISO639-2 language codes with no ISO639-1 equivalent
ISO639-2BlinkIE11/Win 8IE11/Win 7Firefox Nightly*
arnNoYesNo
basNoNoYes
bemYesNoYes
chrNoYesNoYes
dsbNoYesNo
duaNoNoYes
ewoNoNoYes
filYesYesYes
gswNoYesYes
hawYesYesNoYes
hsbNoYesNo
kabNoNoYes
kamNoNoYes
kokNoYesNo
luoNoNoYes
masNoNoYes
mohNoYesNo
nqoNoYesNoNo
nsoNoYesNo
nynYesNoYes
sahNoYesNo
smaNoYesNo
smjNoYesNo
smnNoYesNo
smsNoYesNo
syrNoYesNo
vaiNoNoYes
zghNoYesNoNo

Note: IE11 supports the fil code for Filipino, but not the two letter code tl (Tagalog). As Blink supports both, it is best to use the former.

Supported ISO639-1 language codes with ISO3166-1 country code or UN M.49 region code
ISO 3166-1BlinkIE11/Win 8IE11/Win 7Firefox Nightly*
en-AGNoNoYes
en-BBNoNoYes
en-BSNoNoYes
en-BWNoNoYes
en-BZNoYesYes
en-CANoYesYes
en-CMNoNoYes
en-DMNoNoYes
en-FJNoNoYes
en-GMNoNoYes
en-GHNoNoYes
en-GDNoNoYes
en-GYNoNoYes
en-INNoYesYes
en-IENoYesYes
en-JMNoYesYes
en-KENoNoYes
en-KINoNoYes
en-LSNoNoYes
en-LRNoNoYes
en-MWNoNoYes
en-MTNoNoYes
en-MHNoNoYes
en-MUNoNoYes
en-FMNoNoYes
en-NANoNoYes
en-NZNoYesYes
en-NGNoNoYes
en-PGNoNoYes
en-PHNoYesYes
en-PKNoNoYes
en-PWNoNoYes
en-SGNoYesYes
en-KNNoNoYes
en-LCNoNoYes
en-VCNoNoYes
en-WSNoNoYes
en-SCNoNoYes
en-SLNoNoYes
en-SGNoNoYes
en-SBNoNoYes
en-ZANoYesYes
en-SSNoNoYes
en-SZNoNoYes
en-TZNoNoYes
en-TONoNoYes
en-TTNoYesYes
en-ZWNoYesYes
en-UGNoNoYes
en-VUNoNoYes
en-ZMNoNoYes
en-ZWNoNoYes
en-AUNoYesYes
en-GBYesYesYes
en-USYesYesYes
en-ASNoNoYes
en-BMNoNoYes
en-VGNoNoYes
en-KYNoNoYes
en-GINoNoYes
en-GUNoNoYes
en-GGNoNoYes
en-HKNoYesNoYes
en-IMNoNoYes
en-JENoNoYes
en-029NoYesNo
de-ATNoYesYes
de-BENoNoYes
de-CHNoYesYes
de-LUNoYesYes
de-LINoYesYes
nl-BENoYesYes
nl-AWNoNoYes
nl-CWNoNoYes
nl-SXNoNoYes
nl-SRNoNoYes
sv-FINoYesYes
es-ARYesYesYes
es-BOYesYesYes
es-CLYesYesYes
es-COYesYesYes
es-CRYesYesYes
es-CUNoNoYes
es-DOYesYesYes
es-ECYesYesYes
es-SVYesYesYes
es-GQNoNoYes
es-GTYesYesYes
es-HNYesYesYes
es-MXYesYesYes
es-NIYesYesYes
es-PAYesYesYes
es-PYYesYesYes
es-PEYesYesYes
es-PRYesYesYes
es-UYYesYesYes
es-VEYesYesYes
es-419YesNoYesYes
pt-BRYesYesYes
pt-AONoYesNoYes
pt-CVNoNoYes
pt-TLNoNoYes
pt-GWNoNoYes
pt-MZNoNoYes
pt-STNoNoYes
pt-MONoNoYes
it-CHNoYesYes
it-SMNoNoYes
fr-BENoYesYes
fr-BJNoNoYes
fr-BFNoNoYes
fr-BINoNoYes
fr-CANoYesYes
fr-CMNoYesNoYes
fr-CFNoNoYes
fr-PFNoNoYes
fr-GPNoNoYes
fr-MQNoNoYes
fr-YTNoNoYes
fr-NCNoNoYes
fr-RENoYesNoYes
fr-BLNoNoYes
fr-GANoNoYes
fr-GNNoNoYes
fr-HTNoYesNoYes
fr-LUNoYesYes
fr-MGNoNoYes
fr-MCNoYesYes
fr-MLNoYesNoYes
fr-MUNoNoYes
fr-NENoNoYes
fr-CGNoNoYes
fr-RWNoNoYes
fr-SNNoYesNoYes
fr-SCNoNoYes
fr-CHNoYesYes
fr-TGNoNoYes
fr-VUNoNoYes
el-CYNoNoYes
ro-MDNoYesNoYes
ru-BYNoNoYes
ru-KZNoNoYes
ru-KGNoNoYes
hr-BANoYesYes
zh-CNYesYesYes
zh-TWYesYesYes
zh-SGYesYesYes
zh-HKYesYesYes
zh-MONoYesNo
ms-SGNoNoYes
ms-BNNoYesYes
ms-MYNoYesYes
ar-DZNoYesYes
ar-BHNoYesYes
ar-TDNoNoYes
ar-KMNoNoYes
ar-DJNoNoYes
ar-EGNoYesYes
ar-ERNoNoYes
ar-IQNoYesYes
ar-PSNoNoYes
ar-ILNoNoYes
ar-JONoYesYes
ar-KWNoYesYes
ar-LBNoYesYes
ar-LYNoYesYes
ar-MRNoNoYes
ar-MANoYesYes
ar-OMNoYesYes
ar-QANoYesYes
ar-SANoYesYes
ar-SONoNoYes
ar-SDNoNoYes
ar-SYNoYesYes
ar-TNNoYesYes
ar-AENoYesYes
ar-YENoYesYes
bn-INNoYesYes
bn-BDNoYesYes
ta-INNoYesYes
ta-SGNoNoYes
ta-LKNoYesNoYes
ta-MYNoNoYes
ln-CDNoNoYes
ln-CGNoNoYes
sw-KENoNoYes
sw-TZNoNoYes
sw-UGNoNoYes
ti-ETNoYesNoYes
ti-ERNoYesNoYes

Note: This table excludes locales where the country code and language code are the same, and thus redundant, such as es-ES, fr-FR, etc. This list is not exhaustive; it only includes country and language codes that I have tested. It is possible that there are more supported.

Language/ScriptBlinkIE11/Win 8IE11/Win 7Firefox Nightly*
az-CyrlNoYesYes
az-LatnNoYesYes
ba-CyrlNoYesNo
bo-TibtNoYesNo
br-LatnNoYesNo
bs-CyrlNoYesYes
bs-LatnNoYesNo
co-LatnNoYesNo
ff-LatnNoYesNoNo
gd-LatnNoYesNo
ha-LatnNoYesYes
ig-LatnNoYesNo
ii-YiiiNoYesNo
iu-CansNoYesNo
iu-LatnNoYesNo
jv-LatnNoYesNoNo
kk-LatnNoYesNo
ks-ArabNoYesNo
ku-ArabNoYesNoNo
ky-CyrlNoYesNo
mi-LatnNoYesNo
mn-CyrlNoYesNo
mn-MongNoYesNo
oc-LatnNoYesNo
pa-ArabNoYesNoYes
pa-GuruNoYesNo
sa-DevaNoYesNo
sd-ArabNoYesNoNo
se-LatnNoYesNo
sn-LatnNoYesNoNo
sr-CyrlYes*YesYes
sr-LatnNoYesYes
tg-CyrlNoYesNo
tk-LatnNoYesNo
tt-CyrlNoYesNo
ug-ArabNoYesNo
uz-ArabNoNoYes
uz-CyrlNoYesYes
uz-LatnNoYesYes
wo-LatnNoYesNo
yo-LatnNoYesNo
zh-HansYesYesYes
zh-HantYesYesYes
arn-LatnNoYesNo
chr-CherNoYesNoNo
fil-LatnNoYesNo
haw-LatnNoYesNoNo
moh-LatnNoYesNo
sah-CyrlNoYesNo
sma-LatnNoYesNo
smj-LatnNoYesNo
smn-LatnNoYesNo
sms-LatnNoYesNo
syr-SyrcNoYesNo
vai-LatnNoNoYes
vai-VaiiNoNoYes
zgh-TfngNoYesNoNo

Note: Some language/script combinations may have multiple country specific locales, such as zh-Hans-CN and zh-Hans-SG. IE11 sometimes keeps the script in the normalised form of the locale, even when it only supports one script or language variation for that locale. Blink on the other hand always strips the script if it doesn’t support an alternative script or country variation. It normalises sr-Cyrl as sr. For a number of locales in the table above, Blink supports one form using just the language code, but it does not localise the data when formatting; I’ve marked those locales as unsupported in the table above, as it is impossible to tell which script it should be using.


Internationalization API tips and tricks

$
0
0

In my previous post, I introduced the Internationalization API. In this follow up I will show some tips and tricks for using the API and working around issues I found will writing that post.

Setting the locale based on the document language

In the previous blog post, I mostly set the locale by assigning it to a variable at the top of the JS file. Outside of small demos, it would be best not to hardcode the locale.

One approach would be to set the lang attribute (or xml:lang for XML documents, such as SVG), and then use this to set the locale.

var root = document.documentElement,
    lang = root.lang || root.getAttributeNS("http://www.w3.org/XML/1998/namespace", "lang") || "en",
    day = new Intl.DateTimeFormat(lang, { 
                    weekday: "long" 
                });

Set the locale based on the document language

This takes the language tag from the HTML lang attribute if it exists, otherwise takes it from the xml:lang attribute, and if all else fails, use a fallback language.

This assumes you are formatting something in the same language as the actual document. You may want to check for a language tag set in an lang attribute closer to where you will be inserting the result if you have a multi-lingual document. You’ll also probably want to listen for changes to the attribute value if you have an app where the language can be changed.

Use the API even for monolingual apps and sites

While the raison d’être of a internationalisation API is for supporting multiple locales, do not dismiss it if you are writing a monolingual app.

For one, you can use methods such as toLocaleString using the language of the page in question, rather than that of the browser, which is the default when no locale is specified.

The API also gives you much more control over formatting and collation options, such as varying the strictness of matching strings, setting minimum significant digits, displaying the month in its long, short or narrow form, and so on.

Use smart fallbacks

Not all languages and regions are supported by all browsers, but it is possible to supply a list of locales, or fix up flaky support.

Unsupported languages

If you need to use a language that is not supported by a browser, you can use a fallback by providing an array. Find languages that use the same customs as the language that isn’t supported.

For example, no (Norwegian macrolanguage) is not supported by Chrome or Firefox, but you can give a fallback of Norwegian Bokmål, Norwegian Nynork, and if all else fails, Danish (which uses the same sort order) if you want to collate according to Norwegian customs:

new Intl.Collator(["no", "nb", "nn", "da"]);

Be careful though; just because a locale behaves the same as another for one type of data, doesn’t mean it does for all. Testing is key here. You can check the CLDR data (or by type), but browser implementations don’t always agree.

Unsupported region

While there are not too many major languages that are missing, Chrome does not support many regional variations, outside of British and American English; Portuguese and Brazilian Portuguese; and multiple Spanish variations. In these cases the browser will likely fall back to the base language. This is a problem in English for dates, as the US uses an almost unique date format. While countries such as Switzerland use a specific format for numbers common to all languages in that country, rather than the format of the country where the base language is from.

Don’t be afraid to use a different locale instead of the one you need, if it is not supported, and the base language doesn’t give the correct formatting. While Chrome does not make it easy to detect if the right locale is being used, due to it not normalising the locale to the used form when testing for support, it is possible by checking the locale property after you have created a new instance:

var locale = "en-AU",
    country = locale.split("-")[1],
    usedLocale = null,
    formatter = null;

// Gah, Chrome says supported but it is not
console.log(Intl.DateTimeFormat.supportedLocalesOf(locale));

formatter = new Intl.DateTimeFormat(locale);
usedLocale = formatter.resolvedOptions().locale;

// Set to British English if the country is not included and lang is English
if (usedLocale.indexOf("en") === 0 && usedLocale.indexOf("-" + country) === -1) {
    formatter = new Intl.DateTimeFormat("en-GB");
}

Use an alternative fallback if only the base language is used

This wont work exactly as I wrote it if a script tag or Unicode extension is included in the locale, but that can be made smarter, or you can just hardcode the locale. Be careful for Canadian too, as they sometimes use the US format.

Don’t rely too much on default date formatting

Avoid numerical month formatting

As can be seen in the previous example, displaying the month as a number can be troublesome if the date is formatted in a different locale than they are expecting. Some people suggest using the ISO date format, but outside of people from countries that use such format, or geeks like us who know this format, it too could be confusing; what is to stop people used to US formatting assuming the date is formatted backwards for some reason, and that the month is in the last position?

A much clearer approach is just to display the month alphabetically. As we have locale information at our disposal, the drawback of needing to translate the month is no longer an issue:

var locale = "en-AU",
    formatter = new Intl.DateTimeFormat(locale, {
        day: "2-digit",
        month: "short",
        year: "numeric"
    });

// Chrome: “Nov 08, 2013”, IE11 “08 Nov 2013”
console.log(formatter.format(new Date("2013-11-09")));

Use alphabetical month

If you do not combine this with the previous tip to fix the formatting order, you will still not get a perfectly formatted date in many English speaking countries, but at least there will be no confusion.

A drawback that does exist is that as the month is not numerical, it may not be understandable if you’re using a language tag that is not supported (region/country sub tags are fine, as it will fallback to the correct language). This can be mitigated by using smart fallback languages (as covered previously) or only using alphabetical months for languages you know are supported.

Consider specifying the calendar when using Arabic

A number of different calendars can be used with Arabic. While Chrome uses the Greogrian calendar for its only ar locale, and the preview build of Firefox does the same for all Arabic locales, IE11 uses the Islamic calendar for both Arabic/Saudi Arabia and base Arabic. If you are just providing one Arabic translation, or IE falls back due to unsupported arabic locales (IE doesn’t support localisations for sub-Saharan African Arabic locales), the user may not get the date they expect. The inconsistancy with Saudi Arabian Arabic between browsers also isn‘t ideal.

Instead you can provide the calendar in the locale when using Arabic. In the follow example, IE will fallback to the arlocale, but will use the Gregorian calenedar rather than the default Islamic:

//  ٨‏/١١‏/٢٠١٣
var formatter = new Intl.DateTimeFormat("ar-SD-u-ca-gregory");
console.log(formatter.format(new Date("2013-11-09")));

Set calendar to Gregorian

If instead, you want to use the Islamic calendar in all browsers you can specify that with the islamic value:

// ٥‏/١‏/١٤٣٥"
var formatter = new Intl.DateTimeFormat("ar-SA-u-ca-islamic");
console.log(formatter.format(new Date("2013-11-09")));

Set calendar to Islamic

Correct the numbering system for certain Arabic locales in Chrome

While Arabic generally uses the Arab numbering system, Latin digits are used in Morocco (ma), Algeria (dz), and Tunisia (tn). As Blink only supports the base ar locale, it will format numbers and dates incorrectly for these locales. This can be fixed by specifying the numbering system in the locale for those countries:

var formatter = new Intl.NumberFormat("ar-DZ-u-nu-latn");

// "123.456.789,34" rather than "١٢٣٬٤٥٦٬٧٨٩٫٣٤"
console.log(formatter.format(123456789.34));

Specify Latin digits with the locale

Fix incorrect symbols and spaces

The preview release of IE11 includes a number of issues that I’ve found with formatting that are sub-optimal. Although these can be fixed, it is worth noting that IE11 has not been released yet, and they could be fixed before the final release.

Arabic commas

IE11 includes a regular comma (,) when formatting Arabic numbers. It should use the Arabic comma (٬) instead. This can be fixed with a simple find and replace.

In the following example, I test to see if either the used locale is ar (Arabic) or starts with ar- (Arabic plus some additional locale info, such as a country tag), and that a comma exists in the formatted number. If a different locale is used, or the problem doesn’t exist, the fix will not be applied. Note that you can not just check that the locale starts with ar as that may match 3 letter language codes, such as arn.

var locale = "ar",
    formatter = new Intl.NumberFormat(locale),
    usedLocale = formatter.resolvedOptions().locale,
    formattedNum = formatter.format(100000000000.100);

if ((usedLocale === "ar" || usedLocale.indexOf("ar-") === 0) && formattedNum.indexOf(",") !== -1) {
    formattedNum = formattedNum.replace(/,/g, "٬");
}

console.log("Fixed: " + formattedNum);

Replace comma with Arabic comma

Arabic percentage sign

Similarly, IE11 has an issue where it uses a regular percentage sign (%), rather than an Arabic percentage sign (٪). This can be fixed in the same way. I’ve changed the previous code to check for both:

if ((usedLocale === "ar" || usedLocale.indexOf("ar-") === 0)) {
    if (formattedNum.indexOf(",") !== -1) {
        formattedNum = formattedNum.replace(/,/g, "٬");
    }

    // assumes only one percentage sign in the string
    if (formattedNum.indexOf("%") !== -1) {
        formattedNum = formattedNum.replace("%", "٪");
    }
}

Replace percentage sign with Arabic percentage sign

Of course, in a real app you’d probably want to put this in a function. You may also want to check to make sure that the style is set to percent and useGrouping is truthy, but I didn’t bother, as I figured these characters wouldn’t be included otherwise.

Non-breaking spaces

When formatted numbers have spaces, such as the decimal separator in the French locale; or when a unit is included, such as a percentage sign or currency symbol, it is important to use a non-breaking space. This keeps the whole number and any unit together when a line wraps. Allowing them to break onto separate lines can cause confusion, and generally looks unprofessional.

Fortunately, all browsers that implement the Internationalization API include non-breaking spaces for the grouping separator, but IE11 includes a regular space before (or after) the percentage sign (if a space is used at all) or the currency unit. This can also be fixed with a simple find and replace:

if (formattedNum.indexOf(" ") !== -1) {
    formattedNum = formattedNum.replace(/ /g, " ");
}

Replace regular spaces with no-break spaces

The one place where this falls down is when using currency names, as they often have spaces (e.g. “Swiss Franc”). You probably want to guard against this by doing some extra checking.

Vertical text update: text-combine-horizontal

$
0
0

In a previous blog post, I covered vertical text using CSS writing modes. At that time, it was possible to use vertical text in both IE (and has been since version 5.5) and WebKit. Since Opera switched to Blink, it now also joins that list. However, at that time, the support for more advanced control of glyphs within a vertical layout was very limited.

While the support does remain limited, the IE11 preview has become the first browser to support the text-combine-horizontal feature. I will show you this feature in this blog post; but first, a brief overview of how to use vertical text.

Setting text layout to vertical

Vertical layout can be achieved by using the writing-mode property. When text is laid out vertically, lines of text can proceed from right to left (as in CJK languages), or left to right (traditional Mongolian).

In the W3C Writing Modes specification, top to bottom, right to left text can be achieved using the vertical-rl value. IE implemented this before the current spec, and thus uses an older syntax–tb-rl–that came from SVG:

-ms-writing-mode: tb-rl; 
-webkit-writing-mode: vertical-rl;
-moz-writing-mode: vertical-rl;
-ms-writing-mode: vertical-rl;
writing-mode: vertical-rl;

The less used top to bottom, left to right orientation can be achieved with vertical-lr and tb-lr for IE.

Glyph orientation

Outside of Asian languages like Chinese and Japanese, it is not customary to write using a vertical layout, but it is not unheard of. The Coke can sitting next to me has “Coca-Cola Zero” writen vertically, bottom to top, left to right. If you walk through any major city and look up at store signs, you’ll often see vertical text to save space. You’ll also see it on spines of books. In Asian vertical layouts, you will often see Latin (or other scripts) mixed in with the native script. In all these cases, there needs to be some control of the glyph orientation.

As far as I know, East Asian scripts always orientate there characters horizontally; they don’t flip on their side when displayed vertically. Latin characters can either be flipped on their side, following the direction of the text (such as on the aformentioned Coke can) or left upright, as seen on many store signs.

If you read my previous post, you’ll know that you can set the glyph orientation with the text-orientation property. Support for this hasn’t changed; it is still only supported in WebKit/Blink, and it still only has partial support. The upright value for keeping all glyphs in the horizontal orientation is the most important one for this article.

Combining upright characters

While by default characters are displayed one after another in the direction of the line, it is often desirable to display two or more side by side when using vertical text. A common example of this is Latin numbers in dates; instead of the digits in the month or day being displayed one after another, they are combined as if they were one character (actually 1em) wide.

IE11 adds support for the text-combine-horizontal property which enables this feature. There are two different modes, which act fairly differently, so it is important to understand how they work.

Combining digits

When you just want to combine digits, such as in our date example, you can use text-combine-horizontal: digits. By default this combines any two digits or less that are found together. If you specify a number after the digits keyword, it combines up to that many digits. The upper limit is 4. The glyphs are orientated upright, even if text-orientation is not applied, which is just as well, as IE doesn‘t support that property.

text-combine-horizontal: digits; /* combines runs of 1–2 digits (0–9) together*/
text-combine-horizontal: digits 2; /* same as above */
text-combine-horizontal: digits 4; /* combines runs of 1–4 digits */

The following example is inspired by a Mexican street sign found in Thinking with Type. The text-combine-horizontal: digits; declaration is used to combine each set of two digits in a 1em by 1em square, with the glyphs orientated horizontally:

Mexican street sign demo

There are some things to note here:

  • Each two digit pair are seperated by a space in the markup. If there were no spaces, there would be more than two digits together, and they would not be combined.
  • A space is not needed between a digit and a non-digit, as only number are counted. Thus if “Z88” was in the markup, “88” would still be combined together.
  • The “Z” in this example is not oriented upright as it is not a digit (more on that later)
  • When using the digits value, it will look for any runs of digits in the text of the element it is applied on…
  • …but the property is not inherited, so if there are any child elements (such as spans, em, strong, etc. Not exactly an uncommon occurrence) it will not apply to any text in those elements. This can be seen in an updated version of the demo. This is noted as an issue in the spec, and I hope it gets resolved.

It is also important to be careful when using this feature. While it only works on digits, sometimes long strings of digits are pretty printed to make them easier to read (as you will have seen in my Internationalization article). CJK languages use a comma for this. As this will split a run of digits, you may get part of the number combined and the rest left in the default state. The number 10,000,000 will combine 10 and leave the rest untouched. For this reason, it may be best, if you are likely to have situations like this, to use an inline element such as a span around digits you want to combine. This can be seen in a demo I updated from the previous vertical text article:

Japanese vertical text demo, with text-combine-horizontal

In this demo I combine any 3 digits or less that are found together. I highlighted all the digits in spans in red to be easier to find. Changing the value to 4 will combine the years as well. When four digits get combined, they can get quite compressed, so it is probably only wise to do this far large text sizes.

A couple of issues I found when making the previous demos is that IE applies any text-indent to text that has text-combine-horizontal applied (even if text-indent is only applied to the element’s parent), so this has to be cancelled out; and text-combine-horizontal is not applied to inline elements, even when directly specified on that element. Applying display: inline-block fixes this:

section span {
    /* make IE apply text-combine-horizontal to a span */
    display: inline-block; 
    /* remove text-indent that was applied on parent */
    text-indent: 0;

    -webkit-text-combine-horizontal: digits 4;
    -moz-text-combine-horizontal: digits 4;
    -ms-text-combine-horizontal: digits 4;
    text-combine-horizontal: digits 4;
    color: red;
}

One could take the opposite approach, and wrap the text you don’t want combined in spans, but in my case that wouldn’t work unless I remove the text-indent. If you do this, it is important to set text-combine-horizontal: none on the span, as if the spec is changed so that inheritance is allowed, it will suddenly break. Better to be safe than sorry.

Combining all text in an element

While the digits value only works on, well, digits, you can use the all value for any character. However, it is not that simple. It doesn’t look for runs of characters inside the element and look to combine them, but instead, it tries to combine the entire text content of the element. As with the digits value, the advance width of the result has to fit within a 1em square. As you can imagine, for a few characters that is pretty easy; a number of fonts even have half-width, third-width and quarter-width variants for certain glyphs; but for longer text, it is going to become unreadable quite fast. This text-combine-horizontal: all demo shows this in action.

Something important to point out is that this only works with (non-replaced) inline elements, unlike the digits value, which works in the polar opposite way in IE. I think this is fine, as you’re likely to be individually marking things up where this is to apply to when it works the way it does with all text in the element. It is also not applied if the element contains any child elements.

If you remember our earlier issue with the “Z” that didn’t rotate in the Mexican banner example, you will probably now see how that can be fixed using a span and text-combine-horizontal: all:

Mexican banner with Z in the correct orientation

HTML

<h1><span>Z</span> 44 82 98</h1>

CSS

h1 {
    …

    -ms-writing-mode: tb-rl;
    -webkit-writing-mode: vertical-rl;
    -moz-writing-mode: vertical-rl;
    -ms-writing-mode: vertical-rl;
    writing-mode: vertical-rl;

    /* only currently works in Blink/WebKit */
    -webkit-text-orientation: upright;
    -moz-text-orientation: upright;
    -ms-text-orientation: upright;
    text-orientation: upright;

    /* only currently works in IE11 */
   -webkit-text-combine-horizontal: digits;
   -moz-text-combine-horizontal: digits;
   -ms-text-combine-horizontal: digits;
   text-combine-horizontal: digits;

}

h1 span {
    /* Sets upright orientation for the Z */
    -ms-text-combine-horizontal: all;
}

As you can perhaps see, WebKit/Blink can use text-orientation: upright; to make the Z glyph display upright. I’m a little suprised that Microsoft added text-combine-horizontal without adding text-orientation and updating the values used by writing-mode. Perhaps for IE12?

Setting native-like scrolling offsets in CSS with Scrolling Snap Points

$
0
0

One of the arguments in favour of native vs. Web is that of user experience; particularly when it comes to scrolling. A typical interaction on touch screens (especially tablets) is the sideways swipe to flip between items, such as the next/previous page or photo. Native apps handle this…well…natively. The platform deals with it, so the performance is good, and the behaviour is consistent between apps on the platform. Web apps, on the other hand, have to roll their own. This usually involves a bunch of complex JavaScript, and it isn’t hardware accelerated. As it is an emulation, the behaviour may differ from that on the user’s platform.

However, some platforms use web technologies for native apps. As such, the platform vendor has probably had to solve this problem using those tools. One such platform is Windows 8. Internet Explorer 10+ provide a bunch of vendor specific CSS properties for touch-based scrolling. As these have proven useful, the properties for scroll offsets have been recently been added to the standards track as Scroll Snap Points. In this post, I will quickly guide you through the functionality that is currently in the spec. As it is very new, everything is subject to change, but it does work as is in IE 10 and 11.

Setting snap point behaviour

The first step is to specify how snap points are used, if at all. This is set with the scroll-snap-type property. As with all properties in this spec, IE currently needs the -ms- prefix.

The default value is none which means that any snap points are ignored. If you want to enable them, you need to use the mandatory or proximity value. The first states that any snap points must be used, while the latter leaves it up to the user agent to decide if it is appropriate to use or not.

Specifying where the snap points lie

There are two properties to specify snap points; one for each scroll axis. The scroll-snap-points-x property handles the x axis, and (as you can imagine) scroll-snap-points-y handles the y axis. Both properties accept the same values.

Using regular offsets

If you want to scroll the same amount each time (such as scrolling a full page of content at a time, or if each item of content is the same width or height) you can use the snapInterval() function. The first value sets the position of the first snap point, and the second sets the interval for each subsequent snap point. Each value is a CSS length value or a percentage (of the padding box of the scroller).

In the following contrived demo, I have a bunch of divs, 500px tall. As there is a 100px top padding, I’ve set the first position to 100px, and the interval to 525px (the hight of the div, plus the margin). If you scroll down, each swipe will move exactly one element up or down. The very first swipe will scroll down 100px to the first snap point. If you scroll back to the start, you will not be able to scroll the first 100px into view.

#container {
  -ms-scroll-snap-type: mandatory;
  scroll-snap-type: mandatory;
  
  -ms-scroll-snap-points-y: snapInterval(100px, 525px);
  scroll-snap-points-y: snapInterval(100px, 525px);
}

div {
  width: 500px;
  height: 500px;
  margin: 0 auto 25px;
}

Try scrolling up and down in the simple demo in IE10+

If you want to scroll the entire width or height of the scroller, you can use a percentage instead of a length. In this full viewport demo, I set the start position to 0% and the intervals to 100% (this is actually the default, but I’ve included it to illustrate the concept). I also set the scrolling container to 100vh and 100vw:

#container {
	overflow: auto;
	height: 100vh;
	width: 100vw;
	white-space: nowrap;
				
	-ms-scroll-snap-type: mandatory;
	scroll-snap-type: mandatory;
	-ms-scroll-snap-points-x: snapInterval(0%, 100%);
	scroll-snap-points-x: snapInterval(0%, 100%);
}

Note: As Blink and Gecko no longer use prefixes for new properties, I’ve not included the -moz- and -webkit- prefixes. As the functions use camelCase rather than the usual hyphen separated CSS syntax, I suspect the names may change before the final version of the spec anyway.

Using different offsets

While snapInterval() is great if your content is a consistent size, there are times when the items you want to scroll into view may be irregularly sized. This is where snapList() comes into play. This accepts one to many comma separated values, each specifying a snap point. Each point is the actual position along the axis, rather than an offset from the previous point (this tripped me up at first).

In the following demo I have images that have different aspect ratios, so their widths are different. I want to scroll so that the next image moves to the start of the container when swiping left or right. I calculated the position along the x axis where each image starts and added that to the snap list:

#gallery {
      -ms-scroll-snap-type: mandatory;
      scroll-snap-type: mandatory;

      -ms-scroll-snap-points-x: snapList(786px, 1643px, 2483px, 3264px, 4054px,  4402px);
      scroll-snap-points-x: snapList(786px, 1643px, 2483px, 3264px, 4054px, 4402px);
} 

Try swiping the images in IE10+

There are a couple of things to bear in mind. Firstly, remember to set an initial snap point, so that when scrolling back, the first item can be seen (set to 10px in the demo). Secondly, if there is not enough content to scroll into view the snap point will not be used and you won’t be able to scroll to the last bit of content, so it is important to calculate the last snap point correctly. In this demo, you will see that the last scroll point is much shorter, so that it just reveals the end of the photo. If I tried to scroll the last image to the start of the container, there would not have been enough content to the right of the image, and the snap point would have been ignored.

Advantages of snap points

One of the key advantages is the simplicity of authorship. You can control the behaviour with just two CSS properties, rather than a bunch of custom JavaScript, or importing a library (that the end user’s browser has to download). The performance is also smooth, as the user agent can optimise the performance, and hand it off to the GPU.

Another huge benefit is that it behaves as expected on the platform. In IE’s case, if you slowly drag the image in the gallery, it will stick with your finger. If you let go just before half way between snap points, it will bounce back to the original position, while if you drag it a bit further, it will automatically scroll all the way. It handles all these small details for you.

Great, where can I use it?

Being a brand new spec compatibility is limited. It is fully supported in IE10 for touch, while in IE11 it is also supported for trackpad gestures, mouse, and keyboard, including scrolling by clicking on the scroll bar. Hopefully we will see more uptake as the spec matures.

You can find up to date support information in my CSS Scroll Snap Point support table.

Internet Explorer 11 review, part 1

$
0
0

In this review of Internet Explorer 11, I’m going to attempt to ascertain if it can actually be considered a modern browser.

There has been much written about IE since Microsoft allowed to to stagnate with IE6. There have been a number of jokes written about IE; you probably reconigse them, as they are hardly original and get repeated ad nauseam. There is the one about how slow IE is, then how unpopular it is, and then the one about downloading [insert the favourite browser de jour here]. Then there is the revisionism about IE6. Yes, it actually was a good, and popular browser. when it was released.

But, do the popular perceptions about IE still hold up today, or are they as outdated as those about memory management in Firefox, or that Opera (who boasts a quarter of a billion users on mobile alone) has no users? Read on to find out.

First, an important disclaimer. While I do not work for Microsoft, I am part of the IE userAgents community and the company I work for is a vendor for Microsoft. However, Microsoft did not ask me to write this post, nor have they seen it or suggested any content. In fact I’ve just finished it a few seconds ago. I have also been involved in various roles with Opera and WebKit.

Ever since IE10 was getting ready to be released, I’d tell anyone that would listen that “hey IE9 is pretty crappy, but IE10 is looking to be a pretty good browser. I suspect by the time IE11 comes out, it will have caught up with the other browsers.” So, did that actually happen? This post, and subsequent ones in the series will attempt to find that out.

First we have to define what a modern browser actually is. I’d define that in various ways. As a web developer, I care about web platform capabilities, especially as they pertain to open web standards. A modern web browser has to be able to support what web developers are building today, and what they may want to develop in the near future. A modern browser needs to be performant and keep the user secure. To achieve this it probably needs some form of modern architecture that takes advantage of today’s hardware capabilities. I’d also argue it needs to offer a well rounded developer story, such as developer tools and the ability to be deployed quickly, without having to wait years for users to upgrade to the latest version. Above all, it needs to keep pace with the competition, as if it is way behind the other browsers, it is holding the web back. We saw this with earlier version of IE as they attempted to catch up from a 5 year head start they gave to everyone else.

There is too much to cover in one post, so I’m breaking this review down into multiple parts. Even I don’t know what the result will look like in the end. For this first part, I will look into the elephant in the room; IE’s release schedule and update strategy. I will also briefly look into the story around use of prefixes and standardisation of new features. Lastly I will take a shallow look at web standards support as measured by popular test sites. As these sites have major gotchas, in subsequent posts, I will look into greater detail for each of the major areas: HTML, CSS, JavaScript, and web platform APIs. This post will see where IE11 stands with the features those test sites choose to measure, while the deep dive will attempt to look at all the features as a whole, including those missing from the tests.

Release schedule

It doesn’t matter how good or modern a browser is, if it is not in the hands of the user. I call this the elephant in the room for IE as it is an area where Internet Explorer receives a great deal of–mostly warranted–criticism. The biggest issue, of course, was that hulking big break between IE6 and IE7. At approximately 5 years and 2 months, this period was the dark ages of the Web. The gap between releases has come down since, but they are notably less frequent than other modern browsers, but one.

There are now essentially two release models for browsers. Chrome and Firefox have moved to a rapid release cycle, releasing approximately every six week. IE and Safari are generally tied to OS releases, so are at the mercy of their cycles. Opera was somewhere in the middle with a couple of releases a year, but have moved to the Chrome model now that they’ve switched to Blink.

So how often is IE released, and how does it compare to Safari? Let’s look:

IE release history

Version Release Date Time Between ReleasesDifference
IE 7 Oct 2006 5 years, 2 month +2 years 3 months
IE 8 Mar 2009 2 years, 5 months -2 years, 9 months
IE 9 Mar 2011 2 years -5 months
IE 10 Oct 2012 1 year, 7 months -5 months
IE 11 Oct 2013 1 year -7 months

Although IE11 was released a year after IE10, each release has been coming progressively faster. As IE10 for Windows 7 was actually delayed by 4 months, it was released just 8 months before IE11 for Windows 7.

Safari release history

Now let’s compare how Safari stacks up:

Version Release Date Time Between ReleasesDifference
Safari 3 Oct 2007 2 years, 6 months +8 months
Safari 3.1 Mar 2008 5 months -2 years, 1 months
Safari 3.2 Nov 2008 8 months +3 months
Safari 4 Jun 2009 7 months -1 month
Safari 5 Jun 2010 1 years +5 months
Safari 5.1 Jul 2011 1 year 1 month +1 month
Safari 6 Jul 2012 1 year -1m
Safari 7 Oct 2013 1 year 3 months +3 months

As you can see, Safari originally had long release cycles (as did everyone at the time), had a period of rapid (for the era) releases, and have settled into a release per OS version cycle. This is around one release per year, but as OS X has (purportedly) been delayed due to allocating more resources to iOS, this has slipped somewhat, especially with the latest version.

If you compare with IE, there were two Safari releases per IE release between IE8 and IE10. IE11 on the other hand was released before Safari 7, and thus technically there were no Safari releases between IE10 and 11, but in reality both are on similar yearly release schedules, with IE getting slightly faster. It will be interesting to see if IE continues to reduce the gap between releases or stick to the once a year releases. Other apps built into Windows 8 get updated out of band, but they are not as deeply tied into the OS as IE.

While I’d prefer more regular updates than once a year (perhaps quarterly or every half year would be nice), it is clear that IE is keeping pace with its most similar competitor, and the improvements are encouraging. If IE can’t be considered a modern browser due to it’s release schedule, then the only major desktop WebKit browser on the market can’t be considered modern either.

Update strategy: Evergreen browsers

While regular updates are nice, they don’t mean anything if old versions stick around (Hello IE8!) Getting users onto the latest version is critical. Firefox and Chrome have this down to a T; they really have to, as with releases every 9 weeks, if it took longer to update they’d not have transitioned before the next release comes out.

Browsers that auto-update in this manor have become known as evergreen browsers. Users are always on a pine fresh browser, and all is good with the world (never mind that pines and furs shed needles.) IE versions are presumably deciduous browsers. Grand old oak trees that stand stubbornly proud for many years, with armies of squirrels pelting web developers with acorns.

So which is IE11? The good news is that since IE9, Internet Explorer has included auto-update functionality. In theory then, IE9 and above are evergreen browsers. There are however some complications. While IE9 does auto-update, IE10 was never made available for Windows Vista. As such, IE10 has surpassed IE9 in any marketshare metric you care to look at, but it still has a bunch of users: around 6-7 percent using StatCounter, Akamai and Clicky stats, and 9.5% on NetApps (which is always the outlier due to the way it adjusts its data.)

While IE10 drops Vista support, IE11 is available for the same platforms as IE10. Well, not exactly; it is available for Windows 8.1 instead of 8, but it is a free update that will be pushed out to all Windows 8 users. In theory, while a bunch of IE9 users will remain, IE10 should disappear completely, except for those evil sysadmins and enterprise developers (as Bruce puts it in his previously linked video) that may block the update for their users.

While that is the theory, how is it working out in practice? It is too early to say, but the signs are promising. Using StatCounter stats, IE8 took 9 months to reach the same marketshare as IE7, while IE9 took 1 year to reach IE8. IE10 on the other hand took 29 weeks to overtake IE9, but only 11 weeks from the release of IE10 for Windows 7. It also took 11 weeks from the Windows 7 release using Akamai stats and 13 using Clicky Stats. As IE11 for Windows 7 came out only 3 weeks after the 8.1 version, we should see this time drop dramatically. [Edit: less than a week after thi s post was publish, IE11 surpassed IE10 on both StatCounter and Clicky. The table below has been updated with this week’s data.] But even if we just take the Windows 7 releases into account, the uptake speed is currently faster for IE11. In the table below, I take the market share on each day exactly a week after the previous, starting one week after the release date on Windows 7.

Version Stat provider Week
1 2 3 4 5 6 7 8 9 10 11 12 13
IE10 StatCounter 1.36 1.48 2.35 3.13 3.82 6.72 6.26 5.74 6.13 8.5 10.23 7.75 8.34
IE11 StatCounter .98 2.21 3.84 5.43 6.23 The future
IE10 Clicky 1.42 1.53 2.35 3.01 3.74 4.28 4.36 4.43 4.85 5.33 5.76 6.1 6.78
IE11 Clicky 1.04 2.53 3.24 4.81 5.85The future

Even though IE11 had been on the market for less time when the Windows 7 version was released, and thus starts with a lower market share, it is around 6 weeks ahead of what IE10 was on Clicky, and around 2–4 weeks ahead on StatCounter. It has already surpassed IE10’s market share on both services. I’ve not included Akamai in the table above as it does not yet detect IE11. NetApps on the other hand doesn’t support daily or weekly stats without a paid upgrade.

If you look at the trend graph for both Clicky and StatCounter you can clearly see IE11 growing at the expense of IE10. While Akamai currently doesn’t detect IE11, you can see IE10 starting to rapidly fall away.

As an aside, IE7 is way more popular on Akamai than StatCounter and Clicky. This is almost certainly because Akamai detects IE browsers in compatibility mode as IE7. As Akamai is used by many of the top traffic sites, and thus more likely to be added to the compatibility list, I suspect this is a large percentage of these users. They will be fixing this issue shortly.

Although IE adoption time is dropping between releases, it is clearly slower than Chrome and Firefox. Part of this is likely due to the type of users IE has versus those browsers (especially enterprise users), and the release schedule not mandating such a rapid adoption rate. It also seems that Microsoft is more conservative with pulling the trigger on the updates. You can clearly see stages in IE adoption where the current version of IE jumps then plateaus for a while. This suggests that the users are updated in stages. Probably after minor releases are ready and bugs have been ironed out.

With Safari, you can clearly see with Clicky stats that there is a dramatic uptake right out of the gate for Safari 7. This is likely due to OS X Maverics being free for all users of fairly recent versions of OS X, and Apple being far more aggressive pushing that update out. On my OS X machine the update showed right away, while I had to go digging for the Windows 8.1 release. You can see however that the uptake has started to plateau, and that the uptake of 6.1 (essentially Safari 7 for the previous version of OS X) is slower. Safari also has the same issue as old version of IE, with Safari 5 and 5.1 still hanging around. Indeed, 5.1 is currently the most popular version of Safari. I suspect Apple’s policy of giving away the OS for free will lead to modern versions dying off quickly, but it remains to be seen if 5 and 5.1 continue to overstay their welcome.

For IE adoption going forward, the key issue is when and if they drop support for older versions of Windows. We can see this creates beach heads where certain users are stuck on a version of IE. We see this with IE8 and XP, and perhaps IE9 and Vista (which is fortunately less popular and likely to have a fraction of the impact.) If Microsoft drop support for Windows 7 we could have a catastrophe of IE8 proportions. I really don’t see that coming though. With Windows 7 as popular as it is, Microsoft would be mad to drop it any time soon. Windows 7 is actually a pretty good operating system, so there is little benefit to dropping it right now, while supporting XP would take substantial resources. I’ve heard talk of Microsoft only supporting the current OS and current OS - 1, but that is just not how things have worked in the past. Ignoring server versions, IE8 was available for Windows 7, Vista, and XP, while IE6 was on XP, ME, 2000, 98, NT4, and 95.

In conclusion, this is clearly an area where Microsoft could do better, but things look like they’re moving in the right direction. IE8 will haunt us for a while, but the mistake shouldn’t be repeated with modern versions of IE, as long as they continue to keep Windows 7 along for the ride. I’d like to see Microsoft be as aggressive as Apple with pulling the trigger on the auto-updates. We’ll have to wait to see if this happens, as we’re only a month into IE11 for Windows 7.

Prefixes and standardisation

Prefix strategy

Prefixes are a pain for everyone, causing compatibility issues for users and browser vendors, and maintenance issues for developers. It is clear something has to be done to fix the problem. The Solution Google and Mozilla have come up with is to not add prefixes for new features and include the feature behind a runtime flag, disabled by default. The thought is that if the features are not exposed to the web, the standardisation process will move faster as the browser vendors will want to include the feature, and the development to update the feature to match the spec will happen faster.

This feature behind a flag solution has been adopted by Firefox, Opera, and Chrome. Safari meanwhile looks like it will keep polluting the Web with -webkit- prefixes, although there is no definitive official statement.

As for IE, mum is the word so far. If Microsoft don’t adopt this method, we’ve only really lost the -moz- and -o- prefixes.

So far we have been fortunate that there are not that many -ms- prefixes out there. Microsoft’s strategy has been more conservative in that they generally implement mature specs, such as how they were the first browser to fully support CSS2.1. As they were playing catch up from their long siesta, many of the CSS3 specs were mature enough to implement without a prefix. That is no longer the case now.

Newly proposed IE11 features such as ime-align do use a prefix however.

My main worry is that with less regular updates, IE and Safari will be less likely to disable new features they’ve added, as it will take a year–rather than nine week intervals–before they get the chance to enable them. I can’t say either way which way IE will go, so this is one for the future.

Standardisation

While standardisation of features doesn’t really relate to if a browser is modern or not, it is indicative of modern thinking by the browser vendor, and their willingness to play well with others. I will also only include features on the standards track in the deep dive into standards support in future articles.

So, how is Microsoft doing in this regard?

One of the headline features of IE10 was touch browsing. Instead of the (potentially patent encumbered) Apple touch events model, Microsoft made their own Pointer Events model. This was submitted to the W3C, and within a year it has become a Candidate Recommendation. IE11 was updated to the latest spec, and the prefixes were removed. So far, so good.

Also related to touch, IE10 added its own proprietary CSS properties for scrolling and zooming with touch. The scrolling properties were updated in IE11 and added to a new Scrolling Snap Points spec. I’m not sure what is happening with the zoom properties.

In IE11 almost all of the new features seem to be based off existing standards or proposals. They went with WebGL and Google’s SPDY, rather than inventing their own incompatible alternatives (WebDirectX anyone?) One of the new headline features is the ability to play “premium video content.” Microsoft is an editor on many of the various specs that enable this, including TML Simple Delivery Profile for Closed Captions, EME, MSE, etc.

One area where IE11 adds new prefixed features is for working with IMEs (Input Method Editors, as often used for CJK (Chinese, Japanese, Korean) languages.) These new properties and methods have been submitted to the W3C as the Input Method Editor API. At the time of writing this is still an Unoffical Draft.

In conclusion, while the prefix situation remains unclear, Microsoft look like they are well and truly on the standards track with IE11. It is encouraging that there was no major new feature added that doesn’t have an existing spec or a proposal submitted.

Standards support

Standards support is the area where most developers would judge if a browser is modern or not. If you read Tweets, you’d get the impression that IE is way behind the competition in this regard. But does the perception meet reality?

To answer that question fairly, we’d have to look across the various specs and see how each browser stack up. I plan to do that, at least for the major specifications, but for the first part of this review I’m going to look at the commonly used standards support tests to give a first impression. I’ll also cover what they actually test, and any drawbacks they may have.

HTML5Test

Probably the most commonly used test is the HTML5Test. This focuses on HTML5 (obviously), but also includes a bunch of things not in the spec. It does not cover CSS (except one feature), JavaScript, DOM, SVG (beyond testing if it works in HTML documents), or various other specs. As is common with these kinds of test, it only covers features that were new when the test was first made, and those that were released since then. As such it also doesn’t cover features that already existed in HTML4 and below.

The test gives a score for each feature supported. The score differs between features, so it depends on what value the author gives it. As with other tests of this type, it does not test how well a feature is supported.

As many of the features tested are relatively new, the score is more relevant the newer the browser. For older browsers, many of features may not even have existed when it was released. As such you shouldn’t give much stock in how much better or worse IE8 is verses it’s competition at the time.

What HTML5Test does tell us is how well browsers support some HTML5 and cherry picked APIs, based on the weight the author gives those features.

So how do IE versions stack up to other browsers of similar vintage?

Internet Explorer 8 vintage browsers

Browser Points Difference from IE
IE8 43 X
Chrome 1 32 -11
Opera 10.1 122 +79
Safari 4 156 +113
Firefox 3.5 159 +116

Note: Chrome 2 was actually the closest release to IE8, but it is not listed on the HTML5Test site.

Here you can see that Gecko and WebKit browsers are dominating IE, and to a lesser extent Opera. In the context of this time frame, you have to remember that many of the features tested did not exist yet. The IE8 release also focused on CSS2.1, which is not tested here at all.

Internet Explorer 9 vintage browsers

Browser Points Growth Difference from IE Difference change
IE9 129 86 X X
Firefox 5 287 128 +158 +42
Opera 11.1 288 166 +159 +80
Safari 5.1 319 163 +190 +68
Chrome 10 359 327 +230 +241

Here we can see that each of the browsers increased the gap over IE9. Firefox moved from first place to second last, behind Opera. By this time Chrome has shown a dominance in this test that it has never relinquished to this day.

Internet Explorer 10 vintage browsers

It is with IE 10 that I feel Microsoft was done with catching up with the foundational features it lacked (DOM, CSS2.1, etc) and was ready to add more modern feature. Did that prove to be the case?

Browser Points Growth Difference from IE Difference change
IE10 336 207 X X
Firefox 16 376 89 +40 -118
Safari 6 380 61 +42 -148
Opera 12.1 392 104 +56 -103
Chrome 23 472 113 +136 -94

While Opera 12.1 (the last ever Opera Presto version, RIP) surpassed Safari,and Chrome remained on a tear, IE10 got within two digits of all browsers except Chrome. Similar gains with IE11 would move it to 2nd position.

Internet Explorer 11 vintage browsers

Browser Points Growth Difference from IE Difference change
IE11 376 40 X X
Safari 7 397 17 +21 -19
Firefox 25 447 71 +71 +31
Opera 17 467 75 +91 +35
Chrome 30 499 27 +123 -13

This was a mixed bag for IE11. It is now only 21 points from Safari and closed the gap slightly with Chrome, but lost ground to Firefox and Opera. The latter benefiting from the switch to Blink.

When IE10 came out, I expected IE11 would at least catch up to one of the other browsers. That didn’t happen, but that can perhaps be attributed to having a shorter release cycle than the previous version.

Overall, despite still being in last position, IE is within spitting distance of Safari, and not out of sight of Firefox. There is certainly a case to be made that it is a modern browser here.

HTML features supported by all browsers except IE11 include the main, meter and output elements, and the reversed, ping, elements attributes, and the control and form property, and the on invalid event. APIs not supported include the Web Audio API, Server Sent Events, and CSP 1. CSS (!) not supported includes Blending Modes.

CSS3Test

The CSS3Test covers new features in CSS level 3 specs and some new CSS level 1 specs. It does not cover features that existed in CSS2.1 (so IE8 having better support than many browsers is not reflected). It also does not include every CSS spec, or CSS Level 4 property/values (keeping up with everything is time consuming, especially when these tests are usually hobby projects.) The test checks for the existence of features rather than if they are actually supported. As is mentioned in the test itself, browsers can claim support, without actually doing anything more than parse it. Some WebKit/Blink based browsers may have an inflated score because of this.

I believe the way scoring works here is that every test is worth an equal score. So a spec with a lot of properties or values will be given a lot more points than a spec that may be as complex or more so, but with few properties or values. The test does not distinguish between supporting a property with or without prefix, however, if a property or value was renamed, the older syntax will not be picked up. IE10 in particular suffers from this with CSS Grids and Flexbox.

With all that in mind, on to the results:

Internet Explorer 8 vintage browsers

Browser Percentage Difference from IE
IE8 N/A X
Chrome 2 N/A X
Opera 10.1 28% X
Safari 4 35% X
Firefox 3.5* 35% X

IE8 does not run on CSS3Test, so I couldn’t get a score here. Chrome 2 is no longer available on BrowserStack so I could not include that either. I used Firefox 3.6 instead of 3.5 as that is no longer available on BrowserStack either. So, all in all, you can’t tell much from this round of tests.

Internet Explorer 9 vintage browsers

Browser Percentage Growth Difference from IE Difference change
IE9 30% X X X
Chrome 10 X X X X
Firefox 5 43% 8% +13% X
Opera 11.1 44% 16% +14% X
Safari 5.1 47% 12% +17% X

As with Chrome 2, Chrome 10 is not available on BrowserStack. Firefox, Safari, and Opera are all within 4% of each other, with Opera showing the largest growth. IE9 was well off the pace.

Internet Explorer 10 vintage browsers

With the HTML5Test, this is where things got interesting. Will it perform as admirably on the CSS3Test?

Browser Percentage Growth Difference from IE Difference change
IE10 51% 21% X X
Firefox 16 51% 8% 0 -13%
Safari 6 51% 4% 0 -17%
Opera 12.1 53% 9% +2% -12%
Chrome 23 57% X +6% X

In this round IE10 matched the scores of Safari and Firefox, and is only 2 percent behind Opera. If CSS Grids and Flexbox didn’t change syntax, Safari didn’t claim to support background-repeat which it doesn’t, and specs like Exclusions, @viewport, Scrolling Snap Points, or the hyphen properties from CSS Text Level 4 were included, IE10 would have pulled ahead of those browsers, and perhaps Opera.

This was the first time Chrome has been included, and it has a healthy, but not insurmountable 6 percentage point lead.

Internet Explorer 11 vintage browsers

Browser Percentage Growth Difference from IE Difference change
IE11 58% 7% X X
Firefox 25 58% 7% 0 0
Chrome 30 60% 3% +2% -4%
Safari 7 61% 10% +3% +3%
Opera 17 61% 8% +3% +1%

The situation is even more tightly packed in this round, with Safari and Opera joint leaders, but only 3% ahead of IE and Firefox. Chrome is 1% behind the leaders due to an accident of timing; the latest betas are up to 61% too.

This particular release wasn’t particularly interesting in terms of CSS for IE11, but switching to the latest Flexbox syntax gained it a bunch of points that would have otherwise been given to IE10.

The next release should be interesting now that Google and Apple have split and no longer benefit from each others work (unless the work is ported.)

Although the test (like the others) doesn’t show a complete picture, it is clear from this test that IE11 is a modern browser in terms of CSS support.

The CSS properties supported by all browsers except IE11 include outline-offset, resize, tab-size (only partially supported by other browsers), and text-align (also partial support by others). The :default, in-range, :out-of-range, :read-only, and :read-write pseudo classes, and the vmax value are also supported by all browsers except IE11.

The main missing feature in my opinion is the preserve-3d value of the transform-style property. The others, while nice, are not critical.

Can I Use…

While the other tests focus on one area, such as HTML5 or CSS3, the Can I Use… site includes a hodge podge of different features and technologies. As its focus is on telling the user what features are supported, it mainly includes relatively newer features, or older features that were not in IE.

Drawbacks of other sites also hold, such as not having complete coverage of each technology. Unlike the other tests, it is not automated, so the author checks if each feature is actually supported. For some things this can be subjective, such as IE having a partial rating for the number input type due to not having number spinner UI, even though there is explicitly no requirement for this in the spec (specs do no mandate UI choices), or how Firefox, Safari, and IE are listed as supporting hyphenation due to supporting the hyphens property, even though there are a number of other hyphen properties which they don’t all support.

Most of the new IE11 features that are not well supported in other browsers are not included on Can I Use…, including Screen Orientation API (IE and Firefox), Web Crypto, SDP, EME, MSE, Scrolling Snap Points, etc.

With that being said, let’s look at the results. I’ve broken down the scores to features that are Recommendations, Proposed and Candidate Recommendations, and Working Drafts, and the total of those combined. I’ve excluded features that are unofficial (not in a specification) or “other”, which includes a bunch of things that are not required by specs, such as a number of image and video formats. Unfortunatly the latter also excludes WebGL and Typed Arrays, but these are supported in IE11.

Internet Explorer 8 vintage browsers

BrowserRecPR & CRWDTotalDifference from IE
IE840%11%11%17%X
Chrome 2XXXXX
Opera 10.176%14%23%31%+14%
Firefox 3.574%28%24%35%+18%
Safari 472%30%35%41%+24%

Chrome 2 is not listed on Can I Use… so isn’t included here. In this test IE8 is a long way behind the other browsers; under half the score of Firefox and Safari.

Internet Explorer 9 vintage browsers

BrowserRecPR & CRWDTotalDifference from IE Gain
IE972%43%23%39%XX
Opera 11.186%50%42%53%+14%0
Firefox 586%64%48%60%+21%+3%
Safari 5.182%70%48%62%+23%-1%
Chrome 1082%72%55%65%+26%X

Internet Explorer 10 vintage browsers

BrowserRecPR & CRWDTotalDifference from IE Gain
IE1084%76%57%68%XX
Opera 12.190%71%57%68%0-14%
Safari 686%76%64%72%+4%-19%
Firefox 1694%74%64%73%+5%-16%
Chrome 2392%83%83%85% +17%-9%

Here was can see–similar to other tests–that IE10 made big gains. It caught up to Opera and is within 5% of Safari and Firefox.

Internet Explorer 11 vintage browsers

BrowserRecPR & CRWDTotalDifference from IE Gain
IE1184%83%63%73%XX
Safari 790%79%74%79%+6%+2%
Firefox 2592%84%79%83%+10%+5%
Opera 1792%87%83%86%+13%+13%
Chrome 3092%87%87%88%+15%-2%

We see mixed results from IE in this round. IE11 edges slightly closer to Chrome, but falls behind Opera (benefiting from the switch to Blink), Safari and Firefox. As mentioned previously, much of what was added to IE11 is not included in Can I Use… so the progress made over the last version doesn’t look as impressive as it could.

Note: The scores on Can I Use… changed after I published this post. The data above now includes the updated figures. Previously IE11 also gained on Safari, but the updated figures generally benefited recent WebKit/Blink browsers (+1% for Opera and +2% for Safari), and reduced IE 11’s score by 1%.

So what does IE11 lack that puts it behind the other browsers? For Recommendation specs it is SVG Fonts (also not in Firefox) and SMIL (rated partial for Safari) that put it behind the other browsers. In my opinion both are not critical. SMIL has largely been ignored in favour of JS animation and is being replaced by CSS Animations, and SVG fonts have largely only been used for iOS due to lack of support for TrueType fonts in earlier versions.

The only features tracked by Can I Use… that are fully supported by all other browsers than IE are the CSS resize property, Server-Sent events and CSS Intrinsic & Extrinsic Sizing. The Web Audio API, which is listed as partially supported for all other browsers is also not supported. These would be nice to have (especially Web Audio API) but none of them are a WebGL sized hole in IE’s support story.

Kangax’s ECMAScript compatibility tables

To measure ECMAScript support, there is no ES6Test or the like. Instead I looked at Kangax’s ES5 and ES6 compatibility tables. As these are not a tests, there is no scoring. Instead I counted up all the supported features and awarded 1 point for each.

As with other tests, the same caveats about scoring and support apply. There may be features that are not included in the test (especially as ES6 is a moving target), some tests only check for existence rather than actual support, and the scoring I applied makes no attempt to weight based on importance, complexity or so on. It would be easier to rack up points by supporting a bunch of the new Math methods than add something more complex.

Also note that these tables do not include the ECMAScript Internationlization API. This is currently supported by IE11, Opera 15+, and Chrome 24+. It is not available in Safari, and although it has been implemented in Firefox, it hasn’t been enabled in a release build at the time of writing.

With that said, let’s check out the results.

Internet Explorer 8 vintage browsers

Browser ES5 Score ES6 Score Total Difference from IE
IE8 4 0 4 X
Chrome 2 X X X X
Opera 10.1 10 2 12 +8
Safari 4 15 0 15 +11
Firefox 3.5 18 4 22 +18

As with previous results, I did not have a copy of Chrome 2 to test. Fairly predictably, IE8 was last and Firefox (known for its stella JS support, with Brendan Eich as their CTO) out in front.

Internet Explorer 9 vintage browsers

Browser ES5 Score ES6 Score Total Growth Difference from IE Difference change
IE9 34 0 34 30 X X
Opera 11.1 17 1 18 6 -16 -20
Chrome 10 32 1 33 X -1 X
Safari 5.1 33 0 33 18 -1 -12
Firefox 5 35 3 38 16 +4 -14

This one was surprising to me. IE9 actually had the second best support using this measure; only lacking Safe mode from ES5. Firefox again ends up on top, being the first browser to support all the features of ES5. It lost ground on IE, but only because there was no more ES5 to implement, and ES6 wasn’t ready to implement at this stage.

Internet Explorer 10 vintage browsers

Browser ES5 Score ES6 Score Total Growth Difference from IE Difference change
IE10 35 0 35 1 X X
Safari 6 35 1 36 3 +1 +2
Opera 12.1 35 1 36 18 +1 +17
Chrome 23 35 4 39 6 +4 +5
Firefox 16 35 14 49 11 +14 +10

In this round all browsers reached full ES5 support. Firefox started to pull away again with its early implementation of ES6 features. All other browsers had very limited support for ES6 features, or none at all in the case of IE.

Internet Explorer 11 vintage browsers

Browser ES5 Score ES6 Score Total Growth Difference from IE Difference change
IE11 35 6 41 6 X X
Chrome 30 35 5 40 1 -1 -5
Safari 7 35 2 37 1 -4 -5
Opera 17 35 5 40 4 -1 -2
Firefox 25 35 40 75 26 +34 +20

True to form, Firefox races ahead again, while IE11 regains second place.

There is however something important to note. While Firefox adds new JavaScript features without prefixes, not behind a flag like it does with CSS, Chrome (and Opera) does use a flag to enable new features for JavaScript. Enabling those flags changes things somewhat:

With Experimental JavaScript flags
Browser ES5 Score ES6 Score Total Difference from IE
Chrome 23 35 10 45 +10
Opera 17 35 17 52 +11
Chrome 30 35 17 52 +11

This would put IE11 second last again, only ahead of Safari (and thus WebKit). But it is important to note that out of the box you can not use these features, so this is more theoretical.

While Chrome uses flags to hide and reveal experimental features for JavaScript, Microsoft has instead been building experimental plug-ins on HTML5Labs.com to test prototypes and unstable specs. If we include flags, it is also fair to include these too.

For ES6, Microsoft provides a plug-in for the new Math, String, and Number methods. If we include these, things look different:

With Microsoft JavaScript Extensions plug-in
Browser ES5 Score ES6 Score Total
IE11 35 27 62

There are 21 new methods in all, and that is enough to push IE11 10 points above Opera and Chrome with flags enabled. Of course, you also can’t use this in the real world either, and is harder to enable than a flag. I’m actually surprised Microsoft didn’t implement them natively in IE11 now they are starting to support ES6 and they can’t be particularly hard to implement, especially when they have a prototype.

In conclusion, in the real world where plug-ins and flags can not be used, IE is certainly holding its own in second place. The worst case for IE would still put it ahead of Safari/WebKit, and would be further ahead if the Internationalization API was included in the tests. In JavaScript terms, IE11 has to be considered a modern browser. The only feature supported by all browsers except IE11 is Math.imul.

Official ECMAScript test suites

While I haven’t used official test suites so far, JavaScript is particularly suited to automated testing. ECMA makes available test 262 to test ECMAScript 5.1 compliance, and http://test262.ecmascript.org/testcases_intl402.html# to test ECMAScript Internationalization API compliance. For the sake of brevity, and as only the latest browsers support the Internationalization API, I’ll only list scores for IE11 era browsers here. The scores listed are the number of passed tests. Both tests were run using the 2013-06-13 version of the test suites. This was the latest at the time of writing.

Browser test262 Score test402 Score Total Difference from IE
IE11 11577 143 11720 X
Firefox 25 11511 13 11524 -196
Safari 7 11576 12 11588 -132
Chrome 30 11575 133 11708 -12
Opera 17 11575 133 11708 -12

It is no surprise considering the previous round of tests that IE11 did strongly here, especially considering we’re now including the ECMAScript Internationalization API. What may be surprising is that it finished in first place over Chrome and Opera, and that Firefox finished last this time, with the most fails in the ES5.1 tests. This picture will change somewhat once Firefox enables its ES Internationalization API support, and ES6 features are included in the test, but for now IE is the champ.

Totals and conclusion

If we put all the results together, Chrome 30 finished on top twice, and all other browsers finished 1st once each. Opera finished 2nd three times, while IE11 and Chrome 30 finished there once. IE11 finished last twice, with Safari 7 and Firefox 25 both finishing last once. There is clearly not a huge amount in it:

Browser 1st 2nd 3rd 4th 5th
Chrome 30 2 1 2 0 0
Opera 17 1 3 1 0 0
IE 11 1 1 0 1 2
Firefox 25 1 0 2 1 1
Safari 7 1 0 0 3 1

The two places where IE11 finished the highest were for the ECMAScript tests, which may be unfair, but there is also a decent amount of cross over between canIUse and the HTML5Test and to a lesser extent the CSS3Test.

While IE11 is last the most amount of times, it is only 3 percentage points behind Safari 7 on the canIUse tests and 21 points behind it on HTML5Test. With the growth in those scores over the last couple of versions, if IE continues its growth, it is not outside the realms of possibility that it will catch up in the next version; at least to Safari, and maybe to others.

It is also important to bear in mind that IE11 added WebGL. This was a huge undertaking to implement this in a year, and presumably took a lot of resources, while only accounting for 20 points on the HTML5Test, and one feature on canIUse (it is also reported as partially supported in Safari, despite being disabled, so not usable by web developers.) Now that elephant in the room has been squashed (or close to it; it isn’t 100% feature complete), we could see more progress in other areas. I’m personally hoping for more CSS support in IE12. When IE decides to implement something it is often able to move quickly; if WebGL was a case in point, we can also look to SVG (not included in any test here in any detail), which only took one release to go from 0% support to large chunks of the spec.

We’ve seen that IE’s release schedule is keeping pace with Safari, and that it’s take up is becoming more rapid. While there is still a big question mark over prefixes, newly invented IE features such as pointer events, scrolling snap points, IME support, and so on are getting proposed for the standards track.

It will be interesting to see how IE fairs when there is a more complete picture of standards support (coming in later blog posts), and how things like performance and accessibility hold up, but with this preliminary data, I think you’d be hard pressed to claim recent versions of IE are not a modern browser, or in touch with its competition.

The (probably not) definitive list of CSS features in non-CSS specs

$
0
0

While most CSS features are defined by the CSS Working Group and either included in CSS Level 2.1, or individual CSS Modules, there are a surprising number squirrelled away in various other specifications. These may or may not have been worked on in conjunction with the CSS WG, but as many probably get overlooked, I thought I’d list them in a blog post so that I can find them later. How many did you know about?

Pointer Events

Spec
http://www.w3.org/TR/pointerevents/
Status
Candidate Recommendation
Properties
PropertySupport
Firefox Safari Opera Chrome IE
touch-actionNoNoNoNoYes

The touch-action property determines whether or not touches that begin on the element will trigger the default action, such as panning and zooming.

Resource Priorities

Spec
http://www.w3.org/TR/resource-priorities/
Status
First Public Working Draft
Properties
PropertySupport
Firefox Safari Opera Chrome IE
resource-priorityNoNoNoNoNo

The resource-priority property specifies the download priority of the resource associated with the element (such as the image source or background image.) This includes lazy loading, postponing, or regular loading of the resource.

Input Method Editor API

Spec
https://dvcs.w3.org/hg/ime-api/raw-file/tip/proposals/IMEProposal.html
Status
Unofficial Draft
Property
PropertySupport
Firefox Safari Opera Chrome IE
imeNoNoNoNoNo
ime-alignNoNoNoNo-ms-
ime-mode *YesNoNoNoYes
ime-widthNoNoNoNoNo
ime-offsetNoNoNoNoNo

An Input Method Editor is commonly used for East Asian (CJK) languages to assist typing the specified language with a latin keyboard. It can also be used for other languages, such as to assist typing diacritics. When typing, an IME window pops up allowing the user to select from suggested matches.

The various imeproperties specify the size, positioning, and behaviour of the IME window.

Note: The ime-mode property exists in CSS Basic UI Level 3, but included for completeness as it is part of the ime shorthand.

Fullscreen API

Spec
http://www.w3.org/TR/fullscreen/
Status
Working Draft
Pseudo classes and elements
PropertySupport
Firefox Safari Opera Chrome IE
:fullscreen pseudo-classAltAltAltAlt-ms-
::backdrop pseudo-elementNoNoNoNo-ms-

The :fullscreen pseudo class and ::backdrop pseudo element allows you to style an element and its backdrop (the layer behind the fullscreen element, but on top of the rest of the elements behind it) when in fullscreen mode.

Note: WebKit, Blink, and Gecko browsers support :full-screen rather than the standardised :fullscreen. They each require their vendor prefixes: -webkit- (Chrome, Opera, and Safari), and -moz (Firefox).

Shadow DOM

Spec
http://w3c.github.io/webcomponents/spec/shadow/
Status
Editor’s Draft
Pseudo elements
Pseudo elementSupport
Firefox Safari Opera Chrome IE
::contentNoNoNoNoNo

When using the ::content pseudo element, the relative selector that follows is scope contained, so that you can only style the elements inserted via the shadow DOM, rather than the entire document.

Note: the Shadow DOM spec previously included the @host at-rule and ::distributed() pseudo element, but these are no longer in the latest editor’s draft.

There are also the Hats, ^, and Cats, ^^, selector combinators, but they are not yet included in the Shadow DOM Editor’s Draft, or any other version of the spec that I could find.

View Modes

Spec
http://www.w3.org/TR/view-mode/
Status
Recommendation
Media features
Media featureSupport
Firefox Safari Opera Chrome IE
view-modeNoNoDroppedNoNo

The view-mode media feature can be used with Media Queries to specify how a web site or app is styled when in different visual presentations. For example when it is windowed (think typical desktop apps such as on Windows or Mac with UI chrome, when not fully maximised), floating (the same as above, but without the chrome, such as Widgets or Gadgets), fullscreen (takes up the full screen without any chrome, such as Windows Metro apps or fullscreen video), maximised(full screen but with browser chrome, such as a maximised Windows desktop app), or minimised(when it is minimised but there is still some UI showing, such as a Windows Metro live tile, or “living icon”.)

Note: Opera version based on Presto supported the view-modemedia feature. Support was lost when it switched to the Blink rendering engine in version 15.

SVG

For SVG properties, I’ve removed any that have been moved into a spec produced by the SVG and CSS Working Group (FX task force) to define how they work in both SVG and HTML/XML, such as Masks, Filters and so on. For subsequent SVG versions I’ve only included the new properties unique to that version.

Most of these properties only work in SVG, but a number have since been made to work in HTML/XML in certain browsers.

For support information for SVG properties, I’ve only tested support by checking official documentation, and for the presence of the property in that browser’s developer tool. There are too many to check thoroughly at this time.

SVG 1.1

Spec
http://www.w3.org/TR/SVG11/
Status
Recommendation
Properties
PropertySupport
Firefox Safari Opera Chrome IE
color-interpolationYesYesYesYesNo
color-profileNoNoNoNoNo
color-renderingNoYesYesYesNo
enable-backgroundNoNoDroppedNoYes
fillYesYesYesYesYes
fill-opacityYesYesYesYesYes
fill-ruleYesYesYesYesYes
glyph-orientation-horizontalNoYesYesYesYes
glyph-orientation-verticalNoYesYesYesYes
image-rendering *YesYesYesYesNo
kerningNoYesYesYesYes
markerYesYesYesYesYes
marker-startYesYesYesYesYes
marker-midYesYesYesYesYes
marker-endYesYesYesYesYes
pointer-eventsYesYesYesYesYes
shape-renderingYesYesYesYesNo
stop-colorYesYesYesYesYes
stop-opacityYesYesYesYesYes
strokeYesYesYesYesYes
stroke-dasharrayYesYesYesYesYes
stroke-dashoffsetYesYesYesYesYes
stroke-linecapYesYesYesYesYes
stroke-linejoinYesYesYesYesYes
stroke-miterlimitYesYesYesYesYes
stroke-opacityYesYesYesYesYes
stroke-widthYesYesYesYesYes
text-anchorYesYesYesYesYes
text-rendering *YesYesYesYesNo
writing-mode *NoYesYesYesYes

Notes:

  • Opera lost support for enable-background when it switched to the Blink rendering engine
  • image-rendering exists in CSS Images Level 4, but it accepts different values, except the auto value.
  • writing-mode exists in CSS Writing Modes Level 3, but it accepts different values
  • text-rendering (in some browsers) and a subset of pointer-events can be used in HTML/XML, but there is no CSS specification for these features outside of SVG.
  • CSS Fonts Level 3 includes the font-kerning property, which is similar but has different values (except auto) to the kerning property.
  • enable-background wasn’t included in CSS Filters level 1. A similar but different property called isolation is included in CSS Compositing and Blend Modes Level 1.
  • color-profile was included in an earlier draft of CSS Color level 3
  • glyph-orientation-horizontal and glyph-orientation-vertical were in an earlier draft of CSS Text level 3.

SVG 1.2 Tiny

Spec
http://www.w3.org/TR/SVGTiny12/
Status
Recommendation
Properties
PropertySupport
Firefox Safari Opera Chrome IE
audio-levelNoNoNoNoNo
buffered-renderingNoYesYesYesNo
display-alignNoNoDroppedNoNo
line-incrementNoNoDroppedNoNo
solid-colorNoNoDroppedNoNo
solid-opacityNoNoDroppedNoNo
vector-effectYesYesYesYesNo
viewport-fillNoNoDroppedNoNo
viewport-fill-opacityNoNoDroppedNoNo

Note: the display-align, line-increment, solid-color, solid-opacity, viewport-fill, and viewport-fill-opacity properties are supported in Presto versions of Opera. They were dropped when switching to the Blink rendering engine.

SVG 2

Spec
http://www.w3.org/TR/SVG2/
Status
Working Draft
Properties
PropertySupport
Firefox Safari Opera Chrome IE
marker-knockout-leftNoNoNoNoNo
marker-knockout-rightNoNoNoNoNo
marker-patternNoNoNoNoNo
marker-segmentNoNoNoNoNo
paint-orderFlagNoNoNoNo

Note: the paint-order property is behind the “svg.paint-order” flag in Firefox. It needs to be enabled for the feature to work.

Functions
FunctionSupport
Firefox Safari Opera Chrome IE
icc-color()NoNoNoNoNo
device-gray()NoNoNoNoNo
device-rgb()NoNoNoNoNo
device-cmyk()NoNoNoNoNo
device-nchannel()NoNoNoNoNo
icc-named-color()NoNoNoNoNo
cielab()NoNoNoNoNo
cielch()NoNoNoNoNo

SVG Parameters

Spec
http://www.w3.org/TR/SVGParam/
Status
Working Draft
Properties
PropertySupport
Firefox Safari Opera Chrome IE
parametersNoNoNoNoNo

SVG Compositing

Spec
http://www.w3.org/TR/SVGCompositing
Status
Working Draft
Properties
PropertySupport
Firefox Safari Opera Chrome IE
clip-to-selfNoNoNoNoNo
comp-opNoNoNoNoNo
knock-outNoNoNoNoNo

MathML for CSS Profile

Spec
http://www.w3.org/TR/mathml-for-css/
Status
Recommendation
Properties
PropertySupport
Firefox Safari Opera Chrome IE
table-baselineNoNoDroppedNoNo

Notes: The table-baseline property is not actually defined in the MathML for CSS profile spec, but it is referenced in the default CSS style sheet, and is not mentioned in any other W3C specification. Opera previously supported this property until it was dropped when it switched to the Blink rendering engine.

Is your Fullscreen API code up to date? Find out how to make it work the same in modern browsers

$
0
0

With the introduction of IE11, all major browsers now support the Fullscreen API. However, due to prefixes and differences between the specification and early implementations, you may need to update any code you have that makes use of this feature. When I looked through the top search results on Google, none of the results showed both the latest syntax for all features and the ms prefix. In this post I’ll show you what has changed and what needs updating.

This article won’t cover how to use the Fullscreen API, as there are plenty of articles out there already. Just do a quick Google search if you need to get up to speed, but make sure to come back here, as most are out of date.

Syntax changes between early implementations and the specification

The changes in syntax are relatively minor, but it is important to get right if you want the fullscreen API to work in the widest range of browsers.

JavaScript API

If you’re using the fullscreenchange event no change is required except for adding all the prefixes (see below.)

For most of the attributes and methods the only change is that the “s” in “fullscreen” is now lowercase. It is uppercase in Firefox and WebKit/Blink browsers (later versions of WebKit/Blink support both.) A more substantial change is that the cancelFullScreen() method for exiting fullscreen mode was specified as exitFullscreen() in the specification.

Here is a handy table of the changes. All browsers currently require prefixes with both versions, so remember that the initial character should be capitalised: msExitFullscreen() instead of exitFullscreen(); mozCancelFullScreen instead of cancelFullScreen(), and so on.

Pre-spec Spec Change
fullScreenEnabledfullscreenEnabled Ss
fullScreenElementfullscreenElement Ss
requestFullScreen()requestFullscreen() Ss
cancelFullScreen()exitFullscreen() cancelexit, Ss
fullscreenchangefullscreenchange None

The new syntax should currently be used unprefixed (for Opera 12.1 and the future), and prefixed for WebKit/Blink and IE.

CSS

While the JavaScript API just received a little renaming, the CSS capabilities also were expanded somewhat.

Browsers except for IE support the :full-screen pseudo class for giving styles to an element when it is in fullscreen mode. This was changed in the spec to :fullscreen. IE11 is currently the only browser that supports the syntax in the spec. Opera 12.1 does too (without prefix), but this was dropped when switching to Blink.

Along with this change, a new pseudo element called ::backdrop was added to the spec, and is supported in IE11. This adds a pseudo element behind the fullscreen element, but above all other content on the page. This can then be styled, such as adding a fancy background effect. WebKit and Blink add a black backdrop but it can not be styled, while Firefox and Opera 12.1 don’t include a backdrop at all – if the element doesn’t cover the entire screen you can see the content below.

Here is a handy table. Again, remember the prefixes.

Pre-spec Spec Change
:full-screen:fullscreen -
N/A ::backdrop New

Include all the relevant prefixes

Now this is where things get ugly. The only browser not to require prefixes is Opera 12.1. For all other browsers you should use the regular vendor prefix you know and love.

IE only supports the standard syntax, so you can leave out the ms prefix for the non-standard syntax. Firefox doesn’t support the standard syntax, but you can either include moz with this syntax for future proofing, or just rely on the old syntax (it functionally behaves the same) until the prefix is dropped.

All modern WebKit and Blink desktop browsers support both the standard and non-standard syntax for JavaScript, and only the non-standard CSS :full-screen. As mobile browsers don’t support the spec and Chrome and Opera update rapidly I only use the modern spec. The only case you’ll need to use the non-standard syntax with the webkit prefix is if you need to support Safari 5.1. Although this is 3 versions old (4 if you include 6.1) it is currently the most popular version of Safari in StatCounter, Clicky, and Akamai stats.

The following code tests to see if the Fullscreen API is enabled using all the relevant prefixes, except Webkit’s version of the old syntax:

if (document.fullscreenEnabled || 
  document.webkitFullscreenEnabled || 
  document.msFullscreenEnabled ||
  document.mozFullScreenEnabled) {
  // add Fullscreen API code here. Remember all the prefixes
} else {
  // in reality you should use fallback code here
  alert("Your browser doesn’t support the fullscreen API");
}

Note that the standard syntax is used unprefixed as well as prefixed for WebKit/Blink and IE. The old syntax is uses for Firefox.

Browser differences with CSS styling

Although the JavaScript API more or less works the same in all browsers, CSS styling works quite differently.

In IE11, Firefox and Opera 12.1 the element is set to 100% width and height. If you’re making something such as an image fullscreen it will be stretched, ignoring the aspect ratio.

In WebKit/Blink browsers (including Opera 15+) the element is centred on the screen with a black backdrop. The backdrop can’t be styled.

In IE11 if you set the width and height while in fullscreen the element is positioned at the top left of the screen (at its original size if you set both to auto) with a dark backdrop filling the screen. In Firefox the width and height are ignored. In Opera 12.1 (if you give it a high enough specificity) it will behave like IE11, but the backdrop is set to the size of the border-box of the element, so the rest of the page will be transparent.

The backdrop in IE11 can be styled with ::backdrop but can’t be made (semi) transparent. If you use a background color with an alpha channel it will layer that colour on top of the original backdrop colour.

Making all browsers stretch content to fill the screen

To make all browsers copy the Firefox style you need to add width of 100% to :-webkit-full-screen, and make it fixed position at the top of the screen. You may also want to add it to the prefixless version as we don’t know how browsers will implement this when prefixes are removed.

As WebKit/Blink keeps the original background colour for the element, if the image has transparent portions you may also want to set the background to none. I didn’t do this for the prefixless version in the demo below as this removes the backdrop entirely in Opera 12.1. Note that while Opera now uses Blink, Opera 12.1 (based on Presto) is by far and away the most popular Opera version on any stats sites (as it doesn’t update to Opera 15+), so it is still worth taking care of any differences.

Another enhancement you probably want to do is add object-fit so that any image or video isn’t stretched. Opera 12.1 (the only browser to currently support this and the Fullscreen API) requires the -o- prefix. Although this is mentioned in the spec, Opera doesn’t apply it by default.

:-webkit-full-screen {
  width: 100%;
  position: fixed;
  top: 0;

  /* webkit keeps the original background color, so reset */
  background: none;
}
:fullscreen {
  /* not currently needed, but just in case */
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;

  /* keeps correct aspect ratio and full image visible */
  -o-object-fit: contain; /* Opera 12.1 */
  object-fit: contain;
}

Here is a full screen demo with stretched content. It should work the same in every modern browser that supports the Fullscreen API.

Centring the content

Achieving WebKit’s default behaviour is slightly more difficult. If you only want it to also work in IE it is easy. Just add margin: auto; to :-ms-fullscreen, and set the width and height to auto to stop the content from being stretched.

:-ms-fullscreen {
  width: auto;
  height: auto;
  margin: auto;
}

Here is a simple centred fullscreen demo using this technique. It should be consistent in IE11 and WebKit/Blink browsers. It will not work correctly in Firefox and Opera 12.1 for reasons mentioned previously.

Instead the easiest way to do it is make the parent element fullscreen instead of the actual element (figure rather than img in my demo .) Then you can style the parent as the backdrop and positing the content inside it using your favourite CSS centring method. In my case I used flexbox, but you could use table layout or whatever.

 :-moz-full-screen {
  display: flex;
  align-items: center;
  justify-content: center;
}

:-ms-fullscreen {
  display: flex;
  align-items: center;
  justify-content: center;
}

:fullscreen {
  /* set to flexbox to centre imagine inside */
  display: flex;
  align-items: center;
  justify-content: center;
}

Now the child element(s) will be centred. Note that there is no need to set the width and height of the img element now as it is the parent being stretched not the image itself.

Try it out in the cross browser version of the previous example. This should work the same in all recent browsers that support the Fullscreen API. You can also add the older syntax of Flexbox with -moz- prefix, and the webkit version of the old Fullscreen API if you want even further support.

A quick demo pulling it all together

While showing a single transparent image being set to fullscreen is all well and good, I’ve made a slightly more complex version that allows any image in a gallery to be set to fullscreen. For this I‘ve adapted the demo I made for my Scrolling Snap Points article.

Here is the Fullscreen API gallery demo in action. Try clicking an image to have it go into fullscreen mode at its natural size, and click it again to close it.

The code shows almost all of the features of the API, so you can see how all the prefixes and syntax changes should work:

if (document.fullscreenEnabled || 
  document.webkitFullscreenEnabled || 
  document.msFullscreenEnabled ||
  document.mozFullScreenEnabled) {

  var imgs = document.getElementsByTagName("figure");

  for (var i = 0; i < imgs.length; i++) {
        imgs[i].addEventListener("click", function (event) {
        if (!document.fullscreenElement &&
            !document.webkitFullscreenElement &&
            !document.msFullscreenElement &&
            !document.mozFullScreenElement) { 
              if (this.requestFullscreen) {
                  this.requestFullscreen();
              } else if (this.webkitRequestFullscreen) {
                this.webkitRequestFullscreen();
              } else if (this.msRequestFullscreen) {
                this.msRequestFullscreen();
              } else if (this.mozRequestFullScreen) {
                this.mozRequestFullScreen();
              }
          } else {  
            if (document.exitFullscreen) {
              document.exitFullscreen();
            } else if (document.webkitExitFullscreen) {
              document.webkitExitFullscreen();
            } else if (document.msExitFullscreen) {
              document.msExitFullscreen();
            } else if (document.mozCancelFullScreen) {
              document.mozCancelFullScreen();
            }
          }
        }, false);
      }
    } else {
      // in reality you should use fallback code here
      alert("Your browser doesn’t support the fullscreen API");
    }

The CSS is more complex and perhaps more real world. As I want Firefox to behave the same as WebKit/Blink, I’m setting the figure to fullscreen rather than the image. As both of these elements have been styled as part of the gallery I can use the :fullscreen pseudo class to reset the styling, including setting the images back to their original size.

#gallery :fullscreen {
  /* unset styles. all: unset; would be nice here */
  background: black; /* Opera needs a bg colour  */
  border: none;
  box-shadow: none;
  margin: 0;

  /* set to flexbox to centre image inside */
  display: flex;
  align-items: center;
  justify-content: center;
}

I can also hide the figcaption:

:fullscreen figcaption {
  display: none;
}

Although WebKit/Blink sets the images as centred by default when in fullscreen, I still need to apply flexbox to them in this demo as the layout gets screwed up when exiting fullscreen without it for some reason. Sadly Safari still requires the webkit prefix so those need to be included too.

Lastly I used the ::backdrop pseudo class to style the backdrop in IE11 and any browser that supports the unprefixed version (none as yet.) This wasn’t really needed but shows what can be done:

#gallery :-ms-fullscreen::-ms-backdrop { 
  background: radial-gradient(at center, grey, black);        
}
#gallery :fullscreen::backdrop { 
  background: radial-gradient(at center, grey, black);        
}

Support information

I’ve covered browser support in the prose of this article, but it is always handy to have that info in a table. For this you can check out my Fullscreen API and Fullscreen CSS support tables.

At the time of writing the spec is fully supported by IE11, partially supported by Chrome, Opera, and Safari 6+, and partial supported with a different syntax by Firefox.

Wrap up

Pulling it all together, here is a checklist you can go through to update your Fullscreen API support.

  • Make sure you include the non-prefixed syntax:
    • lowercase the “s” in fullscreen/Fullscreen.
    • change cancel to exit.
    • remove hyphen from :fullscreen pseudo class.
  • Considering updating webkit prefixed code to the specification syntax. You will still need to use the old syntax for the :full-screen pseudo class.
  • Add ms/-ms- prefixes for the standard syntax JavaScript and CSS
  • Consider styling differences between browsers and update the CSS as appropriate.

Once you’ve done this you should be good to go, unless the syntax changes.

Stale. An issue tracker for web docs past their sell by date

$
0
0

One of the great things about our industry is how passionate people are about helping each other learn. Be it articles about the latest and greatest techniques that they’ve discovered, or blog posts about new web platform features that have landed in modern browsers. All this content–often created by people in their spare time–has one downside: it is often unmaintained, and with the frequency that certain features or APIs can change syntax or new prefixed implementations arrive, the content can become outdated. If the content appears high up in search results, or is linked from influential sources, it can lead to developers copying code that may not work in as many browsers as it could. It can also harm the adoption of the latest version of the spec.

With that in mind, I created the Stale repository on GitHub. I intend to make this a place to crowd source the discovery and eventual fixing of out of date content about web platform features on the web. If you come across an article or post that is out of date, then open up an issue linking to the post and what information is out of date. If the author has a GitHub account, @mentioning them in the report will automatically ping them, to alert them to the issue. This has been effective so far.

So what issues qualify? There is no hard and fast rule, but the easier a post is to stumble across when searching for how to use a feature the better. I’d like the first few pages of search results about a given feature to lead to up to date and correct content. Articles, reference materials, and polyfills are usually more important to keep up to date than blog posts that are often tagged with a date and are more often understood to go stale over time.

As for what features to report, I image this as a place to report content about web platform features built into the browser rather than features of libraries such as jQuery and so on, but I’m open to feedback there. Examples of reports so far include outdated content about CSS Flexbox, Gradients, Fullscreen API, and Screeen Orientation API.

I see four main areas where content goes out of date. The two most critical are if the syntax changes (e.g. Gradients and Flexbox), or if new implementations come with a prefix that isn’t covered in the article. Perhaps a lower priority is if the compatibility information is out of date. I personally wouldn’t bother reporting this if it is a blog post and there is no other outdated information such as missing prefix. I’ve also included a tag for bugs such as a bug in the code samples, or a bug in an implementation that either needs worked around (and is important enough to mention) or is no longer needed. I’ve not really used this latter tag as of yet though.

How to report an issue

Reporting an issue is simple. Just open a ticket in the issue tracker and include the following information:

URL
The address of the content in question
Issues
A list of the issues in the post, along with any fixes needed
Contact
Contact information of the author or site. @mention their GitHub user name if they have one.
Tags
I’ve included tags for the technology, the feature, and the type of issue, so that similar issues can be grouped.

I decided to have individual tickets per article rather than one per feature, so that they can be closed something is fixed. There are often common issues that need to be described, so I’m thinking of using the Wiki to catalogue these, along with the required fixes, so that they don‘t needed to be typed out each time.

Why report issues?

Because keeping information up to date is often as important as writing it in the first place, and the original authors are often not aware that their content is no longer up to date. Much of it was written in people‘s spare time, and it is a full time job in of itself to keep up with all the changes that are going on with the Web Platform.

You might wonder why you should report it here rather than in the project’s own GitHub repo. By all means do both and link to one from the other. Not every project or site is on GitHub, so while many sites have a place to directly report issues, not all do. It is nice to have an overview in one place of all the issues with a particular feature.

How to fix an issue?

Usually an issue can be fixed in one of two ways. Either the content gets updated to reflect the current situation, or a deprecation notice is added, linking to a place to find out more current information. Flexbox has its own boilerplate notice made by Paul Irish. I was also thinking of making standard notices for all common features on the Wiki.

If the content lives in a GitHub repo (or similar) or a Wiki, it is often easier to fix the issue yourself, rather than waiting for the author to find time. Consider making a pull request or directly editing the wiki in question.

Once an issue is fixed and went live, note it in the report and close the issue.

Successes so far

Although this initiative is yet young, we’ve already had a number of fixes. Out of 44 issues, we’ve had 9 fixes including:

  • Moz Hacks
  • MDN x 4
  • HTML5Rocks x 2
  • TutsPlus
  • the-haystack.com

Additionally three other sites were fixed before I started cataloguing them on GitHub. Of the 34 currently open issues, at least one has been fixed but is yet to go live (HTML5Please), and three are in progress (HTML5Demos, Sitepoint, and CSSTricks.). While it is clearly early days, it looks like the approach is working.

Any help you can all give, the better and more accurate the web (docs) will become.


Introducing status.modern.ie

$
0
0

Some exciting news just came out of Build, Microsoft’s developer conference, in San Francisco today. Have you ever wondered what the IE team are developing for the next version of IE, or what their position is on your pet feature? While Chrome has the Chrome Dashboard, IE has traditionally been a black hole. Just check out any feature on the aforementioned dashboard and look what it says for IE’s positon. Most will say “No public signals”. The same can be said for sites like Are We Componentized Yet?

No longer. I’d love to introduce you to status.modern.ie. Our dreams answered. I could never have imagined the IE team putting out a dashboard such as this even just a few months ago. In my experience, the IE team is becoming increasingly open, and this is one manifestation of this. Long may it continue.

The site is clearly inspired by the Chrome Dashboard, and shares many of the same web platform features listed on that site. You can expand each feature to see the current browser support and check the specification. Perhaps the most interesting filter is the status, which allows you to display the features in development or what they are considering developing for example. As you’ll be able to see, the IE team are currently adding the much requested preserve-3d, along with GamePad API, WebGL Instance Extensions, DOM3 Xpath and cross-domain font loading. A couple of those should be great for game developers!

The site is currently in beta and will be improved over time, including the data that is displayed. Of note, Opera support information is missing, as the data was pulled from Chrome Status and its information is very out of date. The IE team is in touch with Opera as I speak, and hopefully it will be updated soon.

When I started consulting for the IE dev relations team, being more open about features in development one of the first things I requested (along with a more open bug tracker.) I’ve no idea if I influenced the decision to build this site in any way, but I‘m very happy it happened. The IE team is certainly listening to developers much more recently.

status.modern.ie development

As mentioned, the site is in beta and will be improved over time. The site itself was written by the company I work for – Plain Concepts. The frontend was written using Angular, along with technologies such as HTML5, SVG, CSS3 and WAI-ARIA. The backend was written in Node.js using Azure Websites. There is an API available at http://status.modern.ie/features with CORS enabled. The website will eventually be open source on GitHub once the site leaves beta and we’ve fixed up a bunch of stuff. I’m currently in the process of cleaning up the CSS and making it more responsive. We also have to do a bunch of testing around accessibility. There are a number of features coming, such as being able to directly link to features.

Welcome to the all new Internet Explorer Developer Channel

$
0
0

By the time you are reading this the all new IE Developer Channel will have been released into the wild. This is a new way for the Internet Explorer team to share with the developer community the progress being made in the browser. It is part of our commitment to increased openness, and joins the Status IE site as another method of getting developer feedback, and helping you plan for future IE versions.

Never before has the IE team been so open with their future plans. It is also a break from the tradition of previous developer previews in that it both has the full browser chrome and can be installed side by side with your main IE11 browser. This should make testing much easier, without losing the ability to test in the current version or force you to run a separate VM (it is in fact run as an App-V Client.) As with IE11 it runs on Windows 8.1 update and Windows 7 SP1.

For the first developer channel release, we are including some of the new features that were marked “in development” on the Status IE site. This includes WebGL Instancing Extensions, Gamepad API (unprefixed you’ll be pleased to know), and WebDriver. We have also included a big update to the F12 Developer Tools. A number of other features are in active development that will be included in a future IE Dev Channel release.

As an aside, many of the existing articles and demos for Gamepad API only use the moz or webkit prefixes, or an earlier version of the spec. If you find any outdated content please file an issue in the Stale GitHub repo. I’ve been attempting to reach out to authors to get these fixed.

We hope that you find the developer channel useful and that it will make IE less of a black box to develop for. If you have any feedback or find any bugs, please don’t hesitate to file them on Connect. Interoperability is a big focus of IE. If you have any questions or further comments we are always watching the IEDevChat Twitter feed, and are we’re happy to help.

When I joined the IE userAgents programme, Increased openness was something I wanted to push for, so I’m personally pleased of how things are now moving with the new dev channel and status site; two of the things I hoped could become a reality. This is something that felt a long way off even just a year ago. I feel like things are changing, and I hope we’ve shown that we are heading in the right direction with actions as well as words.

For both the Dev Channel and Status IE releases I had the pleasure of working on the development (and design for IEDC) of the web sites, along with my colleague Antón Molleda. If you find any issues, don’t hesitate to contact us. For StatusIE bugs can be filed in the GitHub repository. For the IEDC site we made liberal use of SVG and it should be fully responsive (which was quite a pain for embedded YouTube iframes.) We didn’t make use of 3rd party libraries or frameworks, except Google Analytics and YouTube so the page should be lightweight. We also tried to make sure the page itself is accessible with the use of WAI-ARIA.

Please take some time to play with the preview and let us know what you think! If you’re not on Windows, don’t forget that Modern IE provides VM images for Windows 7 and 8.1.

A new beginning, with IE

$
0
0

Today is Blue Beanie day. With that in mind, it is as good a time as any to let the cat out the bag. Very soon, I’ll be leaving my current company (Plain Concepts), and joining the Internet Explorer team at Microsoft as a full time employee. I think that might even be a first for a former-Opera Software employee.

Now, I’m not exactly new to IE. For the past couple of years, first as a userAgent, and then more recently as a Microsoft vendor, I’ve worked on some projects with the IE marketing team. From things like answering developer questions, to IE Platform Status, IE Developer Channel, and more. But now I’ll be dropping my vendor prefix–and in the grand tradition of CSS–my alias will be renamed. V-dastor will soon become dstorey at Microsoft.com. (yey, I managed to get my handle I use on Twitter, et al!)

One of the biggest changes is that I will be moving from marketing to Engineering. Not only that, but from Developer Relations (which I’ve done for much of my career, whether it be in engineering, marketing, or wherever else each company decides to place this function) to Program Management. Instead of assisting developers, and promoting and writing about the web standards, I will help build them. I’ll be on the layout team that deals with technology such as CSS, SVG, WebGL, and a whole lot of web compatibility and interoperability. I’m not sure yet exactly what I’ll be working on, except hard engineering challenges. It is an exciting change; one that I’m sure will be incredibly challenging. I’ve worked as the product manager on Opera Dragonfly developer tools, but not as a Program Manager, so I’m nervously excited about what is ahead. But I’m sure I’ll get a lot of support as I get up to speed.

So, now I’ll be a web platform engineer. It’ll be much less of my job description to hang out with you guys, but I’ll not be going away completely. As I’m sure you have noticed, the IE team has opened up a great deal from a couple of years ago. We’re involved more in the community, and our plans are more transparent. It is easier than ever to reach the people working on the product. I’m sure I’ll be sharing some of the things I’m working on when I can, and blogging when I have things to say. There are, of course, many interesting and knowledgeable people to follow. On the web developer ecosystems team (which has taken over a number of DevRel responsibilities), Charles Morris heads up the team, and you can also engage the likes of Antón Molleda, Jonathan Sampson, Jacob Rossi, and my fellow Brit Adrian Bateman. While I haven’t met a bunch of my new team yet, you may have seen Greg Whitworth answering your CSS questions, and Frank Olivier owns interop, and WebGL amongst others. I’d recommend you follow them all. I also want to send a big thanks to Rey Bango for helping me get set up with the IE team after I left Motorola, following the cancellation of a (secret) project. He is always full of great IE knowledge, and bad dancing (NSFW, maybe). And, of course, Chewy Chong and Millo who have been my bosses on the IE DevRel side while I was a vendor.

Many of you may wonder why Internet Explorer, especially after being at Opera. Well, today’s IE is not the IE of 2005. There are a lot of outdated preconceptions about IE, that will be a challenge to shift (but hey, if I didn’t like a challenge, I won’t have worked DevRel for Opera, going up against the big guns). But things are opening up, and the product is improving. IE in the Windows 10 technical preview now has the most implemented ECMAScript 6 features. It is the fastest in benchmarks such as Sunspider, once used as a stick to beat it with. The Chakra team are doing a fantastic job. IE now has WebGL, that many people thought would never be added. IE has led the way on modern touch with Pointer Events, that has broad developer support, such as from the jQuery and Dojo teams. Features such as ObjectRTC with Opus are in active development. I believe that we can go toe to toe with Chrome when it comes to implementing standards and moving the web forward, and I want to become part of making that a reality. A strong IE challenging Firefox and Chrome is good for the web.

If you want to go on this ride with me, follow me at @dstorey on Twitter, or if you have any web standards related questions you can mail me at my twitter handle @microsoft.com once that becomes active.

The Microsoft products I use day in day out, even at home

$
0
0

When I write here, I end up writing long winded articles that I fuss over and take a long time to write. Due to this I’ve not written for a year(!) or had a real meaty article in longer than that. I’ve had a bunch of excuses like…I hate the design; when I redesign I’ll post again, but I’ve decided to just get on with it, and write some sorter form posts until I get back into the swing of things. Or not as the case may be!

As a long LONG term Mac user that now works for Microsoft, I thought I’d write my first one on the MS apps I use day in day out. I’m only including things here I choose to use, and not things I have to use for my day job at Microsoft. Now, Microsoft have not asked me to write this, and I’m going to be as honest as possible. This is my personal opinion and not those of my employers.

As I said, I’m a long term Mac user. At university, I was the only Mac user I saw. Most people were using some form of IBM ThinkPad laptop. As such, old habits die hard, and I consider myself a cross platform user. I’ve both a work ThinkPad X1 Carbon and a person MacBook Air, while my phone is a work supplied low end Lumia. I don’t have a tablet; I’ve never really understood the appeal for my use cases.

Due to my cross platform usage, I’ve started in the last year to look beyond the Mac specific apps I tended to use, to high quality cross platform ones. In general this hasn’t been as difficult as I first though. Much of what I use, such as Twitter, were web first and have perfectly serviceable web apps anyway.

Anyone that knows me will probably tell you how stubborn I can be to change, so anything I recommend here is high praise from me. And in general, except for Microsoft Edge, I had nothing to do with any of them. I use them as they meet my needs.

OneNote

The first Mac specific app I transitioned off of was actually for notes. I’m one of those people that flip from idea to idea in a heartbeat, and have to note them down lest I forget them. For this I has the most unorganised system of about 100 unsaved TextEdit documents with various notes. Am I the only one that does this? Instead, I discover OneNote. I love this app. It is both cross platform and web based, and notes automatically get synced to “the cloud.” It is free too, which is a big bonus. I like how it allows free form edits. Click on any area of the page and it creates a new text box. The UI generally doesn’t get in the way, although I disabled the completely over the top purple colour in the settings. I feel like if I had a machine with pen input I’d get even more from the app. The only thing I can really complain about beyond the purple is that it isn’t always great at importing data such s tables and charts from Excel. In general, a notes app should let you jot down thoughts, get out of your way, and allow you to share them, and OneNote does just that. It is a really work horse app…it is used extensively inside Microsoft.

Visual Studio Code

Perhaps the hardest thing to transition from from any Web Developer is their text editor. This is the familiar home that you have to feel productive and comfortable. If you ask anyone that really knew me, you’d need to pry TextWrangler from my cold dead hands. Much of it was probably just inertia and resistance to change, but I was really stuck on TextWrangler for over 10 years. A lot of habits form in that time. I was used to the syntax highlighting; the find and replace was really second to none. It just felt like a comfy slipper. But as projects got more and more complex, the lack of projects got more and more annoying. And with my memory less than perfect, not having auto-complete became tiresome. I briefly tried BBEdit, but I wanted to go cross platform, and thus tried Brackets and then new kid on the block Atom. It was Brackets that I decided to go with while building Status.modern.ie until Visual Studio Code was announced at \Build. I couldn’t be more excited.

Working at Opera, and gathering feedback on building Opera Dragonfly (I was the PM at the time), the desktop and core developers I talked to at the time would wax lyrically about Visual Studio. It was probably more of an inspiration than crowd favourite Firebug. Visual Studio was too much for me as a web developer that was used to a light weight text editor though, and it is Windows only. Visual Studio Code ticked all the right boxes. It is built with web technologies for the web, it’s lightweight, works cross platform so I can use on my work Windows machine and my home Mac, and it has some of that Visual Studio “DNA”. I like it a lot, and it is only getting better now it is open source. Indeed my main bug bear was that while I loved the IntelliSense auto-complete (especially how it includes a description as well as browser support for CSS),it was fairly out of date. Flexbox for example only showed the old WebKit syntax. But now it is open, I’ve been able to help improve that, and it has gained other improvements such as auto-complete for ARIA too. I don’t know about you, but I always have to look up the appropriate attributes as I always forget them. It also has a bunch of other useful features such as Git integration (which saved my bacon when GitHub Desktop stopped allowing me to commit for some reason that I’ve not been able to fathom), and to me the default dark theme is really beautiful. With F12 (IE/Edge’s developer tools) also using the Monaco editor, I‘d love if the two projects share more in the future. I’d love my F12 to match my VS Code. I’d recommend anyone on Mac, Windows or Linux to try out VS Code, and I’d love to hear what you think.

Azure Websites

This is not something I can write a whole lot about as I develop exclusively on the front end, but all of our projects use Azure Websites, or Azure Web Apps as it is called today (MS really love renaming things!) The best thing I can say about it is that it completely gets out of the way. I don’t even have to know it exists. It has continuous integration, so that I just push my changes in the normal way to GitHub and they’re staged on our development server, and then they can be swapped out to the live site. As a MS project, if you still hold on to old ideas, you might think this requires ASP.net or some other MS invented technology, but as well as using GitHub instead of TFS, we also use Node.js. It just makes sense when we’re browser vendors that we use JS on the server side as well. I’d love to try Chakra Node when and if that becomes possible.

We also use DocumentDB as the database, which does use Chakra. I can’t speak much to this as I’ve not touched it, but my colleague and friend Anton will be able talk more about both of these.

Azure RemoteApp

This one is really cool as a Mac user. Unfortunately, Microsoft Edge doesn’t exist on a Mac, but I can use it anyway through Azure RemoteApp and Remote.ie. It doesn’t get the full performance or fidelity as a native browser as it is streamed, but it is a fantastic piece of technology. It doesn’t work out of the box with localhost, but you can use Ngrok to tunndel through. When using this, the only real issue beyond animation fidelity isif you’re using a slow network. If I need to test older versions of IE, I use BrowserStack.

Microsoft Edge

I can’t really write this without writing about the product I work on. We’re still in the early days of a hugely ambitious project, but it is one I’m hugely proud of being part of. Just like Opera, it is brimming with smart people that really care about the web, and it is really exciting to see where we’re heading. There will always be trolls that try to put you down due to the history of IE, but I think we’ll prove a lot of people wrong. The amount we’re opening up with the roadmap on status.microsoftedge.com, solicitation of feedback from web devs on Twitter and UserVoice, regular previews via the Windows Insider program, and even the recent announcement of open sourcing Chakra (our JS engine) is something we could only dream about a few years ago. The Web is a healthier place when multiple strong parties are competing. Currently Chakra is the engine to beat for JavaScript. We’ve also done a huge amount of work forking Trident to make EdgeHTML, including thousands of interop fixes, deprecating old IE only features, and adding a whole host of new standards. So much so that we’re only 10 points behind Firefox on the commonly cited HTML5test. We’re knocking on the door for sure. And one of the things I’m proud off that doesn’t get much limelight is all the accessibility work. That is something we’re really committed to getting right.

What’s next?

Honestly, I use Office as many of the internal documents are in that format, but I‘ve yet to fully try out Outlook. I use it on my phone as it is the default mail app, but I’m still stuck on mail.app due to inertia on my Mac. We get DRM email at work that doesn’t open there, which is a reason alone to switch (never mind having a cross platform mail app), but in general Mail has been annoying me for a while. Calendar invites will often not show the date and time, emails will randomly not delete, app crashes, etc. I’ve heard good things about the mail and calendar apps MS bought recently, and I’m looking to try Outlook on my Mac to see how it holds up. I just have to get over about 14 years of inertia and habbits of using mail.app. That is a lot of mail!

The other thing I want to experience more is the hardware. Truth be told, after using a Mac for so long, it has been hard switching to Windows hardware. I first got an Acer when consulting, and I hated that plasticy thing. When I joined MS I got a hand me down thick ThinkPad with a VGA port! Even my first ever Mac at the turn of century didn’t have one of those! I’ve since got a close to top of the line ThinkPad X1 Carbon. But through all of them, what I’ve most struggled to get used to is the trackpad and keyboard. Macs do really have great versions of each…and I’m sure 15-ish years of each doesn’t help there either. Cause, really, while I’ve got used to the main modifier key being in a different place, I still struggle with the fact that due to the Mac having a one button trackpad, and being left handed, I automatically click just on the right side of the keyboard. This always to this day makes me regularly rick click on Windows. Now, the Carbon is night and day better. On the other machines I always highlighted text and typed over it as I used the keyboard, due to either weak or none existent palm rejection. And it drove me batty. But I still can’t get away with the fact it still isn’t quite right for me. It is a business machine foremost. People love the keyboard, but I’ve still not quite got into it. It does have quality materials but not quite my style. It would look so much better without those logos . It is definitely a serious looking machine. It says person in a suit. And that is great for that audience.

But I really want to try a Surface. It is perhaps only the second Windows machine I’ve desired as a Mac user (the first was when I had a chunky 15" Powerbook and people around the office had tiny IBM Thinkpads they could throw around). But the Surface, I think, can really compete in the Mac demographic. It has really quality materials, and fit and finish. More so than I‘ve ever seen outside of Mac. But…and this is the key thing…it isn’t just a Mac clone. It isn‘t just this hunk of aluminium that sits in an uncanny valley where it looks like a Mac at first glance but isn’t. Surface, whether it is the Pro or the Book, is its own machine. The matte finish and material (Magnesium instead of aluminium) is different of course, but perhaps more importantly, they have their own profile. That is always a trait Apple have been good at. Draw a quick line art drawing and you’ll instantly recognise an Apple product. From the click wheel iPod, to the rounded rectangle iPhone with circular home button. Surface has this. From the lowercase Greek Lambda of the Surface Pro in profile, to the binder shape of the Surface book. Even the gap between the screen any keyboard in the latter is genius to me. Due to the hinge and how it detaches, there probably needed to be some gap. But put a small gap and it just looks like poor fit and finish. But a relatively big gap and not only does it become part of the design signature, but it avoids those issues, and provides clearance to stop the keys rubbing on the display.

All that is cool, but the reason for that hinge is the ability to remove the screen. I’ve not got into tablets, but I miss the touch screen functionality of my Windows machines when using my Mac, and I love the idea that the book detaches without compromising the keyboard. I could have got the Surface Pro 3 when I got my Carbon, but I felt the keyboard would be too much of a compromise for someone so used to the Mac keyboard and trackpad, and whose tablet use would be a distant second. The book seems to have that balance right for people like me (and I’ve heard that they are fantastic). It also has to be said that the keyboard for the Pro 4 also looks a lot better. And the pen. I really want to try the pen. Especially for Edge annotation mode.

The other thing I have to commend the design team on is no logo (or buttons) on the front of the device at all. In that regard it out Apple’s even the Macs. Whoever made that happen, thank you! Hopefully future Windows Phones will drop the MS logo off the front too.

So all in all, the Surface Book is a highly desirable piece of kit, that holds its own with the best of Apple. The only thing is it is hard to justify when my personal Mac is only 1 year old, and my work laptop is also new.

Wrapping up

Ok, so that was longer than I planned. You see why I don’t blog much now! But, I‘d love to hear what MS products you use yourself. Are you a Mac user that discovered the appeal of VS Code? Are you a cross platform user, that likes that a bunch of products are available on more than one platform? Are you a Windows user that loves MS Edge? What are your thoughts of the various Surface devices as a development machine?

Why I love Visual Studio Code for CSS / HTML development

$
0
0

Visual Studio Code is the new kid on the block in text editor circles. It’s raison d’etre is to provide a keyboard focused lightweight editor that has less of the complexity of a full blown IDE, while trying to provide enough of the powerful features that developers love. While it looks to strike that balance between power and flexibility, it provides a robust extension ecosystem for anything that doesn’t come in the box.

VS Code is mainly targeted around web, Node.js, and ASP.net developers. In fact, it is even written in HTML, CSS, SVG, TypeScript and Node.js. Things like IntelliSense (auto-complete suggestions), syntax highlighting, and even a debugger (for the latter two) are provided in the box. Additional languages can of course be provided by installing extensions from the marketplace. There is even version control built in, so you can connect to GitHub and commit, sync and change branches without leaving the editor.

There are however some fairly common misconceptions I’ve seen around VS Code:

Misconceptions

“VS Code is cool and all but I’m on a Mac.”

That isn’t a problem at all. While Visual Studio is Windows only, VS Code works just as well on Mac, Windows, and Linux. I‘ve even seen people run it on a Raspberry Pi!

”Don’t use VS Code; it’s just an open source fork of Atom!!! M$ are evil, they’ll even kick your dog. Twice.”

Not true. VS Code is based on the Monaco editor that is also part of the F12 dev tools found in MS Edge and IE. It was also part of Visual Studio Online that was part of Azure Websites. It does use Electron (which started life as part of Atom) for the frame of the app, which allows it to be hosted as a cross platform app.

Why VS Code is great for front end dev / designers

Quite a bit has been made about VS Code’s suitability for JavaScript and Node.js. It looks like it is picking up quite a following within the JS, Node.JS, Cordova, and Angular communities. Especially thanks to its fantastic Node debugger, and its JS IntelliSense (powered by TypeScript’s strength in tooling). The Angular team at Google even write Angular 2 in VS Code.

I’ve seen less about its strengths for CSS and HTML development, so I’d like to cover a few of these in this blog posts. Much of this is brand new in the recently released January preview.

General editor features

Auto-resize open panels

Like many editors, a number of files (to a max of 3) can be opened side by side. I work on a small laptop where space is at a premium, and while 3 files can be shown side by side, there isn’t really enough space to realistically work with all three. Except VS Code has a nifty feature where if the panels are slim enough, the panel with keyboard focus will expand to fill the space, with the other panels contracting. This is best shown in a video:

Change bars

If you’ve ever used an inspector such as F12, you’ll probably have noticed the little change bars when you edit things like CSS properties. VS Code has these throughout the editor, so you never have to figure out what you might have changed while experimenting with fixing that stubborn bug. I find it really useful for retracing steps and getting rid of the things I tried that didn’t work out.

screenshot of change bars in VS Code
GitHub and source control integration

Somewhat related to the previous point, there is full source control built in by default. It isn’t as complete as an app like GitHub Desktop, but it allows you to do many of the common tasks you do while coding, such as switching branches, committing changes, comparing diffs, and so.

Built in accessibility

It is currently heavily in development, but along with Microsoft‘s company wide commitment to accessibility, the VS Code team are currently working on making the editor and debugger fully keyboard accessible, along with making it work with a screen reader. There is a dearth of great editors and debuggers that work well for screen reader users, so if they nail this, it is going to be great news for the accessibility community. You can follow their progress in the accessibility GitHub issue.

Performance

A common complaint levelled at editors that are built with web technologies is that they are slow. Especially when you start adding a bunch of your favourite extensions that are always running in the background. VS Code has never slowed down for me (and it can handle our huge project with thousands of source files). As far as I understand it, rather than all extensions being on the same UI thread as the app, each extension has their own thread, so they don’t slow down the app responsiveness, even when you’ve lived in the app for a while and loaded it up with customisations.

Evergreen

VS Code currently updates on a monthly schedule. The GitHub project has a healthy following with multiple commits a day, meaning the editor is advancing at a fast clip.

Another nice thing is that the app upgrades in place, rather than forcing you to download and replace like I’ve experienced with other editors. This makes it painless to upgrade. And if you’d like to be further on cutting edge, there is a Insiders preview release.

CSS features

CSS is where I spend most of my time, and there are a bunch of features that help my productivity, or just make VS Code a pleasure to use. These are some of my highlights

Working with colours

The first thing you will notice is that, similar to how CSS inspectors work, each time you include a colour in a CSS file it will include a colour swatch. This works for both solid colours and hsla/rgba. It even works in gradients, but only for the individual colour stops.

screenshot of colour swatches in VS Code

That is kinda cool (especially for the hex notation challenged such as myself), but what makes it really useful is that while typing the value for any CSS property that accepts a colour, all the valid values are included in the auto-complete. This includes all the named colours (also complete with a colour swatch and equivalent hex notation), and rgb(a) and hsl(a) notation (complete with hints about what the parameters mean.) 

screenshot of auto-completing colour values in VS Code

Not enough? Well, it also includes all the colours you’ve already used in the file, so if you don’t remember the exact hex code of your company blue, it is right there as you type. It really makes it easy to make sure you’re not adding a bunch of same but different colours.

Understanding selectors

Do you sometimes forget exactly what a selector matches, such as the difference between ~ and >? If you do, hover over a selector in your CSS file and it’ll give you a handy hint:

Mini reference inside your editor

Many editors have auto-complete built in, and VS Code is no different. However, I don’t think there is any editor that is close to being as complete and up to date. First of all, often the list of features gets frozen in time and updated ad hoc. VS Code is almost entirely updated with the latest specs that are implemented by browsers. So this includes features such as Motion Path and Grid to the advanced hyphenation properties in CSS4 Text. And it doesn’t just list the WebKit prefixes; it includes everything, including Opera, Mozilla, MS and WebKit. It even including CSS features defined outside of CSS, such as Pointer Events and Fullscreen API.

For CSS properties, a one line description (mostly taken from the spec) is given, that can be expanded to show the complete description, instead of linking off to a separate page outside the editor. It is really useful for those properties you don’t use every day, or those with somewhat arbitrary syntax, such as Flexbox (I never remember which controls the cross axis and which is the main access.)

This also works for CSS values and at-rules.

Another neat thing is that VS Code knows when a property accepts a length value, or a percentage, so even for features like width, it will list all the valid unit types (again, fully up to date). The full list of global values are also covered, instead of just inherit.

Features that accept image values know about the entire range of image types, including the various vendor prefixes needed, and new up and coming features such as image-set().

That is cool while writing your CSS, but you might be looking at some existing code and forget what it means (or it was added by someone else). Now you can hover over the properties in a similar way to the selectors, and the description will also be show.

Syntax highlighting valid properties

Like many editors, the syntax highlighting is based off of TextMate files, but the feature list has also been thoroughly updated (I hope to commit this back). Originally it would only highlight valid CSS properties, but the list was so out of date, you couldn’t tell if you mistyped a property name, or it was just too new to be recognised. Now all the properties and values are as up to date as the auto-complete list. Again, it will recognise even new things such as the all property, or motion-path, and SVG properties.

Browser support

Perhaps even more useful than that, there is browser support information built into the IntelliSense. First of all, it excludes any features (properties or values) that are not supported by any browser. Features that are supported include the browser support list inside the description, so you don’t need to leave your editor to research if you can use the feature. Not only this, but it is granular enough to be all the way down to the value level, rather than just for a property or spec. This took a lot of testing!

Additional help with more obscure syntax
timing functions

Ever needed to using a timing function for an animation or transition beyond the presets like ease-in and ease-out? Now VS Code includes the commonly used Penner Easing Functions mapped to CSS, so you can get the cubic-bezier value without having to look it up. If you’ve used animation in jQuery you may be familiar with these.

Unicode range

The unicode-range descriptor allows you to specify what range of characters a Web Font is used for. A common stylistic use of this is to specify a font just for the ampersand (the often cited “use the best available ampersand” mantra). Hands up who knows the unicode escape for an ampersand off by heart (no peaking!) I suspect not many of you (I know I don’t!).

In VS Code, the IntelliSense for the unicode-range property will include this in the list, so you don‘t have to look it up. I’ve also included a bunch of the ranges for commonly used languages, so you can build out custom ranges by selecting as you type. You’ll never have to look up unicode charts again!

OpenType feature tags

There are a number of feature tags defined in the OpenType spec to access different font features. Examples include ligatures (common, stylistic, etc), small caps, and so on. Instead of having to look these up, they‘ve also been included in the IntelliSense for the font-feature-settings property, along with the human readable friendly name.

Built-in CSS linter

A CSS linter is built in (which, of course, you can customise the rules), so that you get errors and warnings out of the box. If you prefer a different linter, it is possible to disable it and download your favourite extension.

HTML features

Many of the great CSS features apply to HTML as well. For example all the new HTML5.1 features are included in IntelliSense (complete with description), including <picture> and <template>.

When autocompleting HTML attributes, it is smart enough to know which attributes belong to which element, and even the valid values. An example of this is that when using the role attribute, it suggests all the ARIA 1.1 roles as completions. This is also up to date with the spec, so attributes such as download will be suggested for the <a> element, and srcset for <img>.

ARIA properties

There are a lot of ARIA properties. They’re not always the easiest to remember, so VS Code also includes all of these in the auto-completion list. I don’t think any other editor includes these. I’m hoping this will help developers write even more accessible content.

That’s just a few of my favourite features; a few of which have just landed over the last month. There is a solid roadmap going forward, including the much requested code folding. What are your favourite features, and what do you miss from your favourite editor?