Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
OOCSS + Sass = The best way to CSS (ianstormtaylor.com)
128 points by ianstormtaylor on Oct 16, 2012 | hide | past | favorite | 51 comments


I used to be in this school. It has some downsides. I'm now back to the twitter-bootstrap-many-classes-are-fine camp.

* your css can still get large in large sites. Even though you're not duplicating rules, you're still filling your rules up with lots of comma'd selectors.

* IE8 and lower have selector limits of 4095, we hit this because we used @extend on a fairly large site and had to split our css up more

* It creates more dissonance for developers that are comfortable applying ready made classes. Now they have to make up (sometimes it really is just making it up, there's no real semantic name) a class name for something, go to the sass file and add it. This is more steps than they need.

* Many of these things can be cleaned up by good usage of partials or their equivalent on the DOM side. You should be DRYing that up too, so I can't say I relate to the author's concerns about changing DOM.


I wrote a very very similar article many months ago (but no upvotes * sob *) - perhaps people interested in this article would also be interested in my take on it, where I rely much more on mixins than extends:

http://carrotblog.com/css-patterns-evolved/


OP here, nice article! As long as you always group your selectors, mixins would do exactly the same thing as I'm describing. What's awesome about Sass @extend though is that you can ungroup your `.post, .comment, .friend ` selectors and Sass will regroup them for you! If you did that with mixins you'd end up with code duplication. Cheers!


Thanks! And definitely agreed - I never used @extends too much previously, but I'm starting to see some use cases for it. The placeholder class is an especially nice new feature outlined here, also props to Chris Eppstein for his awesome work on this.


I haven't had the experience that HTML is harder to maintain if you use classes more liberally. What this approaches forces you to do is: write or edit CSS every time you want a new combination of existing traits...which isn't ideal either.

The post also suggests that certain class names are "unsemantic", when they obviously aren't. They just have different meaning to the sorts of class names the author is advocating.


Right, I addressed that in the post. They are "non-semantic" as far as people normally apply the word "semantic" to HTML. You might say that they are still semantic, fine. But you'd be hard pressed to argue that they are different than classes like `.dropdown` or `.menu`, and that difference makes them _much_ more susceptible to change. Which means if you're littering your markup with those classes, you will have to sync those changes all over the place.

Yes there are still changes to make (there always will be), but with the OOSass approach you're doing it in a single place. Want all of your statuses to be `.media` modules? One place. Not n places. Moving the work from the n-side to the 1-side is the mark of a good abstraction.


I've been working on my own framework for the last several months and I've been back and forth a bit on this issue. On the one hand I strongly believe that 1.) writing and editing markup is easier than writing CSS (browser inconstancies, context switching), and 2.) your coworkers are probably a lot more proficient with HTML than CSS. On the other, when you start getting class attributes like "col-12 secondary-panel rounded-top inner-shadow pam" you may have gone off the rails a bit. I guess it depends on where you want the mess to be. One argument that keeps me coming back to the multiple class names camp is that keeping your classes semantic and extending your patterns requires writing more Sass every time you add new content, where going nuts with class names doesn't. I love being able to add a new component to the app without having to open up a single stylesheet. We also have trouble running into the 4095 selector limit in IE8 when we package everything, so every extra class we can shave off helps (although in this specific case the problem is more with having a Sass codebase that has been rode over roughshod by five+ developers for the last year).


Chris Eppstein recently wrote a comprehensive article about the changes in Sass 3.2: http://chriseppstein.github.com/blog/2012/08/23/sass-3-2-is-...


Is this possible in LESS?

I know LESS mixins "is kind of the same thing", but the way i understand the %placholder is that it doesn't paste code into the class where you call it. It actually builds a dynamic class containing the code and then add the selectors/classes/ids (thats using the placeholder) to that class. Right? Right.


Yup you're right. And nope, it's not possible it LESS. Mixins actually aren't the same thing, they are just a way to duplicate code, which is exactly what you're trying to avoid. I'd seriously recommend you try Sass. It's got much more going for it.


From the creator (of Sass) "it's Sass not SASS"

https://twitter.com/hcatlin/status/256142344431214592


Good call, fixed!


You can either repeat yourself by using "@extend %mypattern" in Sass using this methodology, or repeat yourself in the DOM with ".mypattern" in the OOCSS approach.

Both are elegant ways of handling the same task, but I don't think one is much more DRY than the other.

I'd argue that it's more correct to describe a class once and apply it to many elements (OOCSS) than it is to describe it many times over and apply it to each element individually (Sass @extend).


"I'd argue that it's more correct to describe a class once and apply it to many elements (OOCSS) than it is to describe it many times over and apply it to each element individually (Sass @extend)."

