5 ms·
How We Could Write Better CSS
- ultimatedelman 13y agowhile the mixpanel CSS is awful, the facebook CSS is not much better. any time you have to use a class that is descriptive of what the element should look like (for instance, .mas, which presumably stands for Margin All Small), you've tightly coupled the structure to the presentation and failed at CSS. While the article gets the idea mostly right, the counterexamples it uses are just as bad practice.
- Pxtl 13y agoThe Facebook CSS is so utterly specific that they may as well use style attributes directly.
- sriharis 13y agoEndorsed! I am also a SMACSS fan. And I say "Keep the specificity minimum" as a mechanic to write more maintainable and scalable CSS. I also have another mechanic - "Don't nest CSS", and here's my explanation for why: http://sriharisriraman.in/blog/2013/09/08/dont-nest-css/ http://sriharisriraman.in/blog/2013/09/08/dont-nest-css/
- antidaily 13y agoNot to mention, nested is always slower.
- cliveowen 13y agoI think there's a big need for an agreed upon standard for writing CSS. There's a lot of beginner stuff out there, but what sorely lacks is an idiomatic way to write proper CSS. You should write base styles and extend them, but to what extent? How should you group the properties? Heck, how should you structure the whole thing? We need this. I've been thinking the same thing as the author for quite some time, I'm glad someone has at least put the idea out there.
- sriharis 13y agoI think http://smacss.com http://smacss.com is what you're looking for.
- cliveowen 13y agoThank you! I never heard of this, it's exactly what I was looking for.
- camus 13y agoCSS sucks,period. When people come up with an improved standard then we can discuss about writing better CSS. Today ,without CSS preprocessors, writing CSS is a nightmare. We'll write proper css when we get a proper language ( and when the box model get fixed on every browser). Until then I dont want to here about "agreeing on a standard for writing CSS". The spec should be the standard.
- sampl 13y agoDeeply nested CSS selectors in the source (like the ones in your MixPanel examples) are often a sign of CSS preprocessors in use. Using a tool like LESS or Stylus, MixPanel is probably including mixins in their styles that allow them the same modular flexibility you describe without cluttering the HTML with confusing, non-semantic classes like "mrm". Edit: your site's visual design is awesome, btw
- mcmillion 13y agoThis * 1000. Just because the output isn't 100% optimal doesn't mean the input isn't sane, maintainable, or clean.
- ultimatedelman 13y agotrue, however, remember that the output must be sane too since you're putting it in the HTML
- nobodysfool 13y agoThe same could be said of facebook. MRM means Margin Right Medium (it may be that originally it was "Margin-Right-Medium" but the compressor made the substitution to "MRM").
- andrenotgiant 13y agoWhen you get to the level of abstraction demonstrated in the Facebook Margins example, you have so many classes for each element that you may as well go back to inline styles. This also enables inconsistent UI in the front-end: some of my page-headers can have .mbl "Large bottom margins" and some could have .mbs "Small bottom margins".
- FredFredrickson 13y agoWhenever I'm writing CSS and I start getting to the point where I question whether or not I might as well be using inline styles, I know I'm doing something wrong and take a step back to evaluate where I went wrong.
- ahallock 13y agoI had a similar experience recently when I was using many compose-able CSS styles. My solution was to use a preprocessor and make an aggregate style; for example: <li class="u-paddingLarge t-important"> would become: <li class="MyImportantItem"> with the SASS being: .MyImportantItem { @extend .u-paddingLarge; @extend .t-important; } You can avoid writing inline styles, keep things DRY, and still have compose-able styles.
- mrxd 13y agoYou're right that this example is no more semantic than inline styles, but that's the extent of the similarities. If you want to update all the large margins across the app, you can do that in one place. That wouldn't be possible using inline styles. You can also enforce style guide standards. Only three margin sizes are allowed: small, medium, large. Inline styles obviously allow for much more variability.
- masklinn 13y ago> If you want to update all the large margins across the app, you can do that in one place. That wouldn't be possible using inline styles. Sure can, your pages are generated, generate the styles from config or constants. There, I fixed it.
- bichiliad 13y agoI'm a bit confused. I'm not a CSS expert by any means, but aren't h tags supposed to represent hierarchy, and by styling them differently in different places (apart from, say, colors or something) largely breaking the information hierarchy? It was my understanding that well-styled pages set up headings properly so that styling one heading different ways didn't need to happen.
- sriharis 13y agoAlthough the context of hierarchy is useful in CSS, there isn't a need to specify the styles with the hierarchy. That increases the specificity as a side-effect, which is a bad thing for maintainability. SMACSS suggests showing the hierarchy in class names instead. For example: use .main-dialog-heading{}' instead of '.main-dialog .heading h2 {}'. Edit: I actually wrote a detailed blog post on it: http://sriharisriraman.in/blog/2013/09/08/dont-nest-css/ http://sriharisriraman.in/blog/2013/09/08/dont-nest-css/
- stan_rogers 13y agoYes and no. In HTML 5, the hierarchy can be much more local/contextualized than in previous versions, so an h2 in an article can be at quite a different level than an h2 in an aside or at the page level. While it is possible to represent that hierarchy in CSS relative to the local context consistently across the entire page, it's not always desirable. On the other hand, arbitrary styling of headings does throw the baby out with the bath water; there should be a consistent and obvious visual hierarchy (corresponding with the semantic hierarchy) within each of the context types.
- paultannenbaum 13y agoWhile I agree with the general idea behind the article (object orient your css), I think the second demonstration involving margins is an example of OOCSS gone wrong. If you are injecting your markup elements with classes like "mbm mts mrl" (or padding, or anything else that is essentially just a css property), this is not much different than just inlining your styles. If you want this level of reusability in your css, use sass and create these as placeholders. From there give your dom element a some kind of class(es) that can extend several of these placeholder values. Ian Storm had a very well written article that hits on this more: http://ianstormtaylor.com/oocss-plus-sass-is-the-best-way-to-css/ http://ianstormtaylor.com/oocss-plus-sass-is-the-best-way-to...
- ryanSrich 13y agoI find that following a prefix method works quite well for organizing a lot CSS. For example (using sass): .home-header-h1{ font-size: 20pt; padding: 0px; margin: 0px; line-height: 1.3; } .home-header-h1-blue{ @extend .home-header-h1; color: blue; } .home-header-h1-green{ @extend .home-header-h1; color: green; } This helps keep classes out of your HTML and avoids large amounts of nested CSS. Here's the compiled source: .home-header-h1, .home-header-h1-blue, .home-header-h1-green { font-size: 20pt; padding: 0px; margin: 0px; line-height: 1.3; } .home-header-h1-blue { color: blue; } .home-header-h1-green { color: green; }
- tommmmmm 13y agoBut with classes with "green" and "blue" in the names, you're still mixing meaning and presentation and hurting maintainability. See: http://thecodelesscode.com/case/95 http://thecodelesscode.com/case/95
- Sakes 13y agoJust nit picking here, but I think your selectors are a bit redundant and long. What do you think about something like this? .home-header-h1{ font-size: 20pt; padding: 0px; margin: 0px; line-height: 1.3; } h1.home-blue{ @extend .home-header-h1; color: blue; } h1.home-green{ @extend .home-header-h1; color: green; } But I think if I was trying to truly minimize maintenance I would do something like... (in LESS not familiar with sass) h1.home { font-size: 20pt; padding: 0px; margin: 0px; line-height: 1.3; &.blue { color: blue; } &.green { color: green; } }
- colmtuite 13y agoOP here. Thanks for the feedback. A lot of people seem to be getting hung up on the sass thing. I'm all for sass, I don't think using 15 CSS classes for margins is the best way to handle this. I just wanted to use a watered down illustration for those who don't yet understand sass. Ideally, this should al be abstracted into variables/mixins/extends. My main point though, is that I'd like to see us working together to decide what the best approach is, then apply that across the board. I don't see any reason for us to continue doing things slightly differently. Whether you use CSS, SASS, LESS or any other preprocessor, we should be writing reusable CSS. At the moment, that is not happening across the web.
- ianstormtaylor 13y agoExtremely confused by the fact that there's no article navigation on your site. I just wanted to read more...
- colmtuite 13y agoYeah, sorry mate. I just hacked it together. My CSS is horrendous too :) I've two other articles: http://www.colmtuite.com/three-reasons-why-wireframing-tools-suck http://www.colmtuite.com/three-reasons-why-wireframing-tools... http://www.colmtuite.com/a-more-flexible-development-framework http://www.colmtuite.com/a-more-flexible-development-framewo...
- pothibo 13y agoNice article! One more important reason why to use class instead of tags: CSS rules are read from right to left. That means the browser will first gather all the h[1-6] and then it will filter the headers down with the other rules from there. If your CSS rules are applied to classes, it will gather the classes first then filter it down (Resulting in a smaller set in the first place). CSS processing will be much faster.
- sriharis 13y agoThat is so true. Github had a lot of performance issues in their diff pages and they solved by using one-to-one mapping class-names and keeping the specificity as low as possible. Here's more on that: https://speakerdeck.com/jonrohan/githubs-css-performance?slide=11 https://speakerdeck.com/jonrohan/githubs-css-performance?sli...
- SolarUpNote 13y agoThe author's wish is coming true. CSS techniques are already becoming unified through frameworks like Bootstrap and Foundation.
- sriharis 13y agoIt is not the frameworks that are bringing about the change. http://oocss.org/ http://oocss.org/ and http://smacss.com http://smacss.com are bringing about this change. Bootstrap's CSS techniques are written with a heavy bias on OOCSS, and by doing that it is setting a good example. I'll give you that.
- cespare 13y agoWas that Mixpanel css written by hand? Maybe it's just slightly inefficient css generated by sass/less/stylus.
- al2o3cr 13y agoThe way FB implements margins is terrible, there's nothing "semantic" about it - it's basically a single level of abstraction above whacking style tags onto elements directly.
- wyck 13y agoThis post is a little over the top, the examples are both legible and work, there is no need to get dramatic over CSS.
- analyst74 13y agoI don't completely agree with author's opinion. I think the Facebook Way (tm) has its pros, but using page-level specificity is a great way to avoid specificity hell. To be more specific, for a site with vastly different pages, it's best to have page or section level class that limits the scope of each css definition, so the person making change to one section of the site will not accidentally break other pages. Also, with little base style, there is less need to override styles with more specificity. For such a site, CSS like this tend to be easier to maintain: #home-page h2 { /* home page title styles / } .news-item h3 { / news item title / } #widget-page h2 { / widget page title / } .widget-item h3 { / individual widget title */ }
- protonfish 13y agoI agree this is a better way to do things, but if we want to be page-specific, why not use separate style sheets? I know we are supposed minimize the number of http requests but is having 2 external style sheets (1 for global styles and 1 for page-specific styles) really too many? It will prevent parsing every style for the entire site on every page load whether the page needs it nor not, plus decrease collisions and other maintenance problems caused by too much CSS in one bucket.
- Jormundir 13y agoI think you both have missed the point. When you code CSS the "facebook way" :(, you don't have to worry about bleeding effects. Want your h1 to have a margin of 35px or whatever? You give it the class large-margin or something. You don't have to worry about affecting other h1's, because they have the classes specific to the way they should be styled. When you style in the way the root comment is suggesting, you do have to worry about bleeding styles, because selecting h1 tags in one section may also style an additional h1 tag you didn't mean to style. The whole point is: don't select specific elements to style, rather, create classes of types of styles, and, when creating an element, select the classes of styles you want the elements to have. This way you don't worry about bleeding styles, each element has the classes representing how they are supposed to be styled, and you will never accidently over-select elements.
- fournm 13y agoI don't know, after dealing with hundreds of jsps and javascript files adding margins in all variety of ways when they should be a consistent size (that of course, has changed over time and not been changed everywhere) in an enterprise codebase I'll take the Facebook approach for margins any day over just directly modifying style properties..
- specialist 13y agoCSS did not, could not, solve the problem of disorganized, inefficient document production, typography, layout, style management, etc. Meaning, the Mixpanel abuse of styles is an old problem. What CSS has over most all DTP and word processing apps is that CSS is declarative and explicit and discoverable. With CSS, styling is source code, and can be managed as such. Or not, like Mixpanel apparently has done.
- nwienert 13y agoThis article is a few years behind the latest best practice. What this is is basically "Object Oriented CSS" that became popular years ago and was later refuted by many in the community for it's numerous downsides, namely in maintenance cost, code-clutter and slow performance on old browsers and mobile. With a preprocessor like SASS you can have OO and have semantic class names. Take that margin example. You could define class names that add varying types of margins. But you don't use them in HTML. You create a semantic class for specific use cases that @extend's the margin class you need. Now you have the best of both worlds. Less, semantic class names, with the flexibility and consistency of the OO style.
- chrischen 13y agoIt could be that Mixpanel is using something like LESS and nesting stuff for organization.
- gprasanth 13y agoI recently started working on UI development. Some useful stuff I found: 1. LESS - http://lesscss.org/ 2. LESS Elements - http://lesselements.com/ 3. Pure CSS - http://purecss.io/ [cool stuff, but not LESS.]
- russelluresti 13y agoWhile I will not argue that the mixpanel css is pretty bad (specifically the duplication making it harder to maintain and increasing the code size), but that margin example from FB is just as awful. I know that there's recently been a backlash against the entire idea of the "separation of concerns" - but having your markup define your style margins is a bit insane. If suddenly you wanted 10px margins instead of 5 you have to grep your entire codebase for .m∗s (limiting the length of the string to 3 characters) and updating all those to .m∗m (or just defining both .m∗s and .m∗m to be 10px, which is just as dumb). But, yes, most of the points in this article are somewhat accurate if not a bit outdated. Try not to use element selectors (and instead apply a class), avoid code duplication, write efficient selectors, etc. (Note: asterisk changed to low asterisk and I hate markdown or whatever other text styling syntax HN is using).
- Jormundir 13y agoIsn't what you're describing the easy way to change a site?
- russelluresti 13y agoNormally, sites will have more views than they have CSS objects. So if you're doing OOCSS it would be easier to just update all the objects (css files) instead of updating all the views.
- masklinn 13y ago> What if you want a h4 to look the same as a h3? What if you have two h3 tags that you want to style differently? Now you add customization classes to these special cases instead of shoving them every-fucking-where.
- pan69 13y agoIn my opinion CSS is very object oriented and the cascading nature of it is very much like inheritance. The problem is that a lot of CSS folk don't come from a programming background, let alone an object oriented programming background so "thinking in objects" isn't something they've learned. A good place to start doing well structured CSS is to separate the layout from the style. Doing this will give you a much better grip of your CSS and makes for easier future changes and adjustments.
- habosa 13y agoThe problem with the abstractions of Facebook is that you then need to always remember the "rules" of the website you're working on. If you're a Facebook software engineer adding a section to some docs somewhere, you have to thing "do we use .mbm or .mbl for our page headers? Damn, I'll check some other source". The ideal CSS, in my opinion, is just the opposite. The developer writes Plain Old HTML and includes a stylesheet, and the new page looks instantly consistent with the rest of the website. That's how you enable anyone to work on the project. If a new UI is needed, the designers will change the css and instantly all pages will look good.