Category Archives: oocss

by Trey Ratcliff

Our (CSS) Best Practices Are Killing US

Watch more video from the Top Picks channel on Frequency

Another day, another melodramatic blog post title. ;)

I was prepping to speak at Webstock this year when I realized I didn’t want to give the talk I had proposed. I didn’t want to talk about the Mistakes of Massive CSS, because I realized it went deeper than that. In fact, in most cases, the things we considered best practices were leading to the bad outcomes we sought to avoid. I realized (unpopular though it might be), that we couldn’t make it work out well by trying harder. Each time we start a new project, we think “this time, I’m going to keep the code clean. This time the project will be a shining example of what can be done with CSS.” And without fail, over time, as more content and features are added to the site, the code becomes a spaghetti tangle of duplication and unpredictability.

It is time to let ourselves off the hook. There is nothing we could have done by trying harder. There is no magic juju that some other developer has that we don’t. Following our beloved best practices leads to bad outcomes every. single. time.

What are those flawed best practices?

  • Classitis!
  • Never add an non-semantic element
  • Or, a non-semantic class
  • Use descendant selectors exclusively
  • Sites need to look exactly the same in every browser

Classitis!

How in the world did we even get the idea that some aspects of CSS were good and others evil? Who decided and what data did they use to judge? Did their goals fit our goals? There is nothing wrong with using classes. In almost every case, classes work well and have fewer unintended consequences than either IDs or element selectors.

You should style almost everything with classes. The goal is to find a balance between classes that are too broad and include everything and the kitchen sink and classes that are too narrow. Generally speaking, you don’t want your classes to be so narrow that each one applies a single property value pair. It becomes extremely hard to evolve your design if every item is composed of mini-mixins.

On the other hand, if classes are too broad, you will have duplication. Try to find the middle ground where all the repeating visual patterns can be abstracted. This is hard, but very worthwhile. If you do it, your code will stay clean. You will finally see results from trying harder.

Classes are our friends. Seeing a lot of IDs is actually very bad. Run from this kind of code:

#sidebar #accounts #accountDetails h3{}

Never add non semantic elements

We don’t want to have unnecessarily heavy HTML with a lot of extra elements. On the other hand, adding an extra element can often provide a buffer between two sets of classes that weren’t necessarily coded to interact with one another. For example, I prefer to have the decorative elements of a container completely separated from its content.

Using a paragraph that happens to be inside a rounded corner box to make a corner decoration means that the container can never hold content other than a paragraph. If you want to include a UL you will need to duplicate all those styles. This doesn’t work.

You want your content to be marked up in beautiful HTML that uses a diverse set of tags like P, UL, OL, LI, H1-6, strong, em. Add a few extra wrapper elements to keep your content nicely cordoned off from your containers or separate out decorative flourishes! Your HTML will be clean and your CSS predictable.

Never add non-semantic classes

We absolutely don’t ever want to use classes like “bigRedHeading”, not because it is non-semantic, but because it isn’t future proof. As the design evolves, the CSS needs to keep pace. On the other hand, CSS needs abstractions. We need to be able to solve a particular problem really well, and then allow people to go on using that solution long afterward. Grids for example solve the layout problem. Once they have been implemented on a site, developers can spend time on more important features and stop re-implementing a layout solution over and over. Abstract solutions are necessarily disconnected from the content they happen to contain. This is something we should look for in a solution, not condemn.

The semantics debate has really gone too far. It is useful as a general principal, but often I see standards aware developers trying to stuff in semantics that never existed in the design. If the design didn’t make a distinction between two things visually, why add additional complexity? Classes work much better when we use them to represent visual semantics, rather than keeping them tied to content.

One more point on the topic. Screen readers don’t read class names. It is not an accessibility issue. (Thanks to John Foliot for confirming)

Use descendant selectors exclusively

Never has more terrible advice been given (ok, ok, I exaggerate, but for CSS, this is as bad as it gets). The descendent selector is *only* appropriate between multiple nodes of the same object (say, a tab container and its’ tabs), and even then, only when you are absolutely certain that there will never be any markup changes. Very hard to guarantee, no?

