hover animation preload
Showing posts with label CSS. Show all posts
Showing posts with label CSS. Show all posts

the Future Of CSS: Embracing The Machine
by kamran.hanfi in

the Future Of CSS: Embracing The Machine
Designers hold CSS close to their hearts. It’s just code, but it is also what makes our carefully crafted designs come to life. Thoughtful CSS is CSS that respects our designs, that is handcrafted with precision. The common conception among Web designers is that a good style sheet is created by hand, each curly bracket meticulously placed, each vendor prefix typed in manually.
But how does this tradition fit in a world where the websites and applications that we want to create are becoming increasingly complex?

Looking Back

If we look back in history, deep into the Industrial Revolution, we will see a parallel with what will happen with our handcrafted style sheets once the complexity of the products that we want to build becomes too great.
The Industrial Revolution (which took place approximately between the middles of the 18th and 19th centuries, starting in the UK) was a period of upheaval in society; several aspects of life were changing. Much of this was due to the way people produced goods: during this period, manual labor started to become mechanized. The textile industry, for example, moved from primarily human- to machine-based production, and its artisans started looking at ways to be more efficient.
C. P. R. passenger train at Donald Station, BC, about 1887

One of the many products of the Industrial Revolution. (Image: McCord Museum)
These machines that were created with efficiency in mind were initially quite primitive, and the public didn’t know what to think of them. It took us some time to adapt the way we worked with them and the way we thought of them.
Jobs that previously required human labor now didn’t require anyone; a machine could do the job cheaper and faster; employees became redundant. But the jobs in which people were being replaced by machines were mainly repetitive ones, jobs for which manual labor didn’t necessarily make for better products — at least not in any significant way.
Some argued that the output suffered in quality, that machine-made objects lacked personality, that craftsmanship was being lost, and yet production improved and evolved. We were also getting to the point that some products were getting too complex to be made by hand anymore.
This revolution shaped the world we live in today and gave us access to things that were until then too expensive or even non-existent.
Getting back to our topic, we’re seeing increasing complexity in the world of Web design and CSS. We want to create increasingly complex websites and apps — systems so complicated that they cannot be made entirely by hand.
MobileMe Calendar app

MobileMe, with its extensive functionality and comprehensive interface, is an example of a complex Web application.

The World Of Developers

Developers and programmers are already inclined towards automation. Developers instinctively avoid reinventing the wheel. They understand the need to automate production (at least some stages of it); they understand that hand-crafted code is not needed at every step of the process.
Even if you are a great front-end developer who knows JavaScript like the back of your hand, you still defer a lot of your work to jQuery or some other library. Even if you’re able to write the code yourself, the time you’d save by not doing that frees you to deal with more significant problems. The gains in writing a script from scratch are no match for the gains in being able to focus attention on problems that no machine or automated process can solve.
jQuery website

jQuery, a well-known developer’s tool.
The skills and knowledge you’ve gathered through the years are not in vain, though. This knowledge is what makes you the best person to decide whether to choose jQuery; it’s what makes you able to adjust a plugin that doesn’t quite do what you need; and it’s what makes you capable of determining the best tool for the job.

The Wrong Attitude

Web designers don’t approve of these kinds of shortcuts. This way of thinking doesn’t translate to CSS; in the world of CSS, taking these “shortcuts” is not well regarded.
We CSS authors have a list of dirty words that we avoid saying when we’re speaking with fellow Web designer friends. For example, when someone says they’ve used a CSS framework, the apology immediately follows: “It wasn’t our fault.”
Principles such as DRY (don’t repeat yourself) are not present in CSS.
DRY states that “Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.” This applies not only to code but to every aspect of a product, such as design itself. When DRY principles are followed, we’re supposed to end up with products that are of higher quality and easier to maintain.
We CSS authors don’t think of the cost of maintenance or the increased complexity that duplication and cancelling out of styles add to our CSS sheets.
We usually follow something closer to WET: we enjoy typing. Why someone would want to hand-code vendor prefixes for CSS gradients is beyond my understanding, but the truth is that some people do, and they take pride in it.
CSS authors — i.e. Web designers who write CSS — don’t like the machine. We don’t think any CSS that the machine can produce will ever be as good as the one we make ourselves by hand. But what if this is not true? What if the result is as good as our own manual labor from scratch?
Other groups have had the same fears. The Luddites were workers who fiercely opposed the Industrial Revolution and progress. They said that machines were taking their jobs — which was true. But they fought, protested, became violent and eventually lost. Things would evolve whether they liked it or not.
Luddites, frame breaking

The Luddites, smashing the machine. (Image: Wikipedia)

Context Matters

It’s true that we don’t all code for the Facebooks and Yahoos of this world; your CSS’ performance might not be the most important thing to focus on in your projects. But this is why considering context matters, and this is why it’s important not to dismiss techniques and solutions because someone once told us they were wrong or dirty.
We can embrace the flexibility that some measure of automation gives us and focus our worries and energies on deeper problems. We could focus on so many things: accessibility, usability, design theory, psychology, business, economics, experimentation and even programming are all suitable candidates and are areas in which having some knowledge, even at a basic level, can greatly improve our work.
Reading list

An interesting reading list. (Image: Mike Kuniavsky)
Expanding our skill set can give us a better understanding of the products we create, the people we create them for (and their context), and how they are supposed to work behind the curtains.
Rethinking our processes might lead to better quality work. It might lead to perfecting a machine still in its infancy. If we don’t deny mechanization from coming into our work, we get the chance to shape it so that it does exactly what we want it to do.

Try This At Home

If we look around, we’ll see that several people are already trying to change the way we write our CSS, whether by introducing some kind of automation or by looking at ways of creating style sheets that don’t bypass issues such as maintainability. We can take inspiration from the work they produce in a number of interesting ways. Below are some of the most prominent examples, but feel free to add your own list in the comments section.

Frameworks: Don’t Reinvent the Wheel

As mentioned, “frameworks” are probably the dirtiest word in a CSS author’s vocabulary — or second dirtiest, after “Dreamweaver.” (Note: this article was written before the advent of Adobe’s Muse.)
Often when discussing the subject of this article, people walk away assuming that the message I am trying to get across is to use CSS frameworks. That’s not correct. But it isn’t entirely incorrect either. Let me explain.
Frameworks are an important tool in a CSS author’s repertoire. By that, I don’t mean that you should blindly use popular frameworks such as Blueprint or 960 Grid System. Sure, these frameworks have nailed some things, and we can certainly learn a lot from their flexibility and modularity, but it’s more important that you — especially if you’re on a team — adapt a framework to the needs of you, your company and your team.
Blueprint website

Blueprint, a popular CSS framework.
Perhaps you or your company works with such disparate clients and projects that a framework wouldn’t really be helpful, though. Perhaps a library in which you can collect snippets of frequently used code would be more useful. Or perhaps a starter template is what you need.
Whatever you need, more often than not you can find a way without having to reinvent the wheel from project to project. And if indeed you work with a number of other designers and developers and share CSS, then these tools will make collaboration easier, and you won’t have to adapt to the style of the person who created a particular file.
Frameworks can also be useful tools for wireframing and prototyping, especially when there are time constraints and you need to put something in front of users or stakeholders quickly.
There are differences between a framework and a patterns library, components or even a simple collection of code snippets. A framework is a system that is flexible and can be adjusted to a myriad types of layouts, creating various page templates, whereas a library constitutes smaller individual modules that don’t have to be tied to any particular overarching framework or page construction.
A pattern demonstrates how, for example, tabbed navigation should function or how to mark it up; a design component could be the exact visual representation of an instance of tabbed navigation, with its colors, shapes and fonts. This explanation of these two distinct and important concepts is very simplistic. The “Further Reading“ section at the end of this article lists some useful resources on both.
Yahoo's Design Pattern Library

The Yahoo Design Pattern Library.
A framework doesn’t have to spit out numerous unsemantic class names to every container in your markup. If you are creating your own, you are free to name those classes whatever you feel is right.
Let’s imagine you are starting to write a framework that can be shared across various development teams in your news organization. You might start with the following skeleton:
/* Resets */

/* Structure */

/* Global elements */

/* Visual media */

/* Article structure */

/* Forms */