What makes you say that the Sass approach is describing it "many times over"? It's described in one place: the %placeholder declaration. There are three steps in the process:

+ Describe the pattern. + Apply the pattern to components. + Apply the components to elements.

In OOCSS, you:

+ Describe the pattern once. + Apply the pattern n times per component. + Apply the component n times per element.

In OOSass, you:

+ Describe the pattern once. + Apply the pattern once per component. + Apply the component n times per element.

The OOSass is much DRYer because if you've decided already that all .dropdown-menu-item's are going to be `.media` patterns, you do that once. You don't have to keep repeating that decision every time you write a new dropdown.


If you are looking for more power, you can use mixins rather than extends. This way, you do get an additional and very signficant power boost - what previously were utility classes are now functions, which take parameters and have the ability to adapt and flex if you write them correctly.


Yup, I've been using mixins for a while now to reduce code bloat. It seems like placeholders are degenerate forms of mixins.

edit After more reading, they are most definitely not degenerate forms of mixins. Placeholders FTW!


The one advantage that extends provides is less code bloat (if you use them right) in the compiled product - rather than inserting the same code, extends will add the select to the list with the previous selector. So if you were to write something like this:

.hello { color: red; }

.world { @extends .hello; background: blue }

...it would compile to something like this:

.hello, .world { color: red; }

.world { background: blue; }

na'mean?


I'm picking up what you're putting down, but I was thinking more placeholders vs. mixins. Although I guess placeholders would avoid this code bloat too, and they can be used as selectors.


tl;dr Somebody discovered the power of mixins

I don't see how SASS is doing something unique here that other preprocessors can't do as well.


Placeholder classes are new in SASS 3.2, so the blog post is explaining how to do them and what problem they solve.

It's not unique, but it has been an awfully long time coming. See: https://github.com/nex3/sass/pull/236


Based on the blog post I'm not seeing how I can't do that in Less for example. I'm using lessphp and I can build patterns like

.media() { // won't compile directly width: 100%; // other cool styling }

img { .media; }

which would output just

img { width: 100%; }

Gives me similar results I think or am I missing something?


The entire point of @extend is so that you don't get the extreme code duplication of mixins. I can't speak authoritatively on LESS since I stopped using it a long time ago, but what happens when you apply that `.media` pattern to another selector? It duplicates all the styles, instead of grouping common selectors into one style definition like @extend does.

And the point is even @extend can get bloaty when nested, but placeholder tags avoid that problem, and remove the extra pattern classes from the output.

So the article is actually advocating that you stop using mixins. Mixins aren't OOCSS, they're just copy and paste made easier.


"It duplicates all the styles, instead of grouping common selectors into one style definition like @extend does."

This didn't come through entirely until I read the comment. I think an example of what mixins would produce would be helpful.

At the end of the day we have two goals: 1) keeping things easy to develop and 2) keeping the CSS filesize as small as possible.

Mixins accomplished 1 but not 2.

One potentially relevant example is bootstrap's core "btn" class, which has over 50 lines: https://github.com/twitter/bootstrap/blob/master/less/button...

When you want a button in HTML you have to add the btn class, as well as an additional class for that button's styling. IE: btn-large, btn-primary, btn-info

Bootstrap could have made this happen with just one class by implementing mixins, but that would result in each btn-primary, btn-info, etc repeating those 50 lines from the btn class.

If Bootstrap used @extend instead, that large btn class could be replaced with a multiple selector, IE: .btn-large, .btn-small, .btn-primary, etc. Then the independent styles could be defined below, as they already are, and we would just need one class to add the appropriate button style.

I guess they could do that today by just using the long selector instead of .btn, but that makes the file harder to maintain.

Let me know if I'm thinking about this wrong.


Yup, that's completely right! I should probably add a bit about mixins being bloaty, so people don't get the wrong idea.


It's quite easy to create duplicate styles in the output with mixins - the compiler isn't that smart yet, do placeholders avoid all of that? I haven't seen a lot of comparisons or examples that really drive it home so far.

I'm actually working on a css post-processor script that optimizes css output. Grouping styles in the most efficient way possible is quite tricky.


@extend avoids duplication, but by itself it has some other bloat problems. @extend + %placeholders completely avoid duplication. Thing is @mixins aren't supposed to avoid duplication, they just inject, and should keep the declaration in the same position in the stylesheet.


Thanks for expanding on the differences