I have had a designer give me a tab container that had one group of tabs to the left and another grouping (usually more simply styled) to the right. In which case, if you had styled the UL using the descendant selector, you would be stuck overriding a bunch of styles you no longer needed. Classes are much much better and can be used in combination with the descendant selector when the nodes belong to the same object.

I guess the only time I use the descendant selector with elements is to style LI, and even then, I often get bitten when someone wants to nest those lists. Better support for the child selector will make that issue easier to fix. Ideally, we don’t want any styles flowing from container to content.

Even with the media block, you might consider putting a class on the media block which sets the styles of the image. It sounds reasonable until you realize that the image is actually its own object. You might have multiple nested media blocks and you will get very weird interactions unless you apply the image style class directly to the image itself.

In the middle layer, you might decide to create one display objects for each of the different types, and that would probably make the objects easier to use, but in the CSS layer, you don’t want to tie it all together like that.

Sites need to look exactly the same in every browser

Forking your design is bad, it makes testing even more complicated, but that doesn’t mean that pixel for pixel a site needs to be exactly the same in every browser. If you try to force the complexities of a modern design onto users of IE6, their user experience will suffer. The site will load slower and reflows and repaints will make the javascript sluggish. IE6 users need a reasonably fast user experience, they do not *need* rounded corners.

Anyway, enough ranting. Please do checkout the slides for Our Best Practices are Killing Us. I hope you find them useful.

Photo by Trey Ratcliff

Automating CSS 3 Gradients

CSS 3 is full of ways to reduce our dependence on background images, one of which is pure CSS gradients. They have several features, which I’m sure designers are salivating over, like multiple color stops, and angled, radial, and linear gradients. Many people had built cool designer-focused tools to make interacting with a somewhat confusing gradient syntax a little easier. The issue for me has been that I’m not a designer. I generally work off of photoshop comps or (when doing big re-architecture projects) the site itself, as if the old version were a design. This means that, for the most part, I was trying desperately to match CSS gradients to an image with zero information about how that image would have been created. Because of my focus on fixing old and broken CSS, the original designer may not even still work at the company.

If you don’t know what I mean, picture me with a color picker going pixel by pixel to try to figure out by hand where the color stops should be and what colors I should use versus extrapolate. Then, for each version, making an image of the gradient I’ve created, blowing it up so I can compare it to the image of the original. Rinse, repeat until I’ve come up with something that kinda, sorta approximates the original. Oh yeah, painful.

Continue reading

Performance Double Whammy Hits New Zealand at Webstock

Interested in Performance and scaling sites to a large number of visitors or pages? I just realized both Steve Souders and I will be giving talks at Webstock next week! This is a pretty amazing opportunity to massively increase your Performance mojo in one go. :)

I’m going to be hosting a workshop in which you will learn to build your own site using OOCSS techniques. By the time you leave you will have the skills necessary to write efficient, scalable CSS. You’ll understand the joy and pain of CSS3 and HTML5, and be ready to go build the next generation of websites and web apps.

Steve’s workshop is filled with Mobile yummy goodness. How do you figure out that your mobile app is slow before your clients start complaining? What’s even going on in there? In his workshop, Steve is going to open up the mobile black-box and teach you to take a peek inside.

I am super excited about Webstock, even more so now that I found out it will be a perf-geek-meet-up. New Zealand here I come!

The hacktastic zoom fix

Everyone keeps asking me what is with all the “x” in the OOCSS grids… so I finally wrote an article. The short answer is that it isn’t just a clearfix (it does that too), but it also causes the element to stretch wide, even when it has very little content. It is a bit of magic that allows us to use display table-cell to create a new formatting context in all browsers. It also allows us to solve sub-pixel rounding errors without resorting to fixed widths. (This has all kinds of great perf benefits because the grids are nestable and stackable).

  content:" x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x ";
}