/* Tables */

/* Reusable */
This structure is probably similar to many of your own style sheets. Let’s look at the “Article structure” section as an example of something that would probably benefit from some framework inspiration. In the project, you will probably have to accommodate several variations of templates from various departments, sub-departments, content creators, editors, etc. Rather than using classes like span-6 and pull-3, you can define a naming system that better ties into the website’s content. For example:
/* Article structure */

article {
width: 80%;
}
article.charticle { /* Charticle pages have no sidebar */
width: 100%;
}
article.listicle {
width: 70%;
}

article > .headline {
font-size: 2em;
}
article.feature > .headline {
color: #000;
}
article.breaking > .headline {
text-decoration: underline;
}

article > section {
border-bottom: 1px solid #efefef;
}

article > aside {
background: #efefef;
padding: .5em;
}

article > footer {
font-size: .9em;
}
Several things about the above CSS could be debated (I’m sure many of you have strong feelings about descendent selectors and named elements and even whether some of these classes could have been simple element selectors — to name but a few points), but none of this matters in this example. What does matter is how you can be influenced by what popular do-it-all frameworks are doing, and how you can apply that to your clean, semantic and perfectly named markup and CSS.
If you can plan for and analyze the needs of the people who create the content, then you can ensure that they have the flexibility they need to do their jobs and that you can be proud of your code. Sometimes an extra class is necessary, but if that makes everyone’s life easier, then why not, right?

Think of Others

Following what we discussed in the previous section, the fact that your CSS doesn’t live in a vacuum can be extremely useful.
Other people — and the future you — might need to come back later on to edit the style sheet that you’re creating today. Wouldn’t you want your future self to be free to go home to your spouse and kids earlier on a Friday afternoon rather than have to stay up late refactoring a CSS file that is hard to comprehend and impossible to extend?
Do yourself and others a favor by considering what you’re doing. Add comments to your CSS files for such things as the following:
Calculations

Font sizes (especially when dealing with ems) and layout measurements are great candidates for these types of comments.
h2 {
font-size: 18px;
line-height: 1.167; /* 21 (original line-height) / 18 (h2 font-size) */
}
Hacks

On the rare occasion that you use a hack, explain what you’re doing, refer to the hack by its common name, and link to an online reference that explains what you’ve just done.
aside section {
float: left;
width: 50%;
display: inline; /* fixes the double float margin bug on IE5/6. More on this bug/solution: http://www.positioniseverything.net/explorer/doubled-margin.html */
}
To-dos

Even CSS documents have “nice to haves,” so listing what you’ve been planning to do but haven’t gotten around to yet might be a good idea.
/* To-do
Change all colors to RGB format.
Sanitize reusable classes section.
*/
File structure

Summarizing what is contained in a particular file can save time when someone is looking for a certain selector.
/*  Table of contents
Resets
Structure
Links
Typography
Small screens
*/
Dependencies

Is this file being imported by some other file? Does it override something else? Explain what and how.
/* Christmas style sheet 2011

Overriding: main.css
Importing reset file: reset.css */
The fact that CSS comments are not standardized could cause a problem with all of this preparedness: everyone does them differently. In my quest for the ideal CSS formatting style, I discovered the dusty a href="http://cssdoc.net/">CSSDOC standard, which tries (or tried) to introduce some kind of sanity to the situation.
CSSDOC website

The old dusty CSSDOC website.
CSSDOC is an adaptation of Javadoc (a documentation generator that extracts comments from Java source code into HTML). It is also similar to PHPDoc, Javadoc’s adaptation for PHP. A comment that follows the CSSDOC format (a “DocBlock”) looks like the following:
/**
* Short description
*
* Long description (optional)
*
* @tags (optional)
*/
Every block starts with /** and ends with a space followed by */. Every line must start with a space followed by an asterisk. The tags may contain information such as @author, @copyright, @todo and so on.
The CSSDOC standard suggests that a CSS file should include a comment about the file itself at the top, containing meta data that is relevant to the whole file. This comment should include information such as the title of the document, a description and tags such as @project, @version, @author, @copyright and even @colordef, indicating which colors are used in the file. The file comment may be followed by any number of section comments that divide the style sheet into relevant blocks. Section comments include the tag @section:
/**
* Typography
*
* @section typography
*/
The CSSDOC documentation is not lengthy. Also, it hasn’t been maintained for a while, but I did find it interesting and have started applying it to my projects because it takes some of the guesswork and subjectivity out of comments.
Another way to make sharing documents on a team easier is to standardize the style. We all have our preferences on how to format CSS, how to name classes and IDs, address bugs, etc. Creating a style guide that recommends a way to do these things in your company will make it easier for anyone who edits the CSS to dive straight into what they need to do, rather than having to decipher someone else’s style.
This may be overkill for a team of one or two, but it can improve efficiency and save time when the team grows. In this case, consistency should have final say; personal preference is not important. If you’re the only one on a team of 12 who prefers single-line CSS, you will have to take one for the team. (Pardon me if I sound bitter; perhaps I still recall what happened on my own team…)
Here are some examples of style guidelines:
  • “Class and ID names must be lowercase.”
  • “Do not specify units for values of 0 (zero). They are unnecessary.”
When creating a style guide, include a succinct explanation for its inclusion, otherwise it will be easy for people to challenge it. The BBC has some great examples of guidelines that are relevant to CSS authors.
BBC's CSS Guidelines

An example of CSS guidelines, part of BBC’s “Future Media Standards & Guidelines” documents.

Learn About Object-Oriented CSS

Object-oriented CSS was started by front-end performance consultant Nicole Sullivan. The methodology brings modularity and flexibility to CSS by forcing you to create small flexible style sheets.
It follows two main principles. First, it states that an element should behave predictably, no matter where you place it on a page. So, a child element should behave the same independent of the parent, and parent elements shouldn’t need child elements to render correctly.
The second principle is that the rules that control the structure of elements should be separate from the rules that control their skin.
So, if you look at the pages that you need to build in a modular way and think of individual objects first and the pages second, then after creating the initial CSS you should be able to build any page layout using just the existing modules.
All of this sounds great, but object-oriented CSS does have some drawbacks.
For instance, in order for an element to be adaptable enough to be placed anywhere on the page, the name of its class should also be flexible. If you style a box and give it a class name of footer, and later on you decide to apply that style to a box in the sidebar, then the initial class name you gave it will be wrong — it’s not flexible enough. Thus, class names in style sheets that follow object-oriented CSS can sometimes be less content-driven or less semantic than we’d like.
Despite its drawbacks, object-oriented CSS has its value in certain situations. If we are working on a big website for which a small style sheet (small file size) and flexibility and maintainability are important, then following the principles of object-oriented CSS can bring huge improvements to our processes and huge savings to our company.
Once again, you don’t have to follow this methodology blindly in order to gain from its benefits.
Going back to the news company, let’s imagine you want to make a box that sits in the sidebar more prominent than other elements contained there. You might write the following CSS:
#sidebar .highlight {
background: #efefef;
border: 1px solid #000;
box-shadow: 0 0 .5em #000;
}

#sidebar .highlight > h1 {
font-weight: bold;
}
What’s so wrong with the CSS above? If you are following object-oriented CSS, then you shouldn’t restrict a style that you will probably reuse in the main content area by confining it to the #sidebar container. In our example, though, we’ll happily keep the descendent element selector in the second rule (object-oriented CSS advises against child elements being dependent on parent elements, but you can draw the line on how closely to adhere to a particular technique as you see fit, and that’s the beauty of it!).
So much more could be said about this technique. It is indeed well worth looking into, all bias aside. You will read things that you probably don’t consider good practice, but remember: context is important, and your expertise equips you to adopt the principles that will help you in your situation.

Step Into Programming

The command line is a boundary between designers and developers that we designers usually don’t want to cross. Instructions on opening the terminal can be quite intimidating for designers if they’re not familiar with it. I confess I’m guilty of steering clear of it most of the time.
But consider this: we keep talking about how we should learn and draw inspiration from the past — from print design, for example. We claim with pride to have deep knowledge of typography, color theory, layout, grids and scales. We see it as a requirement for anyone who calls themselves a professional designer.
This knowledge should be extended to encompass programming, at least at a basic level. After all, it is what powers our most precious creations.
Instead of being inspired by architecture — by its teachings, its processes and its vocabulary — why don’t we get inspired by the architect’s example, by what they have to learn? Why not be inspired by the multitude of disciplines that an architect has to know intimately in order to be a great professional?
Radiant City Model Lac Leman

