10 ms·
Show HN: I decided to document and share my high-level CSS best practices
- iaskwhy 15y agoWhy "We use hyphen delimited, lowercase selectors: .thisIsBad{}, .this_is_also_bad{} but .this-is-correct{}"? I understand if the point is about the styles itself having hyphens, like padding-bottom, but it breaks the complete expression selection with ctrl+arrows (or even with the double mouse click) which I find much more annoying than using underscores instead of hyphens. I'm biased though, I prefer underscores to camelCase anytime (I do obey whatever is the rule on any project).
- csswizardry 15y agoNo reason other than that is what I started off with and I’d rather keep things consistent. Had I started off with underscores then I’d be asking the team to stick with that. I guess that section is more about ‘keep everything the same’ rather than ‘we must specifically use hyphens’ :) Cheers, H
- bung 15y agoI recently brought this up with my own team after updating a 4-language piece on a project. It was originally pieced together at different times and was inconsistent. However, I was testing the waters with them trying to sell them on underscores. 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 :)
- MatthewPhillips 15y agoUnderscores in JavaScript are non-standard too.
- edd 15y agoThe reason I would advocate using hyphens is you should do what the language (standard libraries) do. For example: css: margin-left, border-bottom (hyphenate) javascript: getElementById, documentNode (lower camel case) ruby: each_index, has_key? (underscore)
- iaskwhy 15y agoThis would be an interesting discussion. I prefer to use the same coding style for the whole project without caring how the original authors of each language did it. I do however understand that the language API follows the original convention so one would eventually break it by following by reasoning. Ex in js: make_element_slide(getElementById('box')).
- tomjen3 15y agoI break about half of those rules and it works very, very well. Please don't label things that can be discussed as 'best practices'. One day some newbie will wonder across it, take it as gospel, and then will screw up projects by applying them when they don't make sense. 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.
- csswizardry 15y ago> Please don't label things that can be discussed as 'best practices'. 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
- johncoltrane 15y agoSo you are neatly packaging your knowledge, publishing it and marketing it (at least here and on reddit, not the smallest websites, possibly elsewhere) but somehow it's still a "personal document" and your "best practices" shouldn't be followed? > "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.
- csswizardry 15y agoI see your point. This started off as a personal/close-knit reference for me and my teams’ best practices. Then I thought I might as well share it, even if only one other person finds it useful then that’s better than keeping it to myself. I packaged it with caveats and disclaimers and you can take the advice or leave it. 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.
- MatthewPhillips 15y agoThanks for this. This is extremely useful for non-designers.
- timmyd 15y ago`Whilst this is a very timid example, it does help illustrate how a lot of preprocessors’ built in ‘helpful’ aspects actually go against our ideals; .nav li a{} could (and should) just be .nav a{}.` Not if .nav li a{} and .nav a{} are specifically meant to be differing nests. They could but might not 'should'
- csswizardry 15y ago> Not if .nav li a{} and .nav a{} are specifically meant to be differing nests. But in the example they aren’t differing nests; if you change your example then obviously it isn’t correct any more.
- fourspace 15y agoIf you're truly reusing the example from above, shouldn't it be: .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 {}
- csswizardry 15y agoBecause `.nav li a{}` is overly specific; that’s my whole point. 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{} }
- fourspace 15y agoCool, we're on the same page. =)
- puppybeard 15y agoSome nice ideas, but not many new ones. And the new ones don't always make sense: "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?
- csswizardry 15y ago> that made my teeth itch 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…
- puppybeard 15y agoThe "teeth itch" thing: It feels too much like over-ornamentation. It just wouldn't suit my style of work. I find it much faster to scan css when everything is vertically aligned. If I have to scan left and right as well as up and down, it takes me longer, and comparisons are slower.
- grannyg00se 15y agoIt could also lead to lazy naming. I'd prefer to see intelligent names used instead. If your css is tab-synched with your markup you might be tempted to lazily name your attributes assuming that people will figure out due to the tabbing. But your css should make some kind of sense independent of the markup. 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.
- juddlyon 15y agoThe advice to be explicit when using shorthand is excellent. This has come back to bite me many times (you end up re-writing background and margin declarations to undo your clever shorthand). 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?
- csswizardry 15y agoThanks for the comment, I’m glad you like it :) The shorthand one is a really interesting one; it takes while to kick the habit and be purposely more verbose, but you soon get tired of undoing previously accidentally-set styles. > 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/ http://warpspire.com/posts/kss/ though :) H
- mhartl 15y agoI'm surprised by the lack of spaces in, say, .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.
- jastuk 15y agoPersonally, I prefer the non-spaced variant when dealing with one-lined css. Simply because grouping it visually in chunks makes it easier for me to skim through code. 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; }
- jacobr 15y agoI don't understand how anyone using version control can use one liner CSS. There is code folding in all decent text editors.
- shazow 15y agoHere is a very petty point that isn't mentioned in the guidelines, but implied by example: Is there a good reason why people don't like putting a space after a colon? Such as... 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?
- csswizardry 15y agoFor me it is purely habit. I think: to each their own, just aim for consistency :)
- bbx 15y agoI always write 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?!).
- beaumartinez 15y agoI'd never thought of it that way. However, for me, 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.
- elefont2 15y agoHis advice for using 'short selectors' for performance is just plain incorrect. http://code.google.com/speed/page-speed/docs/rendering.html 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)
- rimantas 15y agoI don't want to see any advice about CSS from someone not wanting to see IDs. This is beyond stupid.
- puppybeard 15y agoThat one really bewildered me too. Suddenly there's no motive for having a unique element on a page, and styling it's children accordingly? Nonsense.
- isleyaardvark 15y agoIt is really easy to shoot yourself in the foot when you add ids to the mix, and there's nothing CSS-wise you can do with ids that you can't do with classes. 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-are-killing-us http://www.slideshare.net/stubbornella/our-best-practices-ar...
- LocalPCGuy 15y agoI recently worked on a project with a relatively new to CSS developer, and I forgot how much people rely on IDs. I almost gave that person a blanket statement to not use IDs, but I guided him towards reusable classes instead. 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.
- csmeder 15y ago> We use hyphen delimited, > 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
- indubitably 15y agoI don’t like .this-is-correct{} because sometimes you have the same variable name in Javascript too, where dashes won’t work.
- intranation 15y agoDashes map more cleanly to existing CSS syntax, eg nth-child, background-color, etc. Much like camelCase looks more like Javascript than my_variable.
- harisenbon 15y agoI do something similar, where I use hyphens to delineate ideas and sub ideas (table-striped) but use camelCase when one of the class parts contains multiple words. (form-addUser) 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.
- awj 15y agoOne tiny tip I have is to use underscores in ids and hyphens in classes. That way if I see $(".things-to-find") the fact that "thing-to-find" is not recognizable as a javascript variable gives that much more of an indication that it will be (relatively) expensive. Likewise #doodad_im_styling looks bad in css files since it doesn't match anything else. Granted I violate both of these principles, when appropriate, but they're there to keep the average case in line.
- crazygringo 15y agoThis is fantastic. While I disagree with some things (I'd rather standardize on px for everything, since em's have also been a huge headache for font-sizes), I love seeing the fact that this document exists. 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.
- tomjen3 15y ago>consensus-best-CSS-practices standard out there 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.
- jader201 15y agoWhile I would never advocate developers not thinking for themselves, I think it's shallow to say that seeking out and following best practices is an excuse to not think. 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-does-opinionated-software-really-mean http://programmers.stackexchange.com/questions/12182/what-do...
- goblin89 15y agoBest practices is a useful tool for developers to switch their minds on to real problems. I don't want to think how to align vendor-specific styles, whether to use a class or ID here, whether to create IE-specific stylesheet or not. 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.
- kapowaz 15y ago> For each level of markup nesting, try and indent your CSS to match. 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.
- 15y ago
- CoryMathews 15y ago2 things I would change. 1. There should never be a css reset, normalize is better. https://github.com/necolas/normalize.css https://github.com/necolas/normalize.css or with IE6/7 junk removed: https://github.com/CoryMathews/normalize.css https://github.com/CoryMathews/normalize.css 2. Structure the file in the method mentioned http://smacss.com/book/categorizing http://smacss.com/book/categorizing "So there would be 5 basic areas in your stylesheet. Base Layout Module State Theme"
- Random_Person 15y agoThanks for the normalize link. I learned more about various browser inconsistencies from their comments than I have from months of self study.
- kristianc 15y agoThanks for the categorising link too. That's something which I've often wondered/changed my mind about - and the OP doesn't offer much in the way of insight on it.
- rhaphazard 15y agoCould someone perhaps take the relevant suggestions from this HN discussion and modify a fork of the repo? I would do it myself, but I don't think I am proficient enough at CSS to sift through the comments effectively.
- camslizzle 15y agothat's good idea. i have written a bunch of my own guidelines which i'm going to beef up with some of these. the problem with creating a list of the 'relevant' suggestions is that it differs for every developer, project and company. someone's 'relevant' may be another's 'pointless'
- ebr4him 15y agoMight as well add a "formatting" section and include some tips on ways to format css. Also tools like procssor.com or cleancss.com
- brawley 15y agoyou lost me when you banned IDs. learn how to use specificity properly before claiming you have best practices.
- Alexandervn 15y agoHe does know how specificity works, I guess. But he is talking about reusability and inheritance. Still I find the claim way too harsh. I use id's in my CSS occassionally. For #wrapper or #carroussel maybe. It it premature optimization to (re-)write everything to classes. Your HTML should be leading.
- TiredOfTat 15y agoWelcome to the dark ages of CSS3! Where you have extremely emotional documents like this one, instead of programmer specs to follow. Does lining up colons have anything to do with anything? Of course not. 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.
- Random_Person 15y agoI'm a relative newb at CSS as I just launched my site last October... I'm mostly self-taught and I LOVE reading stuff like this. Can I beg you for a response? >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?
- csswizardry 15y agoI’ve honestly never heard of that being advocated; I’d drop that ASAP if I were you. If you want to ensure there is no page jump as images load then simply give the images width and height attributes :) H
- Random_Person 15y agoI do that already because that just makes sense, but I've been working to clean up my super-newb CSS recently and I'm trying to make it more manageable. I've been using trial and error for the stuff I'm unsure of but that one says it's !important and I didn't want to tempt fate. :D I'll cut it and see what happens.
- jjcm 15y agoIf you're this concerned about the readability and/or modularity of your code, you should be using a css preprocessor like less/sass/scss. Even if you have css all dolled up like this, it will still take longer to update and manage than it would if you were using mixins and variable declarations. 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.
- drynotoo 15y ago> When building components try and keep a DRY, OO frame of mind. 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.
- duggi 15y agolining up the colons to make life easier for block editors ... le sigh. i just cant take anything else seriously after that.
- samgro 15y agoAny "CSS Best Practices" guide should start with "1. Use a preprocessor." 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.
- csswizardry 15y agoI wrote a rebuttal http://csswizardry.com/2012/03/hacker-news-rebuttal/ http://csswizardry.com/2012/03/hacker-news-rebuttal/
- camslizzle 15y agoSome great general rules here, although I don't employ all of them personally, will definitely be using some to beef up my own guidelines. Cheers!
- soilysound 15y agoI also work for Sky (different part) and these guidelines seem mostly sensible to me, so much so I may recommend them to my team, with some caveats: - 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.