I wrote a while back about creating new formatting contexts with overflow: hidden. A new formatting context is desirable because it tells an element not to wrap around nearby floats, and to clear any floats it contains. Essentially a new formatting context makes an element behave like a column. Anyone who has tried to create a grids system or multi-column layout knows that that is no easy feat.

Zoom Baby

This is one case where Internet Explorer gets it right. Zoom triggers hasLayout, which creates a new formatting context, clears floats, and prevents float wrapping with none of the drawbacks of the standard solutions.

.lastUnit{
  zoom:1;
}

I wish we had a simple property value pair that would do the same thing in standards-based browsers.

.lastUnit {
  formatting-context: new; /* please! */
}

There are several ways of achieving the same thing in Safari, Firefox, Chrome, and Opera, but they each have drawbacks. For example:

Overflow Hidden Hides Stuff

Overflow hidden creates a new formatting context with very few side effects, and for many websites, it will still be the right answer, however it does have one major drawback. If any content within the element overflows its boundaries, it will be cropped. Normally, if you don’t specify a height (you shouldn’t need to), the element grows to the size of it’s content.

 .lastUnit {
  overflow: hidden;
}

However, on a complex site like facebook (and most applications), popovers, fancy buttons, and menus were cropped off because they were outside of the normal document flow and didn’t influence the height of the parent node. This forced me to look for another solution.

Table Cells Create a New Formatting Context

In the specification, several property value pairs create a new formatting context including; overflow (other than visible), table-cell, inline-block, and float. I set out to try them all. Other variations of overflow triggered a scroll bar that didn’t make me happy, and one of them (sorry, it was a year ago, I can’t remember) caused issues in RTL.

I began to test display: table-cell. I used the OOCSS grids test page in which each grid contains a heading and a paragraph filled with lorem ipsum text. To my astonishment, display table cell worked.

.lastUnit {
  display: table-cell;
}

The HTML of the last unit.

<div class="unit size1of5 lastUnit">
<h3>1/5</h3>
<p>i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i </p>
</div>

I was very pleased with myself, until I looked at the modules page. All of the modules in the last column were shrink-wrapped to the text. I began to explore what was different about my working grids and my broken modules. You can see the same issue on the facebook comments page. Notice how the comment box is far too narrow.

Comment box should be full width, but display table cell is shrink wrapping content.

I discovered that display table cell shrinks or grows to fit the content (much like a floated element). On my grids test page, the lorem ipsum dummy text was actually pushing the last column open to take all the remaining space on the line. I was getting the behavior I wanted, but it was triggered by the content, which is unacceptable for OOCSS, because OOCSS requires a strict separation of container and content. I couldn’t require text in the grids, in fact, I have no idea how people will use them.

Generated Content FTW

I realized that generated content was the only way to insert this text without requiring developers to muck up their HTML. As a bonus, generated content is not a part of the DOM, so it should be ignored by screen readers. I took a look at the specification and used the YUI clearfix implementation as a starting point for my solution (This is where things get a little bit crazy). My column, lastUnit, is still set to display table-cell, but we also add the following code:

.lastUnit {
  display: table-cell;
}
.lastUnit:after {
  clear: both;
  display: block;
  visibility: hidden;
  overflow: hidden;
  height: 0 !important;
  line-height: 0;
  font-size: xx-large;
  content: " . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ";
}

Crazy, right? So let me show you what I’m doing here.

Understanding the Code

First, open the module test page in Firefox with Firebug enabled. The modules are inside thirds grids, which use the technique. Change visibility so that you can see how it works.

visibility: visible;

The generated text pushes my lastUnit open in much the same way the lorem ipsum dummy text did in the grids test page. They convince the browser that this element needs all of the space left after the width of floated siblings has been calculated.

Lets go through it piece by piece:

.lastUnit {
  zoom: 1;
  display: table-cell;
}

First, we create a new formatting context so that floats are not wrapped, margins do not collapse, etc. Display table cell is not well supported in older versions of IE, but it doesn’t matter because zoom does the trick. None of the rest of the code applies to IE.