How many disciplines can you spot in this model? (Image: n fiore)
Why not start now? Open Terminal. (Go on, don’t be scared. It’s only there to help.) Now type the following:
$ gem install sass
(You don’t have to write the $; it’s just there to indicate this is a Terminal command.) There, you’ve just installed Sass (which we’ll cover shortly). That didn’t hurt, did it?
If you’re working on a Sass file, you could type the following simple command to make the original Sass-formatted file automatically update the corresponding normal CSS file whenever changes are made:
$ sass --watch style.scss:style.css

The List Goes On

There are several more tools you can keep in your arsenal that can move CSS another step into the future.
Quite a few Web designers and CSS authors are becoming enamoured with CSS preprocessors such as Sass, which make it possible to extend CSS’ syntax to include, for example, variables, complex calculations and nested selectors. Not only do they enable you to use functionality not yet available in normal CSS, but you can increase efficiency by automating tasks such as updating a frequently used color on a file-wide basis, rather than having to change each instance by hand.
Sass homepage

The increasingly popular Sass.
And with all the improvements brought by CSS3, even pure and simple CSS is becoming more powerful, enabling us to create very complex layouts and animations more easily and with fewer lines of code.
The list presented here is a short one, and I’d be happy to know what techniques you apply in your own projects to make the process of writing CSS more fluid and to make your style sheets smaller and more easily maintainable and sharable.

This Is Just The Beginning

Eric Meyer says, “You can’t identify a code craftsman by whether or not they use this framework or that language. You can identify them by how they decide which framework or language to use, or not use, in a given situation.” This statement couldn’t be closer to the truth. Discussing tools without context is pointless.
Saying that something is good or bad should be done in context. By deciding that a certain technique is fundamentally flawed because someone once said so, and holding to that opinion throughout your career without ever challenging it, is not what being creative is about.
In his Critique of Pure Reason, Kant says, “Have the courage to use your own intelligence.” I would ask you to set your biases aside when when speaking about tools, techniques and processes with other designers and developers who write CSS. Don’t view different opinions as a sign of ignorance or poor craftsmanship.
Certainly, we may question certain aspects of our jobs as Web designers, and whether to be more liberal in letting automation into our processes is just one of them — but one I’m particularly interested in.
I know and work alongside very intelligent and creative programmers. These are people who understand systems so complex that my brain shrinks every time it tries to even begin to understand them. These are also people who are proud of their work, true craftsmen of their times. I find it quite interesting how these two groups (CSS authors and programmers) work on the same products but in such different ways, how they both work with code but with such contrasting values.
There is a place for carefully handwritten, handmade, perfect CSS — I take great pleasure in this myself. But there is also a place for the study and perfection of a more mechanized approach to style sheets. Both can certainly run side by side.
What are your views on this subject? Have you been trying to automate any part of your CSS writing? Do you think style sheets should always be handcrafted?
Comments (0)

Adventures In The Third Dimension: CSS 3D Transforms
by kamran.hanfi in

Adventures In The Third Dimension: CSS 3D Transforms


Back in 2009, the WebKit development team proposed a new extension to CSS that would allow Web page elements to be displayed and transformed on a three-dimensional plane. This proposal was called 3D Transforms, and it was soon implemented in Safari for Mac and iOS. About a year later, support followed for Chrome, and early in 2011, for Android. Outside of WebKit, however, none of the other browser makers seemed to show much enthusiasm for it, so it’s remained a fairly niche and underused feature.
That’s set to change, though, as the Firefox and Internet Explorer teams have decided to join the party by implementing 3D Transforms in pre-release versions of their browsers. So, if all goes according to plan, we’ll see them in IE 10 and a near-future version of Firefox (possibly 10 or 11, but that’s not confirmed yet), both of which are slated for release sometime this year.
That being the case, this is an ideal time to get ahead of the curve and start learning about the possibilities and potential of adding an extra dimension to your Web pages. This article aims to help you do just that, by taking you on a flying tour of the 3D Transforms syntax.
Please bear in mind that in order to see the examples in this article, you’ll need a browser that supports 3D Transforms; as I write this, that’s Safari, Chrome, IE 10 Platform Preview or Firefox Aurora.

The Third Dimension

On the Web, we’re accustomed to working in two dimensions: all elements have width and height, and we move them around the screen horizontally (left to right) and vertically (top to bottom). The move to a third dimension can be thought of as adding depth to elements, and adding movement towards and away from you (the viewer). Think about 3D films in which objects are constantly thrust out of the screen towards you in an attempt to demonstrate the possibilities of the extra depth.
To use 3D Transforms in CSS, you’ll need to know about axes (that’s the plural of axis, not the plural of axe). If you already know about working in three dimensions or remember using axes in math class at school, you can skip the next section. For everyone else, here is…

A Quick Primer On Axes

I just mentioned that on the 2-D Web, we move elements around horizontally and vertically. Each of these directions is called an axis: the horizontal line is known as the x-axis, and the vertical line is the y-axis. If we think of the top-left corner of an element as our origin (i.e. the point from which movement is measured), a movement to the left is a negative movement along the x-axis, and a move to the right is a positive movement along the x-axis. The same goes for moving an element up (negative on the y-axis) and down (positive on the y-axis).
The third dimension is known as the z-axis and, as I said, can be thought of as towards or away from you; a negative movement along the z-axis is away from you, and a positive movement is towards you.
screenshot

Showing the three axes: x (left-right), y (up-down) and z (away-towards).
If you’ve read all of this talk of axes and negative movements and you’re rubbing your eyes and blinking in disbelief and misunderstanding, don’t worry: it will all become clear when you get stuck in the code. Come back and read this again after a few examples and it should all be clear.

Transformation Functions

The various transformations are all applied with a single CSS property: transform — yes, the same property that’s used for 2-D CSS Transforms. At the moment, this property is still considered experimental, so remember to use all of the browser prefixes, like so:
div {
-moz-transform: foo;
-ms-transform: foo;
-o-transform: foo;
-webkit-transform: foo;
}
Note that Opera doesn’t currently have an implementation of 3D Transforms, but I’m including it here because work is apparently underway. For the sake of clarity, in the examples throughout this article, I’ll use only non-prefixed properties, but remember to include all of the prefixed ones in your own code.
Anyway, the transform property accepts a range of functions as values, each of which applies a different transformation. If you’ve used 2-D CSS Transforms, then you’ll already know many of these functions because they are quite similar (or, in some cases, the same). Here are all of the 3D functions:
  • matrix3d
  • perspective
  • rotateX, rotateY, rotateZ, rotate3d
  • scaleX, scaleY, scaleZ, scale3d
  • translateX, translateY, translateZ, translate3d
Now, matrix3d definitely sounds the coolest, but it’s so unbelievably complex (it takes 16 values!) that there’s no way I could cover it in this article. So, let’s put that aside and take a quick look at the others.

Rotation

To explain what this does, I’ll have to ask you to do a little mental exercise (which will come in useful later in the article, too). Imagine a sheet of card with a string running through the middle that fixes it in place. By taking the top corners in your fingers, you can move the card up and down, left and right, and forwards and backwards, pivoting around the string. This is what the rotate() function does. The individual functions rotateX(), rotateY() and rotateZ() take a deg (i.e. degree) value and move the element around its point of origin (where the string passes through it) by that much.
Have a look at our first example (a screenshot is shown below in case you don’t have access to a supported browser). Here we’ve rotated each of the elements 45° around a different axis (in order: x, y, z), so you can see the effect of each. The semi-translucent red box shows the original position of the element, and if you mouse over each, you’ll see the transformations removed (I’ve used this convention in all of the examples in this article).
screenshot

Each element is rotated 45° around a different axis: x (left), y (center) and z (right).
There is a rotate3d() function as well, but it’s too complex to explain in a brief article like this one, so we’ll skip it.

Translation

