Category Archives: Image

CSS Lint open sourced

Nicholas Zakas and I spoke at Velocity a few minutes ago. First we talked about CSS 3 and it’s impact on performance, then we demoed and open sourced CSS Lint! I really couldn’t be more excited (or relieved, I was super duper nervous before this presentation).

CSS Lint is a tool to help point out problems with your CSS code. It does basic syntax checking as well as applying a set of rules to the code that look for problematic patterns or signs of inefficiency. The rules are all pluggable, so you can easily write your own or omit ones you don’t want.

Rules currently tested

  • Parsing errors should be fixed
  • Don’t use adjoining classes
  • Remove empty rules
  • Use correct properties for a display
  • Don’t use too many floats
  • Don’t use too many web fonts
  • Don’t use too may font-size declarations
  • Don’t use IDs in selectors
  • Don’t qualify headings
  • Heading elements should have a consistent appearance across a site.
  • Heading styles should only be defined once
  • Be careful using width: 100%
  • Zero values don’t need units
  • Vendor prefixed properties should also have the standard
  • CSS gradients require all browser prefixes
  • Avoid selectors that look like regular expressions
  • Beware of broken box models

(We’ll allow you to turn off rules that hurt your feelings soon!)


Many people have expressed an interest in contributing to the CSS Lint project. We were waiting to have a solid plugable architecture and API before taking contributions. The exciting news is that we are now ready! There are several ways you can contribute:

  1. If you are comfortable with CSS, submit rule ideas. You must provide the rule name, a human readable explanation, browsers affected, and a test case.
  2. If you are comfortable in JavaScript, fork the github project, code up a rule, and submit a pull request. You’ll need to provide all the same documentation requsted in item 1.
  3. If you are comfortable with Node, test out the command line version, submit feature requests.

CSS Lint for Node.js

If you’d like a command line version of CSS Lint, you can install CSS Lint for Node.js using npm using the following:

sudo npm install -g csslint

Once installed, you can pass in any number of CSS files or directories containing CSS files to see the results. For example:

csslint test.css dir_of_css/ test2.css

You’ll receive the same errors and warnings as you would with the web interface.

Guest on The Big Web Show

me on the big web show with zeldman and benjamin

This week I had the good fortune to spend an hour talking with Jeffrey Zeldman and Dan Benjamin about all things CSS on The Big Web Show. It was lively and fun despite my cell phone making weird noises during the podcast. (Ooops, sorry!)

We talked about progressive enhancement, carpentry, testing, rounded corners, oocss, performance, working on big sites, and being a girl on the internets. If you missed the live show, you can check out the video podcast. I was super-duper-over-the-top nervous about the show, but I’ve heard that I didn’t come off like a total dweeb. ;)

Top 5 Mistakes of Massive CSS

Last week, Stoyan Stefanov and I spoke at Velocity Conference about optimizing massive CSS. We talked about our experiences optimizing large-scale sites like Facebook and Yahoo!, and we discussed our findings regarding the CSS efficiency of the Alexa Top 1000 websites.

Velocity was kind enough to share videos of the session:

What is the state of the internet regarding CSS performance? Kind of sad. We aren’t getting a lot of the basics right, and when we look at the more advanced techniques, there are some spectacular examples of what-not-to-do. Why do we care about CSS performance? As Stoyan talks about in the beginning of the video, it blocks progressive rendering and it is very difficult to auto-minify.

The Basics

These basic rules, made famous by YSlow, have been around for a long time, and yet our data showed that many sites in the Alexa Top 1000 are still not employing the most basic techniques.

  • 42% Don’t GZIP CSS
  • 44% Have more than 2 CSS external files
  • 56% Serve CSS with cookies (yummy to eat, bad for static content)
  • 62% Don’t minify (check out the YUI Compressor!)
  • 21% Have greater than 100K of CSS

CSS Weight for the Alexa Top 1000 Sites

More Advanced Techniques

I talked about these more advanced tests for the first time at Velocity. Here is how the top 1000 sites stack up and some recommendations for reasonable results.

Occurrences in one page
Declaration Max Percentage too many
> 10
Percentage sites *way* too many
> 100
float 733 56% 13% If you have a good nestable grids system, you shouldn’t need many floats. The worst offender in the Alexa Top 1000 sites declared the float property more than 700 times! Aim for less than 10.
h1-6 511 56% 9% There are only so many usable font sizes on the web. Below 10px in most fonts is legible only by mice and few sites use really large typography as a design element. Imagine that a site chooses to use 24px as their max. That leaves 14 different sizes, however, we need to divide that number by two because most users can’t see subtle differences like a 1px change in font size. That leaves seven different heading sizes, which means 56% of sites in the Alexa top 1000 have too many heading declarations.
margin: 0 518 64% 14% Different browsers have different default stylesheets. These stylesheets define how elements should look if you haven’t chosen an alternate style. It is important to get all browsers to the same starting point because it eliminates bugs and time wasted testing simple browser compatibility issues. This is should be accomplished using a reset stylesheet such as the one included in YUI. When a reset stylesheet isn’t used, margin zero tends to be sprinkled throughout the stylesheet as developers try to cope with browser differences in the absense of an abstracted solution. Setting the default margins to zero is the most basic job of a reset stylesheet, which means that 64% of the Alexa Top 1000 sites could benefit from including reset.css.
padding: 0 510 62% 10% Excessive declarations of padding zero are similar to margins (see the above description). The worse offender in this case declared padding zero 510 times.
font-size 889 78% 23% Headings (h1-6) often get hidden in class names, which can disguise typography efficiency issues. It is helpful to grep "font-size" to get an idea how many hidden headings exist on the site. The same rules apply to font-size that were explained under h1-6, so in fact the problem is much worse than our initial estimate. These figures mean that 78% of the Alexa Top 1000 sites have excessive heading declarations when we consider hidden headings. In addition, 22% of sites may not be getting the SEO benefits of properly using heading elements.
!important 526 12%* Important overrides all other declarations specificity, so it can be dangerous. If used correctly, only on leaf nodes, it can be a powerful tool for creating typography and spacing mixins that stand outside of the normal cascade. On the other hand, excessive use of important is a sure indication of specificity wars. Specificity wars are what happens when developers start trying to beat each others specificity, rather than having a real solid architecture and code standards. Eventually, like the worst offender in this case with 526 important properties, you can end up in a case where nearly every property is marked important. This means that 12% of the Alexa Top 1000 Sites probably has an internal specificity war in it’s web team.