.lastUnit:after {

We’re using the :after pseudo class so we can insert generated content (text) as the last node inside the lastUnit.

  clear: both;

Makes the generated content clear any non-generated sibling elements.

  display: block; 

We want the element to expand to the full width.

  visibility: hidden; 

Makes the generated content invisible and allows clicks and interaction with any content that might be below.

  overflow: hidden;

Makes sure height is respected by the browser, even in browsers that expand containers (an IE bug).

  height:0 !important; 

We don’t want generated content changing the layout.

  line-height: 0; 

Again, generated content shouldn’t change the layout. We’re covering all our bases.

  font-size: xx-large; 

Large text means we’ll need less generated content.

  content:" x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x ";
}

The faux text does the heavy lifting by opening to full width the element which is in display table-cell.

Finally, An Opera Bug

Someone on the google group noticed that Opera was choking on this method. It seems that Opera cannot wrap a series of “. . .” as if it were normal text (a bug report was submitted, so this may have been corrected already). Simply changing all of the dots to “x” resolved the issue. Any text will work, Easter egg anyone?
We changed that line to:

content:" x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x ";

Drawbacks

Table-cells interact with each other in weird ways. Unlike other elements, which only interact with siblings and parent nodes when they change dimensions, table cells are weird and hard to calculate because the browser does a lot of fudging to make them line up and layout nicely. This fudging has proven to be expensive, so I do wonder about the performance impacts of this approach. Perhaps it is possible to set the display to fixed as Jenny Han Donnelly of YUI suggested — something to test another day.
Generally I avoid table cell whenever possible, but in this case I had tried all of the other methods for generating a new formatting context. Ultimately, browser vendors should allow a trigger that doesn’t have side effects.

Avoiding Pseudo-Bugs

It might be tempting to try to position our last column without creating a new formatting context, for instance, modern browsers are much better at calculating percentage widths. OTOH, zoom creates a new formatting context for IE and it is important to keep the flow as similar as possible across browsers to avoid unintended consequences.

It’s all about working with CSS rather than against it. That means that if you have a new formatting context in one browser you should have it in all of them.

Multitasking is killing me (and probably you too)

Multitasking has been stressing me, robbing me of my focus, my productivity, and my appreciation of the beauty of the exact moment I’m experiencing right now, and dammit, I want my brain back!

Once upon a time, I was assigned 21 projects in my first month on a job. Distinct projects, working with different groups of people on completely different tasks. I went from writing code 95% of the time to running from meeting to meeting.

At the same time, I installed IM at work and didn’t create a separate work account (I can see this clearly now, but at the time, I was just filling out my HR profile, I didn’t see the significance). The lines became blurry and I started to get pings around the clock from both work and friends. This is in part due to “crazy-round-world-syndrome”. My life is international, that’s okay, but it does make boundaries harder.

Perhaps it really began as early as 2000, when I got my first cell phone and lived with it glued to my ear? Getting an iphone in January of 2007 certainly made it worse because as a device my precious is meant to be petted, not simply used to accomplish other tasks more efficiently.

So what does a good geek do? Gather data.

I gathered data from scientific american, psychology today, read research papers, took a mindfullness course, and read links that friends posted to twitter.

And what did I find? In fact, multitasking is killing me. All these constant chats, SMS, growl notifications, and email are releasing dopamine in my brain. The kind of trigger my ancestors might have gotten from a lion jumping out of the bushes. The rush to immediate action. It causes me to value new information above old information because, like a drug, new information (no matter how trivial) gives me a shot of dopamine. My fix of choice is a cocktail of tweetie, iphone, and IM. I know that because after reading about My Brain On Computers, I installed RescueTime to see what I was up to. The results seriously scared me. I was spending far too much time IMing. Even if some of the discussions were technical and useful, the volume was just not acceptable.