This is really just a fancy way of saying “movement.” The functions translateX(), translateY() and translateZ() each take a length value, which moves the element by that distance along the given axis. So, translateX(2em) would move the element 2 ems to the right, and translateZ(-10px) would move the element 10 pixels away from the viewer. There’s also a shorthand function, translate3d(), which takes three values in order, one for each axis, like so: translate3d(x, y, z).
In our second example, we’ve translated each of the elements by -20 pixels along a different axis (in order: x, y, z).
screenshot

Each element is translated by -20 pixels along a different axis: x (left), y (center) and z (right).
Note that translation of an element is similar to relative positioning, in that it doesn’t affect the document’s flow. The translated element will keep its position in the flow and will only appear to have moved, meaning it might cover or show through surrounding elements.

Scaling

This just means making bigger or smaller. The three functions scaleX(), scaleY() and scaleZ() each take a unitless number value, which is used as a multiplier. For scaleX() and scaleY(), this is applied directly to the width and height; for example, applying scaleY(1.5) to an element with a height of 100 pixels would transform it to 150 pixels high, and applying scaleX(0.75) to an element with a width of 100 pixels would transform it to 75 pixels wide.
The scaleZ() function behaves slightly differently. Transformed elements don’t actually have any depth to increase or decrease; what we’re doing is more like moving a 2-D object around in 3D space. Instead, the value given to scaleZ() acts as a multiplier for the translateZ() function that I explained in the last section. So, applying both translateZ(10px) and scaleZ(2) would translate an element 20 pixels along the z-axis.
There’s also a shorthand property, scale3d(), which, like translate3d(), takes three values, one for each of the individual functions: scale3d(x,y,z). So, in the following code example, the same transformation applies to both of the elements:
.e1 {
transform: scaleX(1.5) scaleY(1.5) scaleZ(0.75);
}

.e2 {
transform: scale3d(1.5,1.5,0.75);
}

Perspective

The perspective() function is quite simple, but what it actually does is quite complex. The function takes a single value, which is a length unit greater than 0 (zero). Explaining this is a little complicated; the length is like a distance between you and the object that you’re viewing (a tutorial on Eleqtriq has a more technical explanation and diagram). For our purposes, you just need to know that the lower the number, the more extreme the 3D effect will appear; any value below 200px, for example, will make the transformation appear very exaggerated, and any value of 1000px or more will seem to have no effect at all.
In our third example, we have three transformed elements, each with a different value for the perspective() function: 25px, 50px and 200px, respectively. Although the difference between the three is very discernible, it’s even clearer when you mouse over to see the transformations removed.
screenshot

Each element has a different value for the perspective() function: 25px (left), 50px (center) and 200px (right).
Note that I’ve transformed the parent elements (equally) so that we can see the degree of perspective more clearly; sometimes the difference in perspective values can be imperceptible.

Other Properties

In addition to transform, you’ll need to know about a few other important properties.

transform-style

If you’ll be applying 3D transformations to the children of an already transformed element, then you’ll need to use this property with the value preserve-3d (the alternative, and default, is flat). This means that the child elements will appear on their own planes; without it, they would appear flat in front of their parent.
Our fourth example clearly illustrates the difference; the element on the left has the flat value, and on the right, preserve-3d.
screenshot

The element on the left has a transform-style value of flat, and the one on the right has a value of preserve-3d.
Something else to note is that if you are transforming child elements, the parent must not have an overflow value of hidden; this would also force the children into appearing on the same plane.

transform-origin

As mentioned, when you apply a transformation to an element, the change is applied around a point directly in the horizontal and vertical middle — like the imaginary piece of string we saw in the earlier illustration. Using transform-origin, you can change this to any point in the element. Acceptable values are pairs of lengths, percentages or positional keywords (top, right, etc.). For example:
div {
transform-origin: right top;
}
In our fifth example, you can see the same transformations applied to two elements, each of which has a different transform-origin value.
screenshot

The element on the left has a transform-origin value of center center, and the one on the right has a value of right top.
The difference is clearly visible, but even more obvious if you pass the mouse over to see the transformation removed.

backface-visibility

Depending on which transformation functions you apply, sometimes you will move an element around until its front (or “face”) is angled away from you. When this happens, the default behavior is for the element to be shown in reverse; but if you use backface-visibility with a value of hidden, you’ll see nothing instead, not even a background color.

perspective and perspective-origin

We introduced the perspective() function earlier, but the perspective property takes the same values; the difference is that the property applies only to the children of the element that it’s used on, not the element itself.
The perspective-origin property changes the angle from which you view the element that’s being transformed. Like transform-origin, it accepts lengths, percentages or positional keywords, and the default position is the horizontal and vertical middle. The effect of changing the origin will be more pronounced the lower the perspective value is.

Conclusion

By necessity, we’ve flown through the intricacies of the 3D transformations syntax, but hopefully I’ve whetted your appetite to try it out yourself. With a certain amount of care for older browser versions, you can implement these properties in your own designs right now. If you don’t believe me, compare the list of “More adventures” on The Feed website that I built last year in a browser that supports 3D transforms and in one that doesn’t, and you’ll see what I mean.
Some of the concepts used in 3D transforms can be quite daunting, but experimentation will soon make them clear to you in practice, so get ahold of a browser that supports them and start making some cool stuff. But please, be responsible: not everything on the Web needs to be in three dimensions!
Comments (0)

Resolution Independence With SVG
by kamran.hanfi in



Resolution Independence With SVG


In this article, we’ll look at Scalable Vector Graphics (SVG), one of the most underused technologies in website development today.
Before diving into an example, let’s consider the state of the Web at present and where it is going. Website design has found new vigor in recent years, with the evolving technique of responsive design. And for good reason: essentially, responsive website design moves us away from the fixed-width pages we’ve grown accustomed to, replacing them with shape-shifting layouts and intelligent reflowing of content. Add to that a thoughtful content strategy and mobile-first approach, and we’re starting to offer an experience that adapts across devices and browsers to suit the user’s context.
When we look at the breadth of Web-enabled devices, responsive design is sure to provide a better user experience. Scrolling horizontally, panning and zooming the viewport have their place in user interface design, but forcing the user to do these things just to navigate a website quickly becomes tedious. Fitting the website to the viewport is about more than just layout: it’s also about resolution. In this article, I’ll demonstrate why SVG is a perfect addition to future-friendly Web development.

Introducing SVG

SVG offers a truly resolution-independent technique for presenting graphics on the Web. SVG is a vector graphics format that uses XML to define basic properties such as paths, shapes, fonts and colors, and more advanced features such as gradients, filters, scripting and animation. Create the file once and use it anywhere, at any scale and resolution.
Consider the use cases: UI and navigation icons, vector-style illustrations, patterns and repeating backgrounds. For all of these, a scalable graphic is the perfect solution from a visual standpoint, and yet fixed-resolution images are still the norm. In the example below, we’ll show you how to expand on a common development technique to take advantage of SVG.
Resolution independence with SVG

A Case Study: CSS Sprites

We all know about the CSS sprites technique. (If you don’t, then have a quick read through Sven Lennartz’ article. And Louis Lazaris points out its pros and cons.) In the example below, we’ll show how seamlessly SVG replaces normal raster images. If this technique is not for you, you can certainly imagine a whole array of similar situations in which to use SVG.
Vector icons play a big role in user interface design. Pictures express concepts with vivid clarity, whereas their textual counterparts might carry ambiguity. In UI design, where space is scarce, a simple illustrated icon could be greatly welcome.
I’ve mocked up the following example:
An icon based UI menu
I’ll be first to admit that this row of icons won’t win any design awards, but it will suffice for the sake of this article! Let’s look at the HTML:
<div class="actions">
<a class="a-share" href="#">Share</a>
<a class="a-print" href="#">Print</a>
<a class="a-tag" href="#">Tag</a>
<a class="a-delete" href="#">Delete</a>
</div>
I’ve kept the HTML to a minimum for clarity, but in practice you’d probably want to mark it up with an unordered list. And you’ll almost certainly want to replace those hashes with real URLs (even if JavaScript provides the functionality, having a fallback is nice). Let’s look at the CSS:
.actions {
display: block;
overflow: auto;
}

