11 Things I Learned By Studying the Metro UI CSS Files
A few years ago I had to painfully admit I was really lost when it came to what today I call modern web development. I decided I had to change, I had to get myself up to speed and I had to relearn things. Working with ASP.NET WebForms since Beta 1 really put me in a bad position to compete with the larger market, especially the consumer web space. To do this I needed to learn three languages really well, HTML, JavaScript and CSS. Notice there is nothing relating to the server-side in that list (I know node.js, but it was not around at the time).
What I really decided to do was become extremely efficient modern web developer by learning those three languages, not as a language purist but as a developer that understood the symbiotic nature shared by those three languages and their platform, the browser. I call this the AJAX layer. HTML was the first target because it was the easiest. Next came JavaScript because it provided the application engine I needed and jQuery made that process fun and easy.
Then came CSS, which honestly is the hardest in my opinion. If most developers were honest they would say the same too, but I think far too often they intentionally forget about CSS and focus on JavaScript instead. So I am still learning CSS, not because I did not know it, but like a great artist I did not feel it. CSS3 has added so many new features that is extended the learning curve as well.
So I have decided to start a more formal study of good CSS practices and architecture by finding good resources, but also by studying real-world implementations. Inspired by Paul Irish's 10 and 11 things he learned by studying the jQuery source I decided to share 11 things I learned by studying the Metro CSS files used to create Metro (Windows 8 Store) applications for Windows 8. Once you have installed Visual Studio 2012 with Windows 8 application support you should be able to fine the dark and light theme CSS files in the \Program Files (x86)\Microsoft SDKs\Windows\v8.0\ExtensionSDKs\Microsoft.WinJS.1.0\1.0\DesignTime\CommonConfiguration\Neutral\Microsoft.WinJS.1.0\css folder.
I think the Metro CSS files are a good mix of how to structure a Cascading Stylesheet as well as provide some insights as to what we can and should do to make our web applications easier to maintain and add a performance boost.
Organization
The file defines styles for "big ticket" items in a group followed by font-face imports, headers, form elements, controls then colors and language specific rules. They are following principles known as Object Oriented CSS, which was popularized by Nicole Sullivan a few years ago. Not only does this technique make it easy to manage your CSS it also makes it perform better. As someone who has and still does create some scary CSS over the past couple of decades I can see how this methodology is extremely helpful. Like anything good in the programming world it takes some discipline and mindset changes. But you will ultimately find your code is much more maintainable and that means fewer headaches over the application lifetime.
If you follow the Metro CSS file you will see dimensions being set first, followed by colors and finally culture specific settings. This technique really utilizes the cascading part of CSS because it can override previous rule settings. Personally this is going to change the way I do things. Typically I want to define a rule once unless I can avoid it. I am having to learn to be a little more flexible with that attitude based on what I am seeing in the Metro CSS as well as other good CSS examples. You may need to do the same. In other words focus on a specific task in a rule definition like dimensions or colors or maybe pseudo selectors.
Another advantage this OOCSS techniques affords is the ability to easily break your CSS into different files. In the not too distant past I was very resistant to having lots and lots of JavaScript and CSS files. I hated having to manage all of them. I think it is safe to say I have switch that stance because I am finding minimizing and combining those files easier and easier as better tooling is created. Just think about the new bundling and minification supported added with the latest ASP.NET version. You have extremely finite control over that process. My guess it the Metro CSS file is the product of the combine process. In native applications the minification is not as important because the file is downloaded as part of the large binary anyway. Breaking down this organization I can see a whole group of CSS files that were combined to make the whole.
Be Your Own Reset
A few years ago I discovered CSS resets. These files set the base CSS rules because each browser has its own set of rules it automatically applies to each element. So for example if you want all unordered list to have a margin-left:30px you can define this in your reset. Generally I have used the Eric Meyer or YUI library reset in my projects the past few years. Sometimes I do find even they can get in the way when I do not explicitly override the rule. But it is nice to have the exact same starting point to create styles no matter the browser.
A simple example I found in the middle of the file control anchor underlines and image borders, which is something common I overwrite in my CSS:
a {text-decoration
:none;
cursor
:default;
}/*
No border on images when in a link.
*/
img
{border-style
:none;
}
Looking over the Metro CSS they really created their own reset by specifying the rules they want to enforce, knowing what elements they would be using and needing to style. Now realize CSS for a native, or single known browser is a lot easier than when you are targeting every browser that might execute your web application. The Modern UI CSS can be a little simplified, so unless you are targeting a specific browser and browser version, which I would not recommend, expect to create a much broader set of reset rules.
CSS3 Offers a Lot of Finite Styling Control
The promise of CSS3 is the ability to do things web developers and designers have desired for a couple of decades now. And well it delivers on a lot of that promise with so many new added features, especially in concert with new HTML5 markup functionality. In the following code snippet are the CSS rules that define how an HTML5 range control is styled. This is the control the user can slide back and forth to provide a value.
First all these selectors use the input[type=rage] to specify the type of element to apply the rules. Next we see a series of pseudo selectors to give more finite rendering control to elements belonging to the control like the track, thumb, ticks, etc. This means you can completely overwrite the default styling provided by the browser to provide a very customized, consistent experience.
/*
Range control.
*/
input
[type=range] {width
:280px;
height
:auto;
padding
:17px 0 32px 0;
}input
[type=range]::-ms-track {padding
: 0;width
:auto;
height
:11px;
border-style
:none;
color
:transparent;
/* ticks hidden by default */
}input
[type=range]::-ms-thumb {width
:11px;
height
:11px;
border-style
:none;
}input
[type=range]::-ms-ticks-before,input
[type=range]::-ms-ticks-after {width
:100%;
height
:5px;
display
:none;
}input
[type=range]:disabled::-ms-fill-lower {margin
-right
:5px;
}input
[type=range]:disabled::-ms-fill-upper {margin
-left
:6px;
}input
[type=range]:disabled:-ms-lang(ar, dv, fa, he,
ku-Arab, pa-Arab, prs, ps, sd-Arab, syr,
ug, ur, qps-plocm)::-ms-fill-lower {margin
-right
: 0;margin
-left
:5px;
}input
[type=range]:disabled:-ms-lang(ar, dv, fa, he,
ku-Arab, pa-Arab, prs, ps, sd-Arab, syr,
ug, ur, qps-plocm)::-ms-fill-upper {margin
-left
: 0;margin
-right
:6px;
}
Honestly the thing I find the most difficulty with is finding all the pseudo selectors I can use. Fortunately Microsoft is actually providing pretty good documentation to this effect, you need to take the time to read through it all. WebKit, Opera and Mozilla are providing similar documentation for their browsers too.
Pseudo Elements are Extremely Handy
I am seeing more and more modern web applications use pseudo elements. These are elements either before or after an element that do not exist, but through the magic of CSS3 support you can create some extremely slick shapes and content. In the Metro UI CSS I notice how they create the back button you see in the top left corner of applications. My first thought on the back button is it being a sprite image. In reality it is a pseudo element using the content CSS rule. Content is a CSS setting that allows you to specify text to be rendered before or after an element using either the ::before or ::after pseudo elements.
Here you see the Metro design gurus using an ASCII character reference to inject the back arrow character in the Segoe UI Symbol font face. This is pretty nifty IMO because a single character reference like this is much lighter than downloading the image equivalent even if it is part of a sprite. The only thing I would guard here is for web applications used outside Windows, you won't have Segoe UI Symbol font available. It is a proprietary font that belongs to Microsoft and I am not 100% of what font family to substitute to provide that back arrow. Maybe I can write about that answer later.
.win-backbutton
::before {font-family
:"Segoe UI Symbol";
font-weight
:normal;
/* Can Only be used with ::before & ::after */
content
: "\E0D5";
vertical-align
:50%;
}
In case you were wondering where the circle around the back arrow comes from it is the actual element with rounded corners set.
.win-backbutton
{display
: inline-block;
min-width
: 0;min-height
: 0;background
-clip
:border
-box;
box-sizing:border
-box;
border
-radius:50%;
border-width
:2px;
border-style
:solid;
padding
: 0;text-align
:center;
/* Normal sizing. */
width
:41px;
height
:41px;
font-size
:14pt;
/* line-height must match the content box height. */
line-height
:37px;
vertical-align
:baseline;
}
Make CSS Rule Names Very Descriptive
There are not many hard rules defining how to name a CSS class, but I keep finding it more and more useful to use names that are very descriptive. Sort of like UNIT tests names. Let's look at a couple of class names in the Metro UI CSS file:
.win-appbarclickeater
{
...
}.win-flyoutmenuclickeater
{
...
}
First I want to point out the use of the '-', it sort of makes the name read like a C# namespace and class name. In this case I can guess as to how this rule is used. First it is going to be used in native Windows applications, hence the 'win' prefix. Next I know the class will apply to the App Bar and more specifically something to do with a click eater. Now I have not done much of anything with WinJS programming, but just knowing there is something called a click eater intrigues me! The next rule is similar, this time it will apply to a fly out menu click eater.
The point here is even though I have not written a Win-JS application I have a reasonable understanding as to how these rules are applied. They are self documenting, which can be extremely helpful in maintaining the CSS file and your markup.
Use rgba(#, #, #, #) Instead of Color Hex Codes
Normally I use HEX codes, I sort of just understand them after so many years. There is nothing inherently wrong with using something like color: #C30000. But the more and more I evaluate modern web sites and applications that have really good user experience the less and less I see color hex codes. Instead I see more and more rgb(#, #, #) and rgba(#,#,#,#).
I think this is because the newer CSS3 color functions give you a bit more flexibility by encouraging you to use the opacity value at the end. I have also read several articles on how the rgb & rgba functions work better for gradients and shadows. If you know your application is not going to be running with a modern browser you will have to decide what you want to do. More and more support for the rgb functions is common and you should start consider using them as a best practice.
The more I think about it the more I think this is the best strategy because you will get more granular control over colors. If you are following the organizational pattern I referred to earlier then you can easily add an additional style sheet reference for older browsers that do not support the rgba color functions to ensure you apply the colors you want.
Don't Set Fixed Line-Heights
I find myself having to set line-height more often than I would like. Normally I set it to a fixed or known height to make my layout work. The more I study 'good' CSS I notice they rarely it ever use fixed dimensions like 21px. Instead they use a simple scale number like 1.1429. OK I have no idea where the 1.1429 came from, that is still a mystery of sorts. But let's look at an example from the Metro CSS file.
h1
,.win-type-xx-large
{font-size
:42pt;
font-weight
:200;
letter-spacing
: 0;/* 64px when font-size is 42pt */
line-height
:1.1429;
}
Notice the comment after the line-height rule? It says it will make the line height 64px when the font-size is 42pt, which is defined earlier. So this means the line-height will auto scale from the element's font-size. Off the top of my head I don't exactly know what the correlation between pt and px is, but my guess is here a 42pt font will be 56px tall which means makes the math work. Which makes another side point, you should probably not set font-sizes to pixels, but instead use points or em, which are a little more scalable. I admit I am one of the worst offenders of this rules.
If you want a resource to help you convert between different size using visit GetAllFix.com.
No Id Selectors
There are no #MYELEMENT selectors in the entire document. In fact the only # I found was in a comment. This is important when writing efficient CSS because using id selectors are too specific to be efficient. ID selectors are for JavaScript, which are fast in that context. In CSS using an ID means you can not use that CSS selector's rule for anything else. It is much better to add a CSS class to the element instead because the rule can be reused. Another thing about CSS is class selectors are read from right to left. This means even if you have an ID in the selector if you have any other selector after the #MYELEMENT the parsing will start with the item to the right of the ID selector, rendering any speed advantage moot. So ID selectors should be avoided in CSS styles.
Make the HTML element Overflow Hidden
We have entered a whole new world of web client architecture in the past few years. Web Sites are on their way out, being replaced with Web Apps. If you have noticed I have tried to stop mentioning web sites on this blog, but instead use web app, this is because user experience expectations have been raised dramatically with the popularization of native mobile apps. No linger can we get away with a traditional request-response model, instead web apps need to be more responsive and offer much more engaging experiences to win user affection.
So what do that have to do with making the HTML element overflow:hidden? Making these native application like web apps means we are no longer going to win customers with a long scrolling page We need fixed headers, footers and other elements on the page. The content of interest needs to scroll within the entire screen's viewport. So just like native Metro UI (Windows Store UI) apps do not exhibit classic web page vertical scrolling we can do the same thing with our HTML5 web apps. Defining HTML overscroll:hidden simply means nothing will cause the document to allow legacy scrolling experiences.
IE 10 Introduces Many New Vendor Specific Rules
Sort of continuing the above section on lots of finite control you will see many references to vendor specific rules, starting with -ms-. This is not unique to Internet Explorer these are common in all the browsers. Internet Explorer is the first browser to provide solid support for unprefixed rules. But like the IE competitors they still have some vendor specific features you will have to track down if you want to take advantage of them. You can see this in effect in the very first CSS rule definition with -ms-scroll-translation. This is a property that specifies how the mouse wheel scroll should work, which if you think about it Metro UI is probably the only design framework that takes advantage of horizontal scrolling.
html
,body
{height
:100%;
width
:100%;
margin
: 0;
-ms-user-select
:none;
cursor
:default;
-ms-scroll-translation: vertical-to-horizontal;
}
I think you will find several other style properties that are -ms- prefixes that do not have CSS properties in other browsers. If you see new CSS3 properties that are common you will see them in unprefixed form that is because IE supports these common properties without a prefix.
Looking further down the file you will see the following snippet, which gets into the responsive design space because it leverage media queries to specify CSS rules based on screen size.
@media (-ms-view-state: snapped) {
....
}
I know WebKit, Mozilla and Opera all have some rules they implement no one else does, so when possible raise your awareness of possible vendor specific features you can take advantage of and do so. You will increase your web app's richness.
You Can Specify Custom Rules By Language
Personally I have not done that many applications that needed to target multiple languages or cultures. But as I review the traffic to this Blog and other public facing web apps I have managed I know there is a lot of international traffic. Its one thing to deal with translation, and that is not what this is about, but we have to understand other cultures have slight variations for their fonts and character sets.
The sample rule below shows how you can specify specific fonts based on a language or culture. This won't change the translation, but it will probably make your application more usable in these countries. The CSS rule uses a -ms vendor specific selector, which I would assume is IE 10 specific. I don't know if there are equivalents for other browsers at this time.
body
:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO),.win-type-xx-large
:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO),.win-type-x-large
:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO),.win-type-large
:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO),.win-type-medium
:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO),.win-type-small
:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO),.win-type-x-small
:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO),.win-type-xx-small
:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO),input
:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO),textarea
:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO),.win-textarea
:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO),button
:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO),select
:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO),option
:-ms-lang(zh-HK, zh-TW, zh-Hant, zh-MO) {font-family
:"Microsoft JhengHei UI",
"Segoe UI",
"Ebrima",
"Nirmala UI",
"Gadugi",
"Segoe UI Symbol",
"Meiryo UI",
"Khmer UI",
"Tunga",
"Lao UI",
"Raavi",
"Iskoola Pota",
"Latha",
"Leelawadee",
"Microsoft YaHei UI",
"Malgun Gothic",
"Estrangelo Edessa",
"Microsoft Himalaya",
"Microsoft New Tai Lue",
"Microsoft PhagsPa",
"Microsoft Tai Le",
"Microsoft Yi Baiti",
"Mongolian Baiti",
"MV Boli",
"Myanmar Text",
"Cambria Math";
}
I found these rules at the bottom of the file, which means they will over-write any previous font definitions only when the targeted cultures are in use. So these rules will not conflict with your normal settings unless the culture is being used. It will only take up extra space in your file. There are about 500 lines of language specific definitions. It might be worth it to detect the culture on the server and add an additional CSS file reference in your header just to cut down on the download size.
Conclusion
As modern web takes over we need to adopt better techniques to write our code. Good, clean, well organized CSS files not only help you maintain and develop the rules they also provide some performance gains. You should find you write less CSS in the long run as well and from what I can see and have read you will most likely write cleaner HTML too. So I challenge you to review some of your applications' CSS rules and see if you can start cleaning it up today.
I used the Metro UI CSS files as my first reference when studying good CSS implementations. I hope to add a future post or two on what I discovered evaluating other good and possibly bad sources of CSS.