Author Archive

Learning to Love the Boring Bits of CSS

Learning to Love the Boring Bits of CSS

The future of CSS gives us much to be excited about: On the one hand, there’s a whole range of new methods that are going to revolutionize the way we lay out pages on the web; on the other, there’s a new set of graphical effects that will allow on-the-fly filters and shaders. People love this stuff. Magazines and blogs are full of articles about them.

But if these tools are the show ponies of CSS, then I think it’s time we gave some love to the carthorses: the nuts-and-bolts components of the language, like selectors, units, and functions. I often call these the boring bits, although I say that only with great affection—an affection I think you should share.

To see why, let’s take a quick walk through some of the best of the new boring bits in CSS—the bits being worked on in half-lit laboratories away from the brilliance of the shiny new things in the shop windows. Some of these boring bits have been around for a while but deserve more recognition, while others are just starting to appear in browsers. But they’ll all be revolutionary to the way we work—albeit in humble, unassuming ways.

Relative size units

It’s likely that, as the smart and forward-thinking developer you are, you’ve worked with relative sizing—that is, em units or percentages—so you’ll know this problem: having to use a calculator to work out sizes because of inheritance. For example, it’s pretty common nowadays to set a base font size for your document and then use relative sizing to set your fonts across the rest of the page. In CSS, that probably looks something like this:

html { font-size: 10px; }
p { font-size: 1.4em; }

This is fine, and not a problem at all, until you have a child element you want to set at a different font size. For example, in markup like this:

The cat sat on the <span>mat</span>.

If you want that span to be at a smaller font size, say 1.2em, what do you have to do? Get your calculator out and work out 1.2 divided by 1.4, resulting in this:

p span { font-size: 0.85714em; }

And the problem’s not limited to using em either. If you’re building a fluid site using percentages, you’ll know that the percentage is relative to its container; so if you have an element that you want to be 40 percent of its parent, the length of which is 75 percent, then the width of the element must be set to 53.33333 percent.

Not ideal.

Root-relative lengths

To combat this font-sizing problem, we now have access to the rem (root em) unit. This is still a relative unit, but it’s always relative to a fixed base value, which is the font size of the root element of the document (in HTML, that’s always the html element). Presuming the same root font size of 10px that we used in the preceding example, the CSS rules required for the case at hand are:

p { font-size: 1.4rem; }
p span { font-size: 1.2rem; }

Now both rules are relative to the root font size, which is much more elegant and easy to work with, especially if you have a simple base like 10px or 12px. It’s sort of like going back to using px values again, only scalable.

This is one of the better-supported features in this article; it’s in all modern browsers including IE9, and only absent in Opera Mobile.

Viewport-relative lengths

If you think the rem unit is cool (I do), you’ll be delighted to know there’s also a new set of length units to combat the percentages problem. These work in a similar way to rem, except that they’re relative not to a user-defined value on the document root, but to the dimensions of the device viewport itself.

The two main units are vh and vw, which are relative to the height and width (respectively) of the viewport. Each takes a number as a value, and that number is equal to the same percentage of the specified length. As I still remember the lessons of screenwriting school, let me show that rather than trying to tell it:

div { height: 50vh; }

In this example, the height of the div would be exactly half of the height of the viewport; 1vh = 1 percent of the viewport height, so it stands to reason that 50vh = 50 percent of the viewport height.

As the viewport size changes, so does the value of the unit—but the advantage of this over percentages is that you don’t have to worry about containing elements: an item with a value of 10vw will always be that wide regardless of the width of its parent.

There’s also a vmin unit, which is equal to the smallest of either vh or vw, and it was recently announced that a corresponding vmax unit would be added to the spec (although it hasn’t been at the time of writing).

As of right now these are in IE9+, Chrome, and Safari 6.

Calculated values

When you’re working fluidly and/or responsively, you’ll doubtless come across the problem of mixing units—wanting to have a grid that’s sized in percentages but with fixed margins. For example:

div {
  margin: 0 20px;
  width: 33%; 
}

If your layout only uses padding and border, then you can use box-sizing to help you get around that, but it won’t help you with margins. A better, more flexible approach is to use the calc() value function, which lets you perform mathematical operations with different units, such as:

div {
  margin: 0 20px;
  width: calc(33% - 40px);
}

You’re not limited to using it only on width; you can use it anywhere length values are permitted—and if you want to go really deep down the rabbit hole, you can also use calc() inside calc().

IE9+ has this unprefixed (!), Firefox has it with the -moz- prefix (which should be unprefixed in release 16 or 17), and Chrome and Safari have implemented it with the -webkit- prefix. It doesn't seem to be in mobile WebKit yet, however.

Load a subset of characters

Snappy performance has always been important, but the broad range of mobile devices on the market now—each bringing great variability and uncertainty in connection speed—makes it perhaps even more so. One way to speed up page loading is to keep external file sizes down, which makes a new property for @font-face that aids in doing just that a very welcome addition.

The property in question is unicode-range, and it takes as a value a range of unicode character references. When pulling in external assets, only those specified characters are loaded from the font file, instead of the complete set. This code demonstrates how to load only three characters from the file foo.ttf:

@font-face {
  font-family: foo;
  src: url('foo.ttf');
  unicode-range: U+31-33;
}