.actions a {
background-image: url('sprite.png');
background-repeat: no-repeat;
background-color: #ccc;
border-radius: 5px;
display: block;
float: left;
color: #444;
font-size: 16px;
font-weight: bold;
line-height: 20px;
text-decoration: none;
text-shadow: 0 -1px 2px #fff;
padding: 10px 20px 10px 40px;
margin-right: 5px;
}

.a-share { background-position: 10px 0; }
.a-print { background-position: 10px -40px; }
.a-tag { background-position: 10px -80px; }
.a-delete { background-position: 10px -120px; }
Note the fixed-pixel sizing and the PNG background, which we can see below framed in full Photoshop production glory:
A PNG sprite in Photoshop
This implementation of a CSS sprite is basic, and at today’s standard, it’s not good enough! How can we enhance this? First, let’s consider the following issues:
  1. We’ve rasterized the image at a very early stage. Even at full size, icons in which points sit between pixels, such as the one for “Print,” have blurred.
  2. If we zoom in, the image will blur or pixellate even more; there is no additional data to re-render the image at larger sizes.
  3. Everything has a fixed size, which is neither good for responsive design nor good for accessibility, because the browser’s default font size is ignored.
As you’ve probably guessed by now, we’ll show you how SVG solves these problems. But first, let’s reiterate each point thoroughly to understand the issues at large.

1. Rasterization

Devices such as modern smartphones have a very high pixel density; some already surpass the 300 pixels-per-inch (PPI) mark that is assumed to be the limit of the human eye’s ability to distinguish fine details. A pixel has no real-world equivalent in size until it sits on a screen of fixed dimension (say, 3.5 inches diagonally) and fixed resolution (say, 640 × 960 pixels). At this scale, text with a font size of 16 pixels would be incredibly small to the eye. For this reason, devices simply cannot translate 1 CSS pixel unit to 1 device pixel; instead, they double up. Thus, a 16-pixel font size actually takes over 32 pixels when rendered.
The same applies to images; but they are already rasterized, so doubling up the pixels has no benefit. In our example, each icon has been rasterized at around 25 × 25 pixels (the whole sprite being 30 × 160), so they cannot take advantage of the double pixel ratio. One solution is to use CSS media queries to detect the pixel ratio. This is already implemented in Webkit- and Gecko-based browsers.
To improve our example, we can add the following CSS declaration:
@media only screen and (-webkit-min-device-pixel-ratio: 2)  {
.actions a {
background-image: url('sprite@2x.png');
background-size: 30px 160px;
}
}
The alternate background image supplied in the code above has been saved at 60 × 320 pixels (i.e. double the original dimensions). The background-size property tells CSS to treat it smaller. Significantly, now the device has the additional data to render a better image (if capable).
This solution isn’t bad, but it doesn’t solve the problems we’ll run into in points 2 and 3 below. It also requires that we maintain multiple files of increasing size: a potential burden on bandwidth and a real hassle. For non-vector images, such as photography in JPG format, we can’t do much more than that.

2. Zooming

At their default size, our rasterized icons look acceptable, at least on low-pixel-density screens. However, should the user zoom in on the Web page, these little UI delights will degrade very quickly.
A PNG sprite zoomed in and blurred.
Zooming is a common action when users find a website too small for comfortable viewing. Or, to put it another way, websites that are designed too small are very common. There is really no “perfect” size, because almost everyone has at least some level of visual impairment, since our eyes inevitably deteriorate with age. Secondly, with the rapid increase in touchscreen devices, pinch-to-zoom has become the standard way to enlarge fixed-sized content designed for larger screens (i.e. much of the Web today).
We should develop websites in a way that minimizes the need for user input — that’s where responsive design comes in (see point 3 below) — but zooming is here to stay. There’s simply no way to provide pre-rasterized images for every level of zoom (in theory, an infinite scale). Scalable graphics are the solution, and we’ll show you how to enhance our example. But first, a related word on fixed sizing.

3. Fixed Sizes

Presenting page elements at fixed sizes forces many users to zoom, but it also disables a very useful browser feature. Users can set their preferred font size (the default in browsers is 16 pixels). By sizing everything in pixels, we override this preference. Sizing elements based on this default is much better, so that, if the text is bigger, everything adjusts to match. This essentially mimics the zooming effect but happens without the user having to manually do it on every visit. Ethan Marcotte has written a great article that explains relative font sizes.
Let’s re-implement our sprite example with a solution to these three issues.

A Scalable Implementation

Here is the HTML again. We don’t need to change anything here.
<div class="actions">
<a class="a-share" href="#">Share</a>
<a class="a-print" href="#">Print</a>
<a class="a-tag" href="#">Tag</a>
<a class="a-delete" href="#">Delete</a>
</div>
The updated CSS is where the magic happens:
body { font-size: 100%; }

.actions {
display: block;
overflow: auto;
}

.actions a {
font-size: 1em;
line-height: 1.25em;
padding: 0.625em 1.25em 0.625em 2.5em;
margin-right: 0.3125em;
border-radius: 0.3125em;
background-image: url('sprite.svg');
-webkit-background-size: 1.875em 10em;
-o-background-size: 1.875em 10em;
-moz-background-size: 1.875em 10em;
background-size: 1.875em 10em;
/* styles carried over from the original implementation */
background-repeat: no-repeat;
background-color: #ccc;
color: #444;
display: block;
float: left;
text-decoration: none;
text-shadow: 0 -1px 2px #fff;
}

.actions-em .a-share { background-position: 0.625em 0; }
.actions-em .a-print { background-position: 0.625em -2.5em; }
.actions-em .a-tag { background-position: 0.625em -5.0em; }
.actions-em .a-delete { background-position: 0.625em -7.5em; }
In this version, we’ve made the following changes:
  • The background-image is now an SVG file.
  • All sizes are based on the default of 16 pixels, or 1 em. If the user’s default is larger or smaller, then everything will scale relatively. (If you multiple each em size by 16, you’ll get the number of pixels used in our initial fixed-size example.)
  • The background-size is very important. By setting this in em units, we’re telling the browser to scale the sprite relative to everything else. You’ll notice that 1.875 × 10 em multiplied by 16 becomes 30 × 160 — the base size at which we produced the sprite in pixels.
  • The background-position of each sprited icon is also based on relative units.
Now that we’re using SVG and relative sizes, we have solved the three big issues highlighted above. A scalable graphic can be rasterized on demand to perfectly suit any device resolution and any zoom level. By using relative sizes, we can continue implementing a responsive design, minimizing as much as possible the need for the user to zoom. We’re also respecting the browser’s default font size, and enabling our design to adapt accordingly.
I actually produced the SVG sprite first and the PNG version from that. (I imported the SVG in Photoshop before exporting it as a PNG — Illustrator’s PNG export had very poor rasterization.) Below is the header in my SVG file. Notice the same 30 × 160 initial size.
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="30px" height="160px" viewBox="0 0 30 160" enable-background="new 0 0 30 160" xml:space="preserve">
You can see that the attributes for width and height are set in pixels (width="30px" height="160px") in the opening svg tag (as generated by Adobe Illustrator). This actually causes it to render early in Firefox, before the graphic has scaled to match the em sizes in background-size. Webkit-based browsers seem to scale the SVG perfectly, regardless. I’ve found that editing the SVG file to use em units in these two attributes fixes any rendering issues in Firefox.
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="30em" height="160em" viewBox="0 0 30 160" enable-background="new 0 0 30 160" xml:space="preserve">
I don’t know which browser actually implements this scaling correctly, but let it be noted that extra care is needed to ensure cross-browser perfection. Mozilla MDN has an excellent in-depth article, “Scaling of SVG Backgrounds,” which explores more practical examples. For more ideas, see Alex Walker’s article “A Farewell to CSS3 Gradients.”
Here’s a super-close screenshot showing the SVG sprite:
A close-up of a SVG sprite.
The sprite scales beautifully. (Sadly, the same can’t be said for my tacky text-shadow effect.)
It’s best to experience the joys of scalable graphics and relative sizing firsthand. I’ve uploaded a side-by-side live demo demonstrating a combination of all the techniques mentioned above.

Browser Support