The effect is the same (it's composition vs inheritance) but the SASS CSS is going to be more space efficient. The way I think about it is that @extend copies the selector while mixins copy their contents.


This is what I was thinking as well. Apparently in SASS they only had mixins that work like classes and are included in the output and now the new "placeholders" act like .mixin () {} in LESS.

The example also combines hr {/* style /} .separator {/ style /} into one selector hr, .separator {/ style */}

but maybe that is something a CSS minifier should be able to do?


No, SASS had @mixins and @extend. And now it has @extend with %placeholders, which is the least bloaty solution of them all. Lots of the use cases mixins are touted as solving are actually much better solved by @extend'ing %placeholders.


Yup. Stylus (https://github.com/LearnBoost/stylus) has mixins and a lot more.


Stylus+Nib is the way to go. It annoys me to no end how overlooked it is.


OP here. I actually used to use Stylus and Nib, so don't worry I didn't overlook it. Actually I'm the #5 on the Nib contributors list :p https://github.com/visionmedia/nib/graphs/contributors

But it also used to annoy me how much it was overlooked. Not for Sass so much, but LESS is horrible compared to either Sass or Stylus.

That being said, Stylus doesn't have the ability to extend selectors that don't appear in markup, the way @extend'ing %placeholders works in Sass. (Not that I blame TJ, the guy's awesome repo ratio is the best on github!)

The thing that gets me frustrated with both Stylus and Jade is that they go a bit too far in the minimal syntax direction at the cost of other syntax improvements (since going minimal means its harder to differentiate pieces). The Sass syntax is more than simple enough, and the option to drop semi-colons is a cool thought experiment, but not so useful in real scenarios.

And then there's momentum too. I mostly just wish that we could all get behind one pre-processor, and Sass is the one with the best momentum. (I say best, because LESS has some momentum, but it's syntax is way less thought through, and it has less active committers.) I don't blame TJ at all for this, but he definitely has less time to devote to Stylus than the multiple Sass contributors do. Mostly it's just a question of putting your chips with the player with the most momentum because that will bring you the fastest updates.


The @extend directive, especially with placeholders, is very powerful and allows you to not repeat yourself in compiled CSS as well.


This is the key that I missed when I first read the article. Mixins will always be repeated when compiled. Placeholders result in combined selectors so the styles aren't repeated in the compiled CSS.

In many ways, it seems like placeholders would almost always be preferred to mixins. Though, I'm sure there are exceptions.


It's so DRY... I absolutely love the approach. Way to take the original idea and run with it.


Love the way that works. The only problem with it is that a another, non-related, CSS class still needs to be used. If the element doesn't call for another class you could select the elements directly, but that kinda defeats the point of OOCSS.


True. I'm just advocating for removing the pattern-level classes. The component-level and context-level classes should still remain. Component-level would be `.dropdown` and context-level would be `.user-dropdown` or `.explore-page .dropdown`. Those should be selected and javascript'ed.

But that way all of the purely presentational classes are kept completely in the CSS where they belong.


In an ideal world, I'd like to be able to use the CSS framework of my choice e.g. bootstrap, semantic markup for the reasons the author described in the article, and, the ability to extend my semantic classes with the .span2, .container, etc. classes from the framework.

I actually thought about doing it this way by just importing the bootstrap CSS and extending from the various parts, but I realised elements inside the element I'm going to extend from container won't have the container parent class and thus won't get the correct CSS applied.

Does anyone know of something that solves this?


I thought this exact same thing a few months and have been building a framework that works exactly this way. I've spoken about it at a number of small meetups and events.

I haven't released it to the public yet, and it's currently getting a rewrite and bump to v2, but if you'd like to check it out i can send it over.


Sorry for the delayed reply. Yes, I would very much like to see that. I'd love to try it out, and would happily give feedback on using it in a couple of personal projects. My email's in my profile.


Have you seen Compass Recipes? http://compass-recipes.moox.fr/

It seems like it does exactly what you want, collect patterns in a very simple way of reusing it. The only bad thing is that they are created as mixins, but it shouldnt be that hard to just create a placeholder class including each mixin that you need.


Again isnt this what SASS is for?


SASS pre-3.2 didn't have the idea of classes that exist at compile time just to be extended. Without the placeholder directive you'd have unused classes polluting your CSS, which goes against the DRY ideals of OOCSS.

It's a complete no-brainer, and I was a little surprised to see SASS didn't have it last year when I was looking into it. Better late than never though!


Hi there. Great post.

I completely agree with what you're saying and I've wrote similar things on http://www.betterfrontend.com - perhaps you can help contribute this content there?

Semantics for the win baby.


A small point, but it would be great if your examples came with a render of what it looks like. The description helps, but without the visual to match it the context is slightly harder to grasp.


So... basically, author uses a compiles-to-css to DRY up his code.


And importantly, to DRY up his compiled CSS as well.


If you want a whole Sass framework that uses OOCSS take a look at inuit.css

https://github.com/csswizardry/inuit.css


Love it. Clever and clean.


Great!!! Thanks




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: