Show HN: I decided to document and share my high-level CSS best practices
github.com
github.com
.error{ color:red; }
I much prefer .error { color: red; }
or .error {
color: red;
}
(The latter is particularly nice because it implicitly acknowledges the likelihood that additional rules will be added.)I don't recall seeing the space-compressed version much in the old days. Is it a new trend? I don't like it.
Here I can recognize 4 chunks almost immediately:
.error{ width:350px; height:200px; color:red; background:blue; }
While here everything gets mixed up due to its uniformed spacing: .error { width: 350px; height: 200px; color: red; background: blue; }Also there is nothing wrong with magic numbers so long as you don't use them where a % would be more appropriate (e.g this text is 12px, because it looks nice). If CSS is used with out a pre-processor you have to use them, as there is no concept of variables.
This is valid point, however In the README there is the line ‘This document is a personal one, and for use at my place of work […] this is a document for me and Sky. You do not have to follow the advice given, nor do I provide any guarantee.’
In the context of our team I can afford to make more sweeping statements because I have the ability to discuss and expand on the caveats. Perhaps this document becomes less useful in places without that context.
> e.g this text is 12px, because it looks nice
This is not an example of a magic number, this is a design decision that was made regardless of code. Perhaps I need to me more clear on what a magic number is, but by that I mean anything that has no reason for being.
Cheers for the feedback, I might look at rewording some bits for clarity :)
H
> "In the context of our team I can afford to make more sweeping statements"
As soon as you publish your document and market it the context of your statements changes. A lot. Think about all the *-killers that pop up every single day: the Internet loves to bash them when they fail.
A document was created for a small audience, sharing it was secondary, and an afterthought. It is not up to me to decide who follows them and who doesn’t; I merely made them public and people have the ability to pick, choose or even ignore at will.
It would be better if you viewed your code less emotionally, and focused on getting the job done. Maybe then you'd be more productive?
Can you go into more detail about which rules you disagree with or find unnecessary?
CamelCase vs using-dashes is strictly a developer preference. I happen to agree with the author of the doc about using dashes, but I'm not going to call my preference a "best practice". A "best practice" might be more akin to "if you're working on an already in progress project, don't start doing CamelCase if they're using-dashes, or vice-versa", IMO.
Another controversial one is whether or not to have each style on it's own line, or in the same line. The author prefers a new line for each style because it makes for easier diff-ing in version control. The argument could be made, however, that this style introduces too much whitespace and vastly reduces the number of styles you can view at one time, not to mention increasing the linecount of your stylesheet by at least a factor of 3. Neither is, IMO, a "best practice", it's just a developer preference (IME most devs do agree with this doc, however).
There's some other stuff that really just boils down to how the author prefers to read his CSS, and not really about how to structure it in a proven optimal way. I believe it's hard to argue that those are "best practices", something Wikipedia describes as "consistently shown results superior to those achieved with other means". I would like to see the argument that lining up your -webkit prefixed styles achieves this, for example.
Anyway, IMO, a lot of the recommendations in the doc are good advice, just mixed in with some personal preferences. Like the author wrote though, it is his personal best practices, so in that context I suppose these are Best Practices, only the scope is limited to just the author.
I suspect it is because I write HTML5 apps, rather than websites (distinguishing feature: HTML5 apps have no 'you don't have javascript' fallbacks and they can't reasonably have any.).
I've written my own guidelines similar to this for different workplaces, though never publicized them. It would be wonderful if there could be some kind of consensus-best-CSS-practices standard out there, much like people have standardized on a couple common CSS resets, etc.
I've found that client-side developers tend to differ drastically in philosophies behind CSS coding, especially ones with less experience.
In my opinion, CSS is one of the most "dangerous" languages out there -- more often misunderstood and misused than any other language I've ever come across, including VB6 -- and thus most needing a standardized set of best practices.
No no no no. Best practices becomes an excuse for developers to switch of their minds and not think. In all cases there are exceptions to the best practices but people always forget that.
The reason there are differences between what people prefer is that they work on different problems. That is a good thing and should be encouraged, not squashed.
In fact, some languages, like Rails, are considered opinionated by imposing certain practices and standards in order to streamline the repetitive implementations that most applications need. This frees the developer to focus and think more about the more complex and less repetitive tasks.
http://programmers.stackexchange.com/questions/12182/what-do...
While I can disagree with some points, I don't think it makes sense at all to express the disagreement. OP explicitly claimed that it's his best practices (not universal truth), and I think it's a very valuable thing to share anyway.
margin:0;
Instead of... margin: 0;
The latter looks much more natural to me (probably because I'm used to writing English and other syntaxes), so I don't believe there's an aesthetic benefit. Chrome Inspector and Firebug also prefer the latter, so I don't believe there's a tool benefit. If saving a byte before processing was an issue then we'd be hitting less CRs, so there's no real bandwidth benefit. I don't get it, but I keep seeing it more and more.Is there some benefit to no-space-after-colon that I haven't considered? Was it established as a standard somehow while I wasn't paying attention?
margin:0;
instead of margin: 0;
Here's why.The first reason I do is because you don't need to write that space. It doesn't seem like much but it makes a difference when you're writing up to more than 1000 lines for one CSS (I type every word using Notepad++).
Second reason is: by removing this space, it joins the property (margin) and the value (0) together. And because I write my CSS in lines, it makes a difference when scanning visually.
input { background:white; border:none; float:left; font-size:14px; margin:0; padding:5px; width:400px;}
is easier for me to scan than input { background: white; border: none; float: left; font-size: 14px; margin: 0; padding: 5px; width: 400px;}
because I can easily target any pair property/value.And the reason I don't mind the lack of space after the colon is probably because I'm French and in French there needs to be a space before and after a colon. So I guess that if I remove the one before I might as well get rid of the one after (for symmetry?!).
input,
select {
background: white;
border: none;
float: left;
font-size: 14px;
margin: 0;
padding: 5px;
width: 400px;
}
Is more readable—each rule and selector on its own line. I am biased as I use Vim and half-page scroll lots, and like an 80-character maximum, though.I compensate by ordering my properties alphabetically so I can scan horizontally to find any property (background and border come first, margin and padding are near the middle, text-transform and width are near the end...).
Not a bad idea... I'm stealing it.
The reason is because of shorthand: margin: 20px auto 10px; === works | margin:20pxauto10px; === fails
Therefore, putting the space after the colon is pure habit for spacing reasons.
Yes, I understand that margin:20px auto 50px; works. It's just habit and preference.
"For each level of markup nesting, try and indent your CSS to match" <= that made my teeth itch. Mostly just down to personal taste, but I really find it quicker to read css if only the values are indented. It's easier to compare nested classes that way, as repeated values would occupy more similar space.
"Also write vendor prefixed CSS so that colons all line up" <= not all vendor css3 values have the same structure, so this can't be a standard (eg: gradients, mixed border-radius)
I suppose whether or not you add conditional support for IE is a matter of taste. I prefer to handle IE the boilerplate way, with conditionals determining what class the html element has, and including appropriate styles in the main css. Why sacrifice good, standards-compliant css for dirty IE?
Fair enough; any reason as to why?
> not all vendor css3 definitions have the same structure, so this can't be a standard
Well if it can’t be done then it can’t be done…
Also, it confuses the functionality of the nesting (IMHO). When I look at
.nav
.nav li
.nav li span
It looks like the indents imply some kind of syntactic meaning. Is it tabbed because tabs now mean something? In which case the second line might be equivalent to .nav.nav li which it is not.
Usually an indent implies some kind of relation to the previous line. For example when you indent the body of a function it helps to indicate that the body is part of the function. There's a logical difference and most likely even a scope level difference. The indents that you are adding to CSS don't work that way because each new line starts its select with no concern for the line above.Also, there may be some deeply nested markup that doesn't require css except for the first and last level of nesting. Are you supposed to then have a series of empty tab levels in your css file? And then if you remove some of those nests in the markup, you have to remove them in the css? Not nice. The coupling provides no advantage.
Yes it is one more thing in the pipeline. But you should be minifying your CSS anyway, so you're already compiling your css in a way.
Also, don't use IDs? Really? The article referenced as a source for this claim ends with "Don’t stop using IDs, just be aware of where they can cause you headaches and know where to sensibly circumvent them. Anyone telling you not to use them at all is not wrong, but they’re definitely not right…"
That's good advice. Understanding how specificity works will make you realize, when designing your Twitter widget, relying on a selector ".tweet a" is unreliable, and use "a.tweet-link" instead.
Nope.
> Also write vendor prefixed CSS so that colons all line up
Nope.
> When building a new component write markup before CSS
Yes!
> Instead of building dozens of unique components, try and spot repeated design patterns abstract them; build these skeletons as base ‘objects’ and then peg classes onto these to extend their styling for more unique circumstances.
This is a bone of contention amongst front-end developers. If you're Facebook, and you have a deep and wide site architecture that would otherwise result in masses of duplication, this makes sense (although arguably using CSS preprocessors like LESS or SASS would make even more sense), but these rules do not make sense for small to medium sized sites. If anything, they encourage a thin layer of abstraction on what would otherwise be entirely presentational markup. You were on to something when you said start with your markup: classify your marked up elements by giving them IDs and classes according to what they are and what they do, and then declare rules for how things of that type want to look.
> All components should be left totally free of widths; your components should always remain fluid and their widths should be governed by a grid system.
Nope. Again, grid systems are something that should be used on a case-by-case basis, according to the nature of the site you're building.
> Heavily location-based selectors are bad for a number of reasons.
Nope. What you're arguing against is a rule that has a high degree of specificity. Naturally there is a sane limit to how specific a selector should be (if you want to avoid specificity wars) but `.sidebar h3 span` is not too specific a rule.
> An over-qualified selector is one like div.promo
Alternatively you might call this a self-documenting selector. If you're going to apply a class to multiple types of element and you want them to all inherit the same rules then sure, don't apply an element name too — otherwise you're adding classes which communicate zero information to a developer unfamiliar with the markup structure.
> Do not use IDs in CSS at all.
NOPE NOPE NOPE NOPE NOPE. Understand specificity rules. Write good selectors. Don't outright ban IDs just because you're not careful enough to write clean CSS.
> As a general rule, all layout and box-model rules can and will work without an IE stylesheet if you refactor and rework your CSS.
Hahahahahahahahahhaa.
I'll echo comments from others here; these are not ‘best-practices’ — they're just a set of arbitrary rules that you might find work for you, but you might find they don't. I'd argue that if you enforce these vigorously, your projects are succeeding in spite of these rules, not because of them.
This document is a personal one, and for use at my place of work. I decided to share it in the hope that it might be useful to others but if you disagree with anything please remember; this is a document for me and Sky. You do not have to follow the advice given, nor do I provide any guarantee. — https://github.com/csswizardry/CSS-Guidelines/blob/master/RE...
> Nope.
Fair enough.
> Nope.
Fair enough.
> If you're Facebook, and you have a deep and wide site architecture…
We’re not Facebook, but we are big.
> Nope. Again, grid systems are something that should be used on a case-by-case basis, according to the nature of the site you're building.
Okay, as mentioned this is doc used largely at my place of work where we do use a grid system. For places that don’t use one then this basically means ‘don’t apply dimensions to components; leave structure to parents and wrappers’. Hard coding dimensions on components should be avoided at all costs.
> Nope. What you're arguing against is a rule that has a high degree of specificity.
I’m not. Heavily location selectors hinder flexibility; components should not rely too heavily on where they live, they should be movable as easily as possible. Shorter, less location-dependent selectors aid this.
> Don't outright ban IDs just because you're not careful enough to write clean CSS.
I believe I’ve got my CSS nailed, thanks. IDs will only ever hinder a CSS developer; they offer zero benefit (where CSS is concerned) over a class, thus why would you ever bother using them? If all they can do is harm then just cut them out; even the most careful developers can get tripped up by the overly specific nature of IDs.
> Hahahahahahahahahhaa.
I’ve just finished the rebuild a massive front-end, the project as a whole took over a year. Number of IE stylesheets: 0. It can be done.
Then they're implicitly not ‘best practices’.
> We’re not Facebook, but we are big.
Then it's possibly appropriate. I remain unconvinced even in large projects but I do think CSS is lacking some important features that would make this kind of practice redundant; the kind of things that LESS and SASS provide, like variables and mixins.
> Heavily location selectors hinder flexibility; components should not rely too heavily on where they live, they should be movable as easily as possible.
This again makes presumptions about what kind of site you're building. If you're aiming for heavily modular, reusable components where you'll be repeating markup patterns throughout, it may be more appropriate. Nonetheless, the example you cited looked like a small, common pattern that is easily self-contained enough to be reused in this way.
> IDs will only ever hinder a CSS developer; they offer zero benefit (where CSS is concerned) over a class, thus why would you ever bother using them?
Specificity is an important part of the cascade, and a tool in your box. Being able to target an element with a higher priority than another without needlessly complicating the selector is a feature I wouldn't voluntarily give up just because of some nebulous claim of harm they might cause. Another reason is the same one I don't agree with stripping off element names; they are self-documenting and give developers clear, unavoidable signposts about the nature of the elements they're targeting.
> I’ve just finished the rebuild a massive front-end, the project as a whole took over a year. Number of IE stylesheets: 0. It can be done.
Every project is different. Some will accept layout degradation in older browsers. Some won't. Some will demand extravagant layout effects that require extra time and effort to get working well in IE6-8. To suggest that IE-specific stylesheets are something you should be striving to omit is to needlessly burden developers with (potentially) unreachable goals.
That's the crux of my problem with these ‘best practices’ — developers who've yet to spend a lot of time thinking about how to structure their CSS well could come across these and head off in all manner of wrongheaded directions. Maybe that's why there aren't any universally agreed-upon CSS best practices beyond more simple techniques; the general rule I take with me is ‘YMMV’.
It's definitely appropriate.
> This again makes presumptions about what kind of site you're building.
It doesn't matter whether you're building Facebook or the site for the window cleaner two doors down the road; you never want issues with maintenance, ever. Make sure you can move a person's wall post to a new location without issue, make sure Bob the window-cleaner can move a testimonial from the footer to the sidebar without issue. Size of project is wholly irrelevant.
> Specificity is an important part of the cascade.
It is, and an ID is the quickest way to f#&k with it. As is qualifying your selectors. You're tying yourself to commitments that you might not want to keep.
The things you are arguing against are the most fundamental in helping build maintainable websites.
1-ID's are the fastest CSS selector.
2-ID's are the fastest Xpath Selector.
3-ID's are the fastest JQuery selector.
4-ID's make your front-end test-able.
Without ID's, functional, integration, regression, and even load testing are many orders of magnitude more difficult. If you are worldly enough to be offering best practice advice, I assume you or your organization tests at some point in your process?
Point 1: The speed difference between a class and an ID is so, so slight that it's almost non-existent. The specificity difference between a class and an ID is massive.
Use a good clearfix. Avoid margins and use padding instead as much as possible to avoid issues with margin collapse. Be weary of inline-block.
Single line CSS’ problem is that a diff of it can be a little misleading.
Happy Cog does this (http://happycog.com/a/c/screen.css), Jason Santa Maria (http://v5.static.jasonsantamaria.com/c/screen.v2011083002.cs...), and many other well-respected designers.
1. There should never be a css reset, normalize is better.
https://github.com/necolas/normalize.css or with IE6/7 junk removed: https://github.com/CoryMathews/normalize.css
2. Structure the file in the method mentioned
http://smacss.com/book/categorizing
"So there would be 5 basic areas in your stylesheet.
Base Layout Module State Theme"
>All components should be left totally free of widths; your components should always remain fluid and their widths should be governed by a grid system.
Okay. I just got away from fixed widths and I like it, so I'm on board so far....
>Heights should never be be applied to elements. Never ever set heights on ps, uls, divs, anything.
Okay, but here's where I'm lost. I learned somewhat early on that for a container that will contain anything other than text, you should do something like:
.container{
height: auto !important;
height: 100px;
}
Supposedly this ensures that the page is pre-rendered okay before images and such are loaded. It may have been an IE6 workaround for something that I don't use anymore... whatever the reason it's still in my code, is it some rubbish that I should do away with?H
I'll cut it and see what happens.
The reason we're in the dark ages: we have a subset of front-end designers that are extremely emotional because their code is on display for all to see (View Source). So they take it very defensively, even tho most coders worth their salt aren't 'Emotional About Their Code'.
Also NEVER use pixels. For devices like the 2048pixel width iPad, your so-called Web 2.0 designs with static bitmaps are old school.
In the coming years, all of your graphics will be CSS3 graphics for all header graphics, backgrounds, etc. Bitmap is just too old school for multiple DPI requirements.
Currently you have to rely on an emotional HTML/CSS ninja to get anything done. Soon the CSS3 graphics will be beyond 'lining up colons' and be software generated. I can't wait. Maybe then the whining will end.
For an example of where ids can trip people up, start at slide 66 of this presentation: http://www.slideshare.net/stubbornella/our-best-practices-ar...
It all boils down to reusability though. If you have an ID, say for a #promoCol, sure, there may only be 1 promo column on the page now, but what happens when the client/designer says, hey we need a promoCol on the right side as well? Do you go back and refactor #promoCol to .promoCol (as it should have been originally, IMO), or just add #promoCol2?
Maybe a column is a bad example as you might be able to deduce ahead of time that there MIGHT be more than 1. But you could say that of just about any element on the page. Theater was mentioned, but I've worked on sites where we had to add a second theater second to a page (yah...I know, wasn't my call.)
I would even go so far as to say, if you use IDs in any significant factor in your CSS, you are doing it wrong. And it has absolutely nothing to do with knowing how to work specificity, and everything to do with the additional flexibility not using IDs provides you (or your co-workers) both during an initial build and down the line when maintaining or updating a project.
I love IDs because I don't need to think about changing a class to fix one page only to see the same class screw up another page.
Yeah, that's exactly what you do. Just because your new dev doesn't know how to refactor (and it's hardly even refactoring, it's like a two-line diff) doesn't mean we all shouldn't use IDs.
IDs have an extra bit of self-documentation when you use them - when I see #promoCol, I know instantly that there's just one promocol, and I don't have to worry about breaking the look of another promocol while I'm fiddling with the CSS in there. If there's a class, you don't know how many things it applies to until you've done a grep over your project.
- Have no problem with IDs if they're used correctly for unique items. The cascade should not be an issue. - Formatting of css and vendor prefixes - these aren't guidelines they're personal preferences. There's no appreciable maintenance benefit for any of them in my opinion. Each to their own.
I am in favour of dashes too, On a big project you might spend literally 100s of hours writing or editing css, using dashes will save you enough time in keystrokes to have a an extra long lunch by the end of it.
http://code.google.com/speed/page-speed/docs/rendering.html is a great page describing CSS performance.
Selectors like '.nav a' would not be allowed at all as a part of my team's CSS best practices, as it is a descendant selector that uses a tag as the key. (On the other hand, most sites, expecially non-dynamic sites, don't need to optimize CSS at all, as there are usually other things which are the bottleneck)
> lowercase selectors: .thisIsBad{},
> .this_is_also_bad{} but .this-is-correct{}.
.
I am a fan of mixing Camel Case and Dash Separated. I use Camel case for specific elements.
eg. ".addClientButton"
However, I use a mix of Camel Case and Dash Separated for IDs specifying a specific element in a specific part of the dom.
eg. "#newClientPanel-addClientButton"
.
I learned this method from looking at how apple.com does their styles on their check out screen. However, it doesn't look like they don't do it this way any more.
How do you handle making unique IDs? I guess I could switch to something like
.add-client-button and #new-client-panel_add-client-button
This also plays well with my IDE which splits word selection on a hyphen, so if i want to change form-addUser to form-removeMonkey, it's just a single selection, where as if it was form-add-user, I would have to actually drag to select the text.
I guess that section is more about ‘keep everything the same’ rather than ‘we must specifically use hyphens’ :)
Cheers, H
We've all been using dashes in CSS for so long, but nowadays I personally feel like I'm writing so much JS that I'm longing for underscores.
Downsides: 1. You have to press shift a lot more when writing css 2. ???
Upsides: 1. You can use the "same_name" in CSS and JS 2. You can double-click easily
Feel free to expand on this, we haven't made the change, it's just something that crossed my mind recently :)
css:
margin-left, border-bottom (hyphenate)
javascript:
getElementById, documentNode (lower camel case)
ruby:
each_index, has_key? (underscore)Granted I violate both of these principles, when appropriate, but they're there to keep the average case in line.
The multiple measurement units is cool too: particularly unitless line-height, magic numbers, and relying on parent box sizing.
Great stuff, thanks for sharing this. Couple questions:
Do you find indenting descendant selectors helpful?
For your comments, do you adhere to CSSDoc or any particular convention?
> Do you find indenting descendant selectors helpful?
Oftentimes yes; it can give a new developer more of a clue of the markup structure that a previous developer intended to be used. I can see at a glance that `x` needs to be in `y` but `a` needs to be a sibling of `b`. Of course you could just glean that yourself by looking at and reading all the selectors individually, but it’s nice to get an idea of structure at a glance.
> For your comments, do you adhere to CSSDoc or any particular convention?
Nothing official; I have my own habits but no documented standard. I like the look of http://warpspire.com/posts/kss/ though :)
H
Two different things here. OO can mean having excessive numbers of things (files, objects) to do something that can be done more clearly and consisely without them, and it could be argued that having additional files is less DRY if you don't need to provide the same amount of code. So it is good to be DRY before OO.
Not if .nav li a{} and .nav a{} are specifically meant to be differing nests. They could but might not 'should'
But in the example they aren’t differing nests; if you change your example then obviously it isn’t correct any more.
.nav {
li {}
a {}
}
If that's not the case, why is your first "nested" pure CSS example this: .nav a {}
instead of .nav li a {}EDIT Hold on, I think I get you… My example was an example of someone writing something incorrectly. An example of it being written correctly would indeed be:
.nav{
li{}
a{}
}