At the start of this article, I said that SVG was underused. I believe that has generally been the case due to poor browser support. But things are different now! Browser support for SVG has blossomed over the last year to the point where implementing it is a viable use of development time.
According to the website When Can I Use?, support for SVG across multiple implementations is as follows (I’ve combined support for both CSS’ background-image and HTML’s img source — the most useful attributes):
  • Internet Explorer 9+
  • Firefox 4+
  • Chrome 4+
  • Safari 4+
  • Opera 9.5+
Mobile browser support is also pretty much across the board. If a workable fallback exists for older browsers, then SVG is a very viable solution.
For some of the new additions to Web standards, we can implement them safe in the knowledge that old browsers will simply ignore them and that they aren’t even required. We call this “progressive enhancement”: better browsers get a progressively better experience. SVG is slightly different, because for most practical purposes, it simply replaces other images in CSS backgrounds and HTML elements. The image format — be it SVG, PNG, JPG or GIF — is either supported or it isn’t. We can’t simply follow the practice of progressive enhancement here, because an image failing to render is not an acceptable experience.

Browser Sniffing or Feature Detection?

We could make an educated guess and say that we need to worry only about users of Internet Explorer 6 to 8. In this case, the conditional comments technique for IE-only styles enable us to re-apply a second CSS background-image of a supported format such as PNG, instead of the default SVG background.
Browsing sniffing is always a dangerous game. While Internet Explorer tends to be the main offender, we can never assume it is the only one.
The safer and highly recommended option is to detect SVG support and use it only if it’s found. I suggest using Modernizr if you need to detect multiple features. Modernizr applies a class of svg to your root html element if detected (to which you can apply SVG as a background-image). If you’re using SVG as the source of an image element in HTML, then implementation is a little harder. You’ll have to write more JavaScript to find and replace all sources once support has been established.
The problem with these methods is that the browser will download the fallback image before SVG is detected — the only exception being the conditional comments technique for IE. Users will also likely see a flash of re-styled content when the source image changes. This shouldn’t be the case for long; but at least for now, these problems may be enough to hold you off on SVG usage.

File Size

In our sprite example, the raw SVG file was 2445 bytes. The PNG version was only 1064 bytes, and the double-sized PNG for double-pixel ratio devices was 1932 bytes. On first appearance, the vector file loses on all accounts, but for larger images, the raster version more quickly escalates in size.
SVG files are also human-readable due to being in XML format. They generally comprise a very limited range of characters, which means they can be heavily Gzip-compressed when sent over HTTP. This means that the actual download size is many times smaller than the raw file — easily beyond 30%, probably a lot more. Raster image formats such as PNG and JPG are already compressed to their fullest extent.

Performance

Rendering performance is a concern with SVG, especially on mobile devices, whose hardware is limited. Raster images can be rendered pixel for pixel after decompression and de-encoding. Vector graphics need to be rasterized at a specific resolution every time they’re viewed.
SVG has consistently proved slower than Canvas as a platform for animating vector graphics; but our concern here is basic rendering, not manipulation a thousand times per second, and if that is possible, then simple rendering shouldn’t be a concern. The more intensive SVG features are things like clipping masks and filter effects. These are unnecessary for many practical purposes (like our sprite example), but, if required, the best way to check performance is by testing. A lot of Web development is supported in theory, but in practice results are far from perfect.

Alternative Methods

Hopefully you agree that SVG is extremely useful but not always the ideal solution to resolution independence. Ultimately, the trick is to avoid raster images while maintaining the scalability of visual styles. Below are a few more ideas to think about.

CSS3

You’ve probably already started combining CSS3 properties such as linear-gradient, text-shadow and box-shadow to create more complex styles. Web developer Lea Verou curates a CSS3 pattern gallery that shows off the impressive potential of gradients alone.
CSS3 gradient patterns
In his article “Mobile Web in High Resolution,” Brad Birdsall introduces a technique to maintain pixel perfection for high-resolution displays using the pixel-ratio property.
Then there are pure CSS “icons,” which Faruk Ateş rightly points out as being absolute “madness” — certainly so if you’re using CSS to create a logo! But you could argue the benefits of a small handful of very specific techniques, such as CSS triangles, as demoed by Chris Coyier.

Web Fonts

Dingbat Web fonts and look-a-like Unicode glyphs are two interesting alternatives for vector icons, both with accessibility and semantic challenges. Jon Hicks has a write-up of perhaps the best practice for this. SVG seems a more appropriate technique for icons, but both have an immediate visual impact at high resolutions — and we’ll be paying increasing attention to that in coming years.

Looking Forward

As you can see, SVG usage is very much a possibility, and browser support and performance will only improve in future. What’s important to note from this article is that we really should be building websites that are as resolution-independent as possible.
Consider the “one Web” philosophy and the vast range of devices we use to access it — there is no single user experience. The more we can do to stay device-agnostic, the better. Responsive website design addresses many of these needs and certainly provides many benefits. Using vector graphics may not be as apparent, but its little improvements really do make a difference.
With today’s level of support, many users can experience the beauty of crisp scalable graphics… or perhaps that’s the wrong way to think about it. Most users won’t say “Wow! Kudos on the vectors.” To our dismay, they probably wouldn’t even consider them (and certainly wouldn’t recognize the effort required to craft them). And that’s a good thing; each time we improve the user’s experience, we don’t necessarily need to make a song and dance about it. Letting things continue to grind away under-appreciated is OK. It’s the lack of such things that gets recognized and sniffed at. Raise the user’s expectations in visual aesthetics, and they’ll start to notice the websites that do look shoddy. If you don’t do it, others will.

Comments (0)

Progressive And Responsive Navigation
by kamran.hanfi in



Progressive And Responsive Navigation



Developing for the Web can be a difficult yet rewarding job. Given the number of browsers across the number of platforms, it can sometimes be a bit overwhelming. But if we start coding with a little forethought and apply the principles of progressive enhancement from the beginning and apply some responsive practices at the end, we can easily accommodate for less-capable browsers and reward those with modern browsers in both desktop and mobile environments.
screenshot

A Common Structure

Below is the HTML structure of a navigation menu created by WordPress. This unordered list is pretty common for content management systems and hand-coded websites alike. This will be the basis for our work.
Please note: Any ellipses (…) in the snippets below stand in for code that we have already covered. We have used them to shorten the code and highlight the parts that are relevant to that section.
<nav class="main-navigation">
<ul>
<li><a href="#home">Home</a></li>
<li>
<a href="#about">About Us</a>
<ul class="children">
<li><a href="#leadership">Leadership</a></li>
<li><a href="#involvement">Involvement</a></li>
<li><a href="#vision">Our Vision</a></li>
</ul>
</li>
<li><a href="#clients">Our Clients</a></li>
<li>
<a href="#support">Support</a>
<ul class="children">
<li><a href="#blog">Blog</a></li>
<li><a href="#downloads">Downloads</a></li>
<li><a href="#faq">FAQ</a></li>
</ul>
</li>
<li><a href="#contact">Contact Us</a></li>
</ul>
</nav>
Unstyled Navigation

Our navigation, unstyled.

Our Tools

  • CSS Reset
  • HTML5 elements
  • LESS CSS
  • jQuery

CSS Reset

Resetting our CSS styles is where we’ll start. Browsers have different default styles for the elements we’ll be using, so understanding this and getting all of the elements to look the same is important. In this example, since we’re using an unordered list, there will be default left padding, top and bottom margins, and a list-style. You can either deal with these individually or, if you’re project will include more than just this navigation, use a reset to clear all of the styles and start fresh. I prefer Eric Meyer’s Reset CSS, but there are a few others to choose from, listed below. Whichever you choose, make sure it accounts for the new HTML5 elements.

HTML5 and CSS3 Elements

We’ll be wrapping the menu in HTML5’s nav element, which is one HTML5 feature that we should be using right now. If you need more good reasons to use HTML5 in your daily work, such as accessibility, then read “Top 10 Reasons to Use HTML5 Right Now” over at Codrops.
CSS3 will give our menu the progressive feel we’re looking for. We can use nifty effects such as linear gradients, text and box shadows and rounded corners, while providing a reasonable appearance for browsers that are dragging their feet. You could also consider using something like CSS3 Pie in the process. This will give those lagging browsers most of the functionality they lack to display your CSS3 properties.