Simply knowing this has lead to change. I realized that working from home too much means I am starved for interaction with other developers. I try to get that on IM, but constant distraction is inherent to the medium. Instead, I’m working from client offices, joining a co-working group, and inviting people to get together to work on projects face-to-face. It is much more satisfying than IM, and doesn’t come with the chipmunk on crack scatter-brain side effects.

Mindfullness Meditation

A month ago, I started doing some mindfulness meditation. It is all about noticing how things are right now. The only effort you extend is a certain curiosity about how things will unfold. The rest happens naturally in proportion to your willingness to see things as they really are.

At first, Madagascar Bourbon Vanilla cupcakes started tasting oh-so-good. Then I started noticing how much time I spend swapping between tasks. That my frustration tolerance is very low. In other words, if I get stuck, rather than trying to work out a solution, I simply switch to an easier task (like email or twitter). I was spending so much time task-swapping I wasn’t even noticing what was happening right now! I resolved to walk my dog without checking my iphone. It was wonderful.

As a programmer, I love that amazing feeling of being in-the-zone. When the work seems to flow out of me and time doesn’t even really exist anymore. I had that feeling less and less (or maybe I was just more aware of it because of all the mindfulness meditation?), and I wanted it back. I went through all my old email since OOCSS started taking off. My god, it was a lot of email. Three or four messages per day filled with interesting five-part questions of a deeply technical nature (like cross-browser sub pixel rounding errors).

So I started to say no to projects and speaking engagements, to try to make my life more sane and manageable.

Feeling less productive

Test your focus (flash) based on a Stanford Study

Test your focus based on a Stanford Study

Then, the guilt set in. I *should* be doing more, I shouldn’t say no to an awesome project or speaking engagement. I should clone myself so that I could keep up with my email. I am the middle child in my family. My sister is a type-A go getter. She always has a million things going on. She has to-do lists and lists of her to-do lists. I’ve always felt like that was the “right” way to be. So again, I did some research. Multitaskers:

  • Did a significantly worse job filtering out the irrelevant information.
  • Took longer than non-multitaskers to switch among tasks.
  • Less efficient at juggling problems.
  • Tended to search for new information rather than accept a reward for putting older, more valuable information to work.
  • Process visual and auditory input less efficiently.
  • Become reliant on more a more simplistic, and often inferior, thought process, and can thus fall prey to perceptual decoys.

Huh, so maybe this multitasking thing gives the illusion of productivity without achieving higher volume, let alone my real goal of time spent deliciously focused on the task at hand.

So what makes people lose focus?

Decision-making. Apparently, time spent making decisions tires your brain. Much like the muscles of a runner, you can only go so far before you become too tired to run any more. Apparently, even tiny decisions (do I delete or archive this email) can seriously impact your ability to make good choices. See the last bullet point above.

Perhaps there is a parallel between this and choosing 1000 times a day not to respond to growl notifications bouncing in your periphery. Each time you exert will-power, you make it harder to have the mental energy to effectively make analyze your options. I’m taking this to mean that I should shut down Tweetie, Adium, and Mail for several hours each day, rather than trying to resist each time a new message comes in. To avoid “ego depletion” so that I will have enough left to use on something that truly exercises my concentration muscles and teaches me to tolerate frustration, like coding.

How can you get focus back?

These papers suggest three things; a good nights sleep, positive emotions, and slowly building up stamina. In addition, another link I got from Zeldman talks about the importance of being curious and gentle with yourself. Saying, “hmm, I wonder if I’ll manage to focus today?” is apparently much more effective and productive than admonishing yourself with a lot of “musts”, “shoulds”, and other guilt-producing tools of grinding willpower. So, I’m curious to see if I can find ways to reduce the number and frequency of tiny decisions and displays of self control which happen throughout my day. I wonder if I can make it to meditation today? It will be interesting to see if I can limit communication time to specified periods.

Is it working yet? Is it? Well, I’ve been doing this stuff for a few weeks, and I do seem to be writing a lot more blog articles. As always, I’m a work in progress.

References

All of my references are listed on Delicious. Check them out. There is some really good stuff in these articles. I definitely recommend going directly to the research papers.