This is especially useful if you’re using font icons and only want to show a subset on a given page. In one test I ran, using unicode-range shaved an average 0.85 seconds from the loading time of a font file, which is not insubstantial. Of course, your own mileage may vary.

This property is currently implemented in IE9+ and WebKit browsers like Chrome and Safari.

New pseudo-classes

Units and values are all well and good, but it’s selectors and pseudo-classes that I get particularly excited about. Coming up with a clever selector pattern, even though it’s hidden away where only a hardy few may ever see it, makes me feel like a craftsman. To paraphrase Steve Jobs’ father: you should make the back of the fence look as good as the front even if no one else knows you’ve done it—because you’ll know.

When I first used :nth-of-type() it was a revelation, like I had kicked down the doors of perception. OK, I’m exaggerating a little. But there are a couple of new CSS pseudo-classes that are really worth getting enthused about.

The negation pseudo-class

You probably won’t realize quite how useful the :not() pseudo-class is until you try it. The argument provided to :not() is a simple selector—no compounds. When a list of subjects is being made by a selector that includes :not(), any elements matching the argument will be excluded from that list. I know, that sounds complicated to me, too. But it’s actually quite simple.

Imagine this: you have an item list and you want to apply a rule to all its odd-numbered items, but never the last one in the list. At the moment you’d have to do something like this:

li { color: #00F; }
li:nth-child(odd) { color: #F00; }
li:last-child { color: #00F; } 

With the negation pseudo-class you can exclude the last item from the rule using :last-child as the argument, thus reducing the number of rules by one and making the code a little easier to manage:

li { color: #00F; }
li:nth-child(odd):not(:last-child) { color: #F00; }

It’s nothing groundbreaking, and as I’ve shown already you can work without it—but it’s quite useful. I had the opportunity to use it on a project built with embedded WebKit, and it proved its worth consistently. It’s honestly one of my favorite pseudo-classes.

That’s right, I have favorite pseudo-classes.

This is the most widely implemented of all the features in this article; it’s in IE9+ and all modern browsers, unprefixed. And if you’re familiar with jQuery, you may already be used to using this—it’s been in there since version 1.0, along with the similar not() method.

The matches-any pseudo-class

The :matches() pseudo-class accepts as an argument a simple selector, a compound selector, a comma separated list, or any combination of those items. Great! But what does it do?

It’s most useful for cutting the cruft of multiple selectors. As a use case, imagine you have a bunch of p elements in different containers but you only want to select a few of them; perhaps the style rule you write would look something like this:

.home header p,
.home footer p,
.home aside p {
  color: #F00;
}

With :matches(), you can shorten that considerably by finding the commonalities in the selectors; in our example here all have .home at the start and end in p, so we can use :matches() to aggregate all of the elements in between those. Confusing? Here’s what it looks like:

.home :matches(header,footer,aside) p { color: #F00; }

This is actually part of CSS4 (CSS Selectors Level 4, to be precise), and in the same spec it mentions that you’ll also be able to use the same syntax—comma-separated compound selectors—in future versions of :not(). Exciting!

Today, :matches() is in Chrome and Safari with the -webkit- prefix, and in Firefox under its old name, :any(), with the -moz- prefix.

Do you love the carthorse yet?

The best thing about all the new features in this article is that they solve real-world problems, from the small but annoying repetition of selectors to the new and ongoing challenges of building high-performance responsive sites. In fact, I can imagine using every single one of these features on a regular basis.

New features like filters may have higher visibility, but you’re far more likely to find the ones presented here useful on every one of your builds.

Each of them will make your professional life a little easier while expanding the possibility space of what you can achieve—and there’s nothing boring about that.

Translations:
Italian


RSS readers: Don't forget to join the discussion!


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 3-D 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 3-D 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 3-D Transforms syntax.

Please bear in mind that in order to see the examples in this article, you’ll need a browser that supports 3-D 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 3-D 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 3-D 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 3-D 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 3-D 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 3-D 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 whole number greater than 0 (zero). Explaining this is a little complicated; the number 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 3-D effect will appear; any value below 200 will make the transformation appear very exaggerated, and any value of 1000 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: 25, 50 and 200, 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: 25 (left), 50 (center) and 200 (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 3-D 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 3-D 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 3-D transforms and in one that doesn’t, and you’ll see what I mean.

Some of the concepts used in 3-D 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!

Further Reading and Resources

  • The Bright (Near) Future of CSS
    Eric Meyer’s comprehensive article on CSS3, covering CSS3 3D Transforms as well.
  • 3D Transforms, Westciv
    This tool lets you play around with different transformation values and shows you the result in real time.
  • “CSS3 3D Transforms,â€� W3C
    The CSS 3D Transforms module is the full specification, although it is very dry and technical.
  • “20 Stunning Examples of CSS 3D Transforms,â€� Paul Hayes
    See what you can build when you master 3-D Transforms.
  • The Book of CSS3, Peter Gasston
    My book contains much more detail about all of the functions that I’ve covered in this article, as well as the ones I had to leave out.

(al)


© Peter Gasston for Smashing Magazine, 2012.


  •   
  • Copyright © 1996-2010 BlogmyQuery - BMQ. All rights reserved.
    iDream theme by Templates Next | Powered by WordPress