LESS CSS

To make our CSS more efficient, we’ll use LESS along with a class file to ease the difficulty of dealing with all of those browser prefixes. Other options, such as Sass and Compass, do effectively the same thing and might better fit your particular development environment. If you’re interested in learning more about LESS and how it compares to Sass, check out another article of mine, “An Introduction to LESS, and Comparison to Sass.”

jQuery

To make our navigation a little friendlier in small browsers, such as those on mobile devices, we’ll use JavaScript. Essentially, we will gather all of the elements in our navigation and reorganize them into a select form element. Then, when the user selects an option from the list, they will navigate to that page. Interaction with a select element is one of the easiest and best ways to handle navigation in a small window. The practice is pretty common as well, so the learning curve for users will be gentler.

Getting Started

After applying a reset, we get something like the following. You can see that the margins, padding and list styles have been cleared.
Reset navigation

Reset navigation

Child-Level Menus

For now, the child-level menus will only get in the way. The best thing to do is remove them from the equation and add them back in when it’s time to style them. To achieve this, we will apply position: relative to all of the list elements, and move the children off screen until they are needed.
.main-navigation {
li {
position: relative;
}
.children {
left: -999em;
position: absolute;
}
}
Applying left: -999em; position: absolute; will move the children to the left of the screen by a significant margin. This method is preferable to just using display: none because it is more accessible to screen readers.
Unstyled without children

Unstyled without children

Common Navigation Styles

Every navigation menu will probably have links in it. But these links are not like the links we see in the main body of the page, which are blue, underlined and distinguishable from the surrounding text. Rather, links in the navigation will stand alone, and their function will be obvious. That being said, the links in a nav element will probably have a few features of their own that distinguish them from typical anchor tags.
nav {
a {
color: inherit;
display: block;
text-decoration: none;
}
}
Thus, a link will inherit the color of the text assigned to the parent element, in this case nav. It will be set to display as a block-level element, because we want the clickable area to be large and we do not want underlining (because that would just look funny).
Navigation with more functional links

Navigation with more functional links
Please note: color: inherit is not supported in IE 6 or 7. If you need to support those browsers, then you will need to explicitly set the color that you want.

Lining Up

Getting the menu in line calls for the use of floats. Initially, we’ll float all of the elements in the nav element to the left. Later, we’ll undo this property for the child-level menus, along with a lot of the other styles that we’ll set along the way.
.main-navigation {
ul, li, a {
float: left;
}
…
}
Inline navigation

Inline navigation
Because every element in the nav element is now floated, the element itself will collapse as though it were empty. There are a few ways to deal with this. One is to also float the nav element itself, which will expand it to wrap around its contents. If need be, you can set it to width: 100% to fill any remaining space to the right. Or you could use Nicolas Gallagher’s “micro” clearfix solution, which essentially adds clear: both just before the closing of the nav element.
/* For modern browsers */
.cf:before,
.cf:after {
content:"";
display:table;
}
.cf:after {
clear:both;
}
/* For IE 6/7 (trigger hasLayout) */
.cf {
zoom:1;
}
Because we’re using LESS for our CSS, applying the clearfix to our main-navigation class without modifying the markup is very easy.
.main-navigation {
.cf;
…
}
We’ll see more of this, as well as a description of how this works, in the section titled “Rounded Corners and Gradients” below.

Styling

All righty. By now, you’re probably as tired of looking at an unstyled menu as I am. To start, we’ll build what looks like a block wall, and then chisel a nice menu out of it. We won’t serve the block wall to antiquated browsers, but it’s a good start anyway.

Background Color and Borders

.main-navigation {
font-size: 0.8em;

ul, li, a {
…
}
ul {
background: #eee;
border: 1px solid #ddd;
}
li {
…
border-right: 1px solid #ddd;
}
li:last-child {
border-right: none;
}
a {
height: 35px;
line-height: 35px;
margin: 3px;
padding: 0 15px;
}
.children {
…
}
}
In the code above, the text was just too big, so we shrunk it with font-size: 0.8em. This property is set on the main-navigation class, so it applies throughout the navigation. The top-level unordered list has a border: 1px solid #ddd property to break it out from the page. Each list item element is given a border-right: 1px solid #ddd; to separate it from each other. The li:last-child selector targets the last list item element in the unordered list, removing the right border because no item follows it.
The links within the navigation are given a background color and some left and right padding to add distinction and increase their clickable area. We’re fixing the height and line-height, instead of using top and bottom padding, so that we can predict more accurately where the child-level menus will be positioned relative to their shared parent list item.
Navigation resembling a block wall

Navigation resembling a block wall

Rounded Corners and Gradients

.main-navigation {
…
text-shadow: 0 1px 1px #fff;

ul {
border: 1px solid #ddd;
.border-radius();
.linear-gradient();
}
…
}

.border-radius (@radius: 5px) {
border-radius: @radius;
}
.linear-gradient (@start: #fff, @end: #ddd, @percent: 100%) {
background: @start; /* Old */
background: -moz-linear-gradient(top, @start 0%, @end @percent); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,@start), color-stop(@percent,@end)); /* Chrome, Safari 4+ */
background: -webkit-linear-gradient(top, @start 0%,@end @percent); /* Chrome 10+, Safari 5.1+ */
background: -o-linear-gradient(top, @start 0%,@end @percent); /* Opera 11.10+ */
background: -ms-linear-gradient(top, @start 0%,@end @percent); /* IE 10+ */
background: linear-gradient(top, @start 0%,@end @percent); /* W3C */
}
Above, we have created two new classes, border-radius and linear-gradient.
The border-radius class is actually what LESS developers refer to as a parametric mixin. Essentially, it’s like a class, but you can pass variables to it in case the default value isn’t exactly what you want. In this case, if 5 pixels isn’t what you want, you could reference the mixin as .border-radius(10px), and then it would use 10px instead of the original 5px. With the border-radius property, you could also pass it something like .border-radius(5px 0 0 5px), and it would apply the 5-pixel rounding to only the top-left and bottom-left corners. For more information and possibilities on border-radius, see “Border-Radius: Create Rounded Corners With CSS” at CSS3.info.
Another parametric mixin is linear-gradient. But with LESS, you can add classes to other selectors and it will apply the same styles—thus negating the need to modify the markup just to add another class (and, by extension, its styles) to an element. Both of the classes I’ve created cover the possibilities of browser syntax. Currently, Webkit has two different syntaxes, because for some reason the browser makers decided to ignore the specification when first implementing it and made up their own syntax. With Chrome 10 and Safari 5.1, they went back to the specification, joining the other browsers, and made things a little easier for us. However, if you still care about the previous versions, you’ll need to add their crazy syntax as well. We’ve also added a white text-shadow to the text in the navigation to give it a slightly beveled look.
Navigation with a gradient and rounded corners

With the two classes applied, you can see the slight gradient and the rounded corners.
Some browsers do not support CSS3 gradients. Yes, I’m looking at you, Internet Explorer 6, 7, 8 and 9. If you want to use something other than the filter syntax for gradients, you’ll have to wait for version 10. In the meantime, either you could use the filter syntax for IE (see the “For Internet Explorer” section of “Cross-Browser CSS Gradient”) and put them in an IE-specific style sheet, or you could use an image gradient. You could also just leave them without the gradient, but that’s not the point here.

Parent-Level Hover States

