Generated Content by David Storey: A blog about HTML5, CSS3, SVG, ES5/JavaScript and other open web technologies. Also throws in thoughts about design and general geekery.
Why I love Visual Studio Code for CSS / HTML development
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.
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.
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.)
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?
The Microsoft products I use day in day out, even at home
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?
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.
Welcome to the all new Internet Explorer Developer Channel
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.
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.
Stale. An issue tracker for web docs past their sell by date
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.
Is your Fullscreen API code up to date? Find out how to make it work the same in modern browsers
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 fullScreenEnabled fullscreenEnabled S → s fullScreenElement fullscreenElement S → s requestFullScreen() requestFullscreen() S → s cancelFullScreen() exitFullscreen() cancel → exit, S → s fullscreenchange fullscreenchange 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.
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.
The (probably not) definitive list of CSS features in non-CSS specs
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 Property Support Firefox Safari Opera Chrome IE touch-action No No No No Yes
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 Property Support Firefox Safari Opera Chrome IE resource-priority No No No No No
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.
Property Property Support Firefox Safari Opera Chrome IE ime No No No No No ime-align No No No No -ms- ime-mode * Yes No No No Yes ime-width No No No No No ime-offset No No No No No
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 Property Support Firefox Safari Opera Chrome IE :fullscreen pseudo-class Alt Alt Alt Alt -ms- ::backdrop pseudo-element No No No No -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 element Support Firefox Safari Opera Chrome IE ::content No No No No No
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 feature Support Firefox Safari Opera Chrome IE view-mode No No Dropped No No
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 Property Support Firefox Safari Opera Chrome IE color-interpolation Yes Yes Yes Yes No color-profile No No No No No color-rendering No Yes Yes Yes No enable-background No No Dropped No Yes fill Yes Yes Yes Yes Yes fill-opacity Yes Yes Yes Yes Yes fill-rule Yes Yes Yes Yes Yes glyph-orientation-horizontal No Yes Yes Yes Yes glyph-orientation-vertical No Yes Yes Yes Yes image-rendering * Yes Yes Yes Yes No kerning No Yes Yes Yes Yes marker Yes Yes Yes Yes Yes marker-start Yes Yes Yes Yes Yes marker-mid Yes Yes Yes Yes Yes marker-end Yes Yes Yes Yes Yes pointer-events Yes Yes Yes Yes Yes shape-rendering Yes Yes Yes Yes No stop-color Yes Yes Yes Yes Yes stop-opacity Yes Yes Yes Yes Yes stroke Yes Yes Yes Yes Yes stroke-dasharray Yes Yes Yes Yes Yes stroke-dashoffset Yes Yes Yes Yes Yes stroke-linecap Yes Yes Yes Yes Yes stroke-linejoin Yes Yes Yes Yes Yes stroke-miterlimit Yes Yes Yes Yes Yes stroke-opacity Yes Yes Yes Yes Yes stroke-width Yes Yes Yes Yes Yes text-anchor Yes Yes Yes Yes Yes text-rendering * Yes Yes Yes Yes No writing-mode * No Yes Yes Yes Yes
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 Property Support Firefox Safari Opera Chrome IE audio-level No No No No No buffered-rendering No Yes Yes Yes No display-align No No Dropped No No line-increment No No Dropped No No solid-color No No Dropped No No solid-opacity No No Dropped No No vector-effect Yes Yes Yes Yes No viewport-fill No No Dropped No No viewport-fill-opacity No No Dropped No No
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 Property Support Firefox Safari Opera Chrome IE marker-knockout-left No No No No No marker-knockout-right No No No No No marker-pattern No No No No No marker-segment No No No No No paint-order Flag No No No No
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 Function Support Firefox Safari Opera Chrome IE icc-color() No No No No No device-gray() No No No No No device-rgb() No No No No No device-cmyk() No No No No No device-nchannel() No No No No No icc-named-color() No No No No No cielab() No No No No No cielch() No No No No No
SVG Parameters
Spec
http://www.w3.org/TR/SVGParam/
Status
Working Draft
Properties Property Support Firefox Safari Opera Chrome IE parameters No No No No No
SVG Compositing
Spec
http://www.w3.org/TR/SVGCompositing
Status
Working Draft
Properties Property Support Firefox Safari Opera Chrome IE clip-to-self No No No No No comp-op No No No No No knock-out No No No No No
MathML for CSS Profile
Spec
http://www.w3.org/TR/mathml-for-css/
Status
Recommendation
Properties Property Support Firefox Safari Opera Chrome IE table-baseline No No Dropped No No
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.
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.
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.
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.
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:
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.
Setting native-like scrolling offsets in CSS with Scrolling Snap Points
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.
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:
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:
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.
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:
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?
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.
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:
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.
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 localeMatcher 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 (“٪”).
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:
numberingSystem
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.
timeZone
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
timeZoneName
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.
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:
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.
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.
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.
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.
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.
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:
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). – [email protected]
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.
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.
Feature IE 11 IE 10 Firefox Chrome Opera 15 Opera 12.1 WebKit Nightly Safari 6 let Yes No JS 1.71 Flag2/strict3 No No No recognise const Yes No Yes Yes, !strict4 !strict4 !strict4 constant const Yes No Yes Yes No Yes No block level const Yes No No Flag2/strict3 No No No
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.
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
The border-image shorthand and individual properties are now supported
Flexbox support has been updated to the latest spec, and unprefixed
The pointer-events property now works on HTML content.
The text-combine-horizontal property from CSS Writing-Modes is now recognised with the -ms- prefix. However, I’m not sure to get this to work. I assume it only works with glyphs that are upright in vertical text, but IE doesn’t support the text-orientation property. Perhaps this is work in progress?
:fullscreen pseudo-class and ::backdrop pseudo element, both with -ms- prefix. Not technically part of a CSS spec, but included in the Fullscreen API spec.
IE10 had a bug where the rem unit could not be used in the font-size component of the font shorthand. This has thankfully been fixed in IE11.
HTML5, DOM4 and associated APIs
The following are now supported:
The hidden attribute
Fullscreen API
Custom Data Attributes API (element.dataset)
Device Orientation Events
The Screen Orientation API
DOM4 Mutation Observers (replacement for DOM Mutation Events)
Input Method Editor API (scripted access to an IME)
Media Source Extensions
Encrypted Media Extensions (this will prove controversial I’m sure)
Web Cryptography API
Tracking Preference Expression (DNT)
Dynamic TextTracks (addTextTrack, addCue, and removeCue)
TTML Simple Delivery Profile for Closed Captions
Streaming XHR cache control (msCaching attribute)
Pointer Events have been updated to the latest Candidate Recommendation
devicePixelRatio
Navigation Timing 2
pagehide/pageshow events
The prefetch attribute
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):
let
const
Map
WeakMap
Set
__proto__
Block-level function declaration
Non-standard __defineGetter__ and __defineSetter__
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:
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:
MSIE has been replaced by IE
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.