* >50

Happy perf optimizing!

The media object saves hundreds of lines of code

What is the internet made of? At least the UI layer is mainly composed of media blocks. I talked about the Facebook stream story before, and all the tiny objects of which it is composed. For the most part, the stream story is made up of the media object repeated over and over.

The media object is an image to the left, with descriptive content to the right, like this Facebook story:

image to the left, descriptive content to the right

The media object

The content area on the right can contain any other objects. In this case, it contains text, but we could put lists, grids, or even other media objects inside. As we’ve seen before, there are actually many different versions of the media block on the Facebook website (and on most websites). These five are just a few examples of the way this object might be used:

Variations on the media object

Sometimes the image is a tiny icon, a large video, or an avatar, but it is the same basic object. When I’m building a new object, the first thing I do is to figure out which parts are reusable components, and define what I know and do not know about them.

what do we know?

  • Can be nested
  • Optional right button
  • Must clearfix

What have we decided *not* to know? (Think flexibility!)

It is equally important to define what is flexible, or unknown, about a new object.

  • Image width, margins, and decoration vary
  • Right content is unknown
  • Width unknown

Once it is built, we can use it to create many of the same basic object. In the following image, I’ve highlighted all the media objects on the facebook homepage. You can see that even implementing this one object can save a ton of code because we stop repeating ourselves.

media block use

The media object highlighted in red on the facebook homepage

Implementation Details

How does it work? The hard part is making sure that the image can be any width, so that the element is reusable. It means our content area needs to be flexible so that it can fill in all the remaining space available. We’ll have to create a new formatting context to make a flexible column.


<div class="media attribution">
<a href="" class="img"> <img src="" alt="me" /> </a>
<div class="bd"> @Stubbornella 14 minutes ago </div>

The CSS:

/* ====== media ====== */
.media {margin:10px;}
.media, .bd {overflow:hidden; _overflow:visible; zoom:1;}
.media .img {float:left; margin-right: 10px;}
.media .img img{display:block;}
.media .imgExt{float:right; margin-left: 10px;}
  1. We clearfix both the wrapper element, media, and the inner content wrapper, bd (body) using the secret benefits of overflow. There are other ways we could have implemented the clearfix plus new formatting context. More on that in a later post.
  2. Then we float our image wrapper (generally a link) left and our optional right region to the right.
  3. Finally, we set some margins and paddings to keep everything lining up nicely. You might choose to set margins via a class which extends the .img object if you have several different kinds of images with different spacing and decoration.

Voila, we’re done. It is a very simple object, but it is very powerful. We can eliminate a lot of lines of code abstracting this repeating pattern. The code for the media block and many other “web Lego” are available on the Object Oriented CSS open source project.

How to create CSS objects? Get the granularity right!

In a previous post, I said:

Shoehorning CSS and HTML into PHP abstractions prevents the code from being DRY and ultimately leads to code bloat, because, the CSS and HTML require a far more granular object structure than the PHP.

And then I didn’t expand on it, or give proper context. Ooops, sorry!

Correct granularity is one of the keys to tiny CSS

In the PHP layer, the following stream story (from facebook) might be a single object. All of the logic of determining which bits of HTML to show or hide are contained within one object structure.

An example of a stream story on the facebook website

A Facebook stream story

Frequently, developers try to make the CSS match this middle-end logic. We expect all the CSS code for the stream story to be sand-boxed within a wrapper id, for example #story. This ends up with bloated code that isn’t DRY. Why? because the proper architecture for the CSS layer is much more granular. Trying to base the CSS architecture on the PHP layer is something akin to trying to use the DB schema to configure apache. It just doesn’t work.

stream story broken down

The stream story is composed of many smaller (more granular) objects

So we can see that the stream story example above is composed of many more granular objects. As we make the objects more granular, we begin to see the same patterns emerge over and over, and the same objects become much more reusable. We start to see that most sites on the interwebs are composed of the same basic repeating patterns combined in different ways. As a side benefit, the CSS gets *much* smaller and simpler.

The stream story, one PHP object, is composed of several HTML & CSS objects:

1 heading


5 Media Blocks

2 Link Styles

Link Styles

1 Comments List

Comments List

1 Action List

Action List

1 Paragraph


Benefits of this approach?

Getting the CSS object granularity right means that our CSS (and by extension, our HTML) become much simpler and lighter. Our little reusable object can be employed across the site to create new and different pages without adding to the weight of the CSS.

As a starting point, I recommend creating the following objects: headings, lists, text treatments and links, containers, media, grids, and template. Create all your smallest objects first, before you build whole pages, and your CSS will stay small by default.