.main-navigation {
…
li:hover {
a {
.linear-gradient(#dfdfdf, #c0bebe, 100%);
}
.children {
…
a {
background: none;
}
}
}
…
}
The code above will trigger the hover state for anchor elements when the user hovers over their parent list item, rather than hovering over the anchors themselves. This way is preferable so that the anchor element maintains its hover state when the user is mousing over the child-level menu as well. Doing it this way does, however, create the need to reset the background color of anchor elements within the child-level menus. That’s the part you see within the children selector.
Hovering over the parent-level links

Hovering over the parent-level links

Displaying the Children

Bringing the children back onto the screen is easy enough. But before we get carried away, we need to clear out a few styles that are applied to all unordered lists, list items and anchors.
.main-navigation {
…
.children {
background: #fff;
left: -999em;
position: absolute;

li, a {
float: none;
}
li {
border-right: none;
}
}
}
The code above changes the background of the child-level menu to white, instead of the light gradient that we used in the parent-level menu. The next couple of lines remove the left float from the list items and anchors. We’ve also gotten rid of the right border that separates the list items in the parent-level menu.

The Hovering Box

.main-navigation {
…
.children {
background: #fff;
.box-shadow();
left: -999em;
margin-left: -65px;
position: absolute;
top: 30px;
width: 130px;
…
}
}

…
.box-shadow (@x: 0, @y: 5px, @blur: 5px, @spread: -5px, @color: #000) {
-moz-box-shadow: @x @y @blur @spread @color;
-webkit-box-shadow: @x @y @blur @spread @color;
box-shadow: @x @y @blur @spread @color;
}
…
We’ve added another parametric mixin to the equation. This one produces the box shadow, with all of its parameters as variables, and with the browser prefixes. We’ve borrowed the styles from .children to make the box appear to hover over the parent menu. To center the child underneath the parent element, we’ve set the left position to 50%, and set the left margin to the negative value of half the width of the child. In this case, the child level menu is set to 130 pixels wide, so we’ve set the left margin to -65 pixels.
Navigation w/child reset to hover style

Navigation with the child reset to hover style

Child-Level Hovers

.main-navigation {
…
.children {
…
a {
.border-radius(3px);
height: 30px;
line-height: 30px;
margin: 3px;
}
a:hover {
background: #dff2ff;
}
}
}
We’re using the parametric mixin that we created for the border-radius for the links in the children as well. Adding a 3-pixel margin and 3-pixel border radius to all of the anchor elements within the child menu will accent the 5-pixel border radius of the menu well. We’ve also adjusted the height and line height a little, because they just seemed too high. Finally, we gave the list items a nice soft-blue background color on hover.
Navigation w/child menus and their hover state

Navigation with child menus and their hover state

Responding to Mobile Browsers and Size Constraints

A lot of screen sizes and browsers are out there. The iPhone has had two resolutions. Up to the 3GS model, it was 480 × 320; since the iPhone 4, it has been 960 × 640. Android browsers run from 480 × 320 to 854 × 480. Android also has a lot of browsers to choose from. There are the usual Firefox and Opera, as well as a ton of browsers by small start-ups. You can get Opera for the iPhone, but since you can’t make it the default browser, you’re pretty much stuck with Safari. Given this variety, we’ll have to make some adjustments if we want our navigation to be useful on all devices and in all browsers.

Fitting the Content

Accomplishing this part is easy, but doing it will probably require adjusting our styles. But that’s why we’re here, isn’t it?
Currently, when we open the navigation demo in iOS, it looks like this:
Original navigation in iOS

Original navigation in iOS
This might not look too bad on a giant screen, and it might even be usable on the iPad, but you would struggle to use it on a phone. Zooming in might make it easier, but that’s not ideal. Optimizing for the device is preferable, and forcing the browser to use the available space is simple.
<meta name="viewport" content="width=device-width">
This alone makes a huge difference in the way the browser renders the page. And while the menu is not the prettiest it’s ever been, it is a lot more functional.
Navigation on iOS with the viewport adjusted

Navigation on iOS with the viewport adjusted

Media Queries

We can use media queries to adjust the styles based on the media in the browser. In this case, we’ll use the width of the page to change the look and feel of the navigation to make it more suitable to the available space. In this case, we’ll make the menu items more button-like.
@media only screen and (max-width: 640px) {
.main-navigation {
ul {
border: none;
background: none;
.border-radius(0);
}
li {
border-right: none;
}
a {
border: 1px solid #ddd;
.border-radius();
font-size: 1.2em;
height: auto;
.linear-gradient();
line-height: 1em;
padding: 15px;
}
}
}
In the code above, we’ve used a media query to target situations in which the user is only looking at a screen and in which the width of the window is a maximum of 640 pixels. In this scenario, we’ve removed the border, background and border radius from the unordered list, and applied those styles to the anchors themselves. We’ve also increased the font size of the anchors, cleared the height and line height, and adjusted the padding of the links to increase the clickable area.
Navigation adjusted for mobile display

Navigation adjusted for mobile
As you can see, the links look much friendlier in a mobile browser. They are, however, only half functional, because touch devices don’t have a hover state. This means that if you have child-level menus, as we do here, you’ll have to figure out a way to display them as well. You could replace the hover state with a touch event of some kind, or expand the children out onto the page. That would greatly increase the size of the navigation, though. The following method might be best.

Replacing the Menu in Mobile Browsers With JavaScript

$(function() {
/* Get the window's width, and check whether it is narrower than 480 pixels */
var windowWidth = $(window).width();
if (windowWidth <= 480) {

/* Clone our navigation */
var mainNavigation = $('nav.main-navigation').clone();

/* Replace unordered list with a "select" element to be populated with options, and create a variable to select our new empty option menu */
$('nav.main-navigation').html('<select class="menu"></select>');
var selectMenu = $('select.menu');

/* Navigate our nav clone for information needed to populate options */
$(mainNavigation).children('ul').children('li').each(function() {

/* Get top-level link and text */
var href = $(this).children('a').attr('href');
var text = $(this).children('a').text();

/* Append this option to our "select" */
$(selectMenu).append('<option value="'+href+'">'+text+'</option>');

/* Check for "children" and navigate for more options if they exist */
if ($(this).children('ul').length > 0) {
$(this).children('ul').children('li').each(function() {

/* Get child-level link and text */
var href2 = $(this).children('a').attr('href');
var text2 = $(this).children('a').text();

/* Append this option to our "select" */
$(selectMenu).append('<option value="'+href2+'">--- '+text2+'</option>');
});
}
});
}

/* When our select menu is changed, change the window location to match the value of the selected option. */
$(selectMenu).change(function() {
location = this.options[this.selectedIndex].value;
});
});
To summarize, first we’re checking whether the window is less than or equal to 480 pixels. To ensure an accurate reading on mobile devices, you can use a meta tag to scale the viewport accordingly:
<meta name="viewport" content="width=device-width">
We populate the first variable, windowWidth, with the value of the window’s width as defined by the given device. We can use this value to then check whether the width is narrower than a particular value. We’ve chosen 480 pixels here because, while we might want to use media queries to adjust the menu below 640 pixels, at a certain point the viewport would be just too small to justify the menu taking up all that space.
We then use jQuery to create a clone of our menu that we can later crawl to create our options. After we’ve done that, it’s safe to replace the unordered list with the select element that we’ll be using and then select it with jQuery.
In the largest part of the code, we’re crawling through the clone of our navigation. The selector used, $(mainNavigation).children('ul').children('li'), ensures that we go through only the uppermost list elements first. This is key to creating the nested appearance of the select menu. With it, we select the “direct” child-level unordered list elements and then their “direct” child-level list elements, and then parse through them.
Inside each of these “direct” descendants, we get the value of the href attribute and the text of the link, and we store them in variables to be inserted in their respective options. This is implemented by appending <option value="'+href+'">'+text+'&kt;/option> to our new select list.
While we’re in the top-level list item elements, we can check whether any child-level menus need to be parsed. The statement if ($(this).children('ul').length > 0) checks whether the count of the selector is greater than 0. If it is, that means child-level items need to be added. We can use that same selector, with a slight addition, to go through these elements and add them to our select list, $(this).children('ul').children('li').each().
The same parsing method applies to these elements, although they use different variables to store the values of the anchor tags, so as not to create conflicts. We have also prefixed text to the menu labels at this level, --- , to differentiate them from the other items.
Parsing through the menu in this method (nested) will create the parent-child relationship you would expect.
After the menu is created, a little more JavaScript will enable the select list to serve as navigation.
$(selectMenu).change(function() {
location = this.options[this.selectedIndex].value;
});
When the select menu is changed, a new option is selected, and the window location is changed to reflect the value of the option. That value comes from the href of the original anchor element.
The result is like so:
screenshot

The select menu in a desktop browser
Select menu on Android and iPhone

The select menu in Android and iPhone browsers
Given the increased clickable area of the native controls, the select menu is obviously much more user-friendly on mobile.
Comments (0)