10 ms·
Things to Avoid When Writing CSS
- gotchange 11y agoI have to disagree with the first two points and concur with the last two. Modularity can be achieved in CSS with ease (with Sass or any other capable preprocessor) and I do it all the time and I haven't come across a problem like he cited in his prose. The extended «@import» keyword/statement handles this perfectly and you can do wonders with it, you just have to keep a mental record of the hierarchy in your head (You already do that with the order of <link> and <style> elements as well as the CSS individual rules within a single file) and aim for well encapsulated components that are as loosely coupled as possible to the surroundings in the markup and you will have a true piece of mind. As with nesting, yeah this could be a source of annoyance and inconvenience but I usually set a ceiling of 3 levels deep maximum for any component with rare exceptions when the need arises but most of the time I don't exceed the 3 level nesting limit and the codebase is still very very manageable.
- emn13 11y agoThe issue with nesting rules like "max three" is that you really don't want 3 levels of nesting, you want zero. Setting an arbitrary cap isn't a bad coping mechanism, but you might end up with pervasive low-level nesting, even though you almost certainly don't need it. In almost all cases I see, when people nest with SASS (or less), they don't really mean "in this context, this item is styled like this", what they mean is "this item only ever exists in this context". And if you use nesting for that, then you have at least one of three problems: - it might be entirely redundant - as in you get exactly the same style if you just omit the surrounding selector blocks. This is quite common if you're using classes heavily. - it might be a "clever" way to avoid using a class name. This is terrible idea; it's not clever to call something `.frugal > div > span > span > b`, not even via nesting, it's simply undescriptive. Give the beast a name already, and use that. If you're after this style, why not use inline style tags? (No seriously - that's not as terrible as it sounds). - You've got too many catch-all selectors, and are fighting a selector specificity battle. Nesting here is again a really, really terrible solution, because you've just made the problem that much worse. Nobody is ever going to understand why the components layout breaks when they refactor if and one layer is added or removed. If your style depends delicately on these kinds of interactions, you're in a world of pain. Use @import, and consider refactoring your usage of general or catch-all selectors. I think its good advice to avoid nesting, especially more than one level of nesting. It's never necessary (just use compound selectors instead), and where compound selectors turn into a tedious, repetitive mess you've got techdebt you should be resolving, not making worse. Avoid doesn't mean "never use" - but if your css has even one instance of three-level deep nesting, I feel confident in suggesting that you're making things fancier than they need to be. Nobody likes that programmer that left behind his "clever" solution to save a few dozen keystrokes once, but that needs lots of context to understand, and that's exactly what nesting in SASS is.
- MatekCopatek 11y agoI find it funny that you suggest compound selectors as an alternative to nesting, since nesting exists primarily to avoid the repetitiveness of compound selectors. I can agree that it might encourage some people to nest more then if they did it by hand, but in my personal case, I was writing long compound selectors already. The ability to nest only made the styling DRY-er and gave it visual structure. High specificity is definitely an issue that needs to be dealt with, but I'm not sure the best solution is to stop using a feature that possibly encourages it but also brings many other useful things to the table. To end on a constructive note - don't forget you can use nesting to concatenate string names as well. .button { &-big {} } will produce .button-big {}, which means you can do some sort of visual nesting without producing unnecessary specificity.
- emn13 11y agoThe issue with nesting to hide compound selectors is that it's papering over a problem, not solving it. Hiding a problem tends to make it worse because it's easy to ignore it, and easy to make it much worse. Compound selectors are necessary for context-dependent styling; and all compound selectors are context dependent. Nesting is equivalent. However, context dependency makes it harder to reason about a layout, makes it harder to refactor, and makes it harder to reuse parts elsewhere. DRY-ness is vastly overrated in all programming languages; what matters is composability. You're not writing a compressor. DRY is simply a means to an end; being DRY helps composability because it means that changes to one part of your program don't necessitate changes to the repetitive parts elsewhere. If you need to extract that commonality - of course, do so! But it's much better if you can delete it outright, and in the case of SASS nesting that's almost always the case. For another perspective: every composition in a selector is essentially a nested if in the "program" that is your styles. Do you really need nested ifs all over the place? If someone changes the html structure a bit, are they going to be surprised by which styles match if they fails to keep the styles side-by-side? If you're nesting styles, your styles are likely extremely tightly coupled with your html structure, and any changes that don't in details dovetail with changes to the styles will cause unpredictable consequences. If you're going to do that, consider something like [radium](http://projects.formidablelabs.com/radium/ http://projects.formidablelabs.com/radium/) - i.e. inline styles. But you're probably best off combining that with conventional styles for all the easy, reusable bits.
- nitin_flanker 11y agoI have been using a percentage value to set width size for four year, since the day I first used HTML. I used to get confused with pixel. Percentage provides me a better estimate always.
- acjohnson55 11y agoMultiple files as an antipattern? Good luck with that. If you use BEM, one of the many React style libraries, or any similar methodology for simulating local scope, any big problems with multiple files evaporate, and you get to reap the rewards of modularity. Granted, you still inherit styles from parent document elements, breaking modularity a bit, but for my purposes, it's close enough. As a bonus, almost any perceived need to nest styles is also obviated. On a side note, I found the tone of the article pretty obnoxious.
- marrs 11y agoI think it's often an anti-pattern. A good acid test for me would be, will modifying a rule written to a selector in one file affect a selector in another. If the answer is yes, then you haven't modularised by definition; you just think you have. This gets more complicated if you are doing SASS-style inheritance between selectors.
- gotchange 11y ago> will modifying a rule written to a selector in one file affect a selector in another. Actually this is how it's supposed to work in terms of code reusability and implicit inheritance. You change a detail in one dependency and that change propagates through the chain to every other dependent object. The trick is whether that change is intentional or not. When intentional, this is a sign of a good architecture and vice versa and the poor performance can be simply dealt with via good encapsulation to avoid future leaks.
- marrs 11y agoThe "good architecture" there is to begin by making things general and then build specialisation on top of that. This is essentially what the author was saying. At that point its an implementation detail if you have your CSS in one file or many. I think what the author is talking about is when you choose a module structure that is orthogonal to that. That is the square peg that he is referring to, by my interpretation.
- forgotmypassw 11y ago>A lot of web development seems to be about splitting things up into manageable chunks or “components”. [...] This doesn’t work so well for CSS. I'm not a web developer by any means but I'm pretty sure there's a way to manage CSS "components" that then are compiled into a single, minified stylesheet, no?
- igvadaimon 11y agoI think what author meant here is order of those compiled files. For example, when 'media_queries.css' comes before 'main.css', those media queries will be most likely overwritten.
- lojack 11y agoTypically, you'd have a css file that serves as an entrypoint that you'd then use to specify the order of the files to include. Additionally, while it sometimes makes sense to rely on order of your CSS selectors (e.g. media queries), this can easily be an anti-pattern. Keeping a single file well organized helps as long as you maintain the organization. Splitting things into separate files can enforce this organization.
- forgotmypassw 11y agoI understand that but there surely must be a way to account for that, I'd imagine something like telling the tool to "don't override this section", or "this one overrides that one, but not the other way around" should be an option.
- micheleb 11y agoyeah, but the point is that it's very easy to forget about adding these rules because of the very complexity that motivated splitting CSS into several files in the first place
- gotchange 11y agoThis where the «!important» flag shines through but it gets a lot of hate in the community but I am seriously not convinced with their reasoning and arguments put forth as they seem not fully aware of the standard order of conflict resolution in dealing with cascading and inheritance in the language.
- arnold_palmur 11y agoI prefer using rems over ems, as ems are a pain to deal with for large applications (due to the nature of compounding).
- emn13 11y agoHowever, rems don't compose as nicely. It kind of depends what you're building. E.g, if you're in a footnote or any context where the font-size differs from your general default, it's quite likely that whatever content you want to embed there also needs measurements that scale - you want ems, not rems. The nature of compounding really shouldn't be an issue - because if that's an issue, then your font size is going to be an issue in any case. I'd say rems are appropriate when you're making a component that has little to do with it's context. If you're conceptually emulating an iframe, then you probably don't care about the scale you came from. Most pages have a few components like this, but they tend to be the exceptions, not the rule.
- arnold_palmur 11y agoRight right - I'm working on a large framework (built-in ember) where everything is components, hence the appropriateness of rems. That being said, I'm not sure I follow your example about the footnote - I don't see any difference from what you are gaining with ems vs. rems as rems are also going to scale. The scaling would be from the root vs. the parent element which to me seems much more manageable allowing you avoid having to calculate the result of compounding needed to achieve your desired font-size.
- emn13 11y agoWell, if you're going to use ems, you probably should think about compounding the reverse way - don't say, "I want X absolute font size, what scale do I need", instead say "I want something smaller. In the footnote example, imagine you'd want to include a button. That button will contain text, and that text should be just as large as surrounding text (or a bit larger - it doesn't matter for this case). You want to specify button layout using ems so that the button is reusable both in the small-font footnote context, and in the large-font body text context. Even moreso, if you decide than the footnote font needs changing, your button will scale naturally, rather than needing you to adjust the rem-based scale.
- poxrud 11y agoUsing sass splitting files is not a big deal. The author is living in the past, component based CSS is becoming the norm. For more info I'd suggest reading about SMACSS by Jonathan Snook.
- TheAceOfHearts 11y agoI'm on mobile, so I'm unable to link to it, but Google CSS modules. Seriously, it's a godsend for achieving true modularity.
- thebouv 11y ago"Considering it’s a point of professional pride to avoid nested structures as much as possible in other languages..." Nested loops can be bad. Nesting logic deeply in other languages is bad. Nesting style rules that belong together, well, together isn't nesting as much as it is putting like stuff together. I may create section.myawesomesection {...} and everything to do with the stuff in there is in there, not leaking out. I don't accidentally use a class name used somewhere else and globally change it, I don't change all global UL tags to be flat, inline, no list-style. I change them in context of section.myawesomesection. Not to mention allowing me to put my breakpoints together in context (particularly useful with a mixin like breakpoint(small) or something). Yes you can really go nuts with the nesting and create a giant pile of crap. But then that's you being a bad planner (not even going to say coder here, as CSS/SASS is more about planning than coding).
- stoikerty 11y agoI agree, nesting has been one of the most helpful parts in SASS to keep everything organised. Nestin is just harder to do right, you need some experience in organising files. Even with the specifity I vastly prefer nesting to a bunch of files with flat selectors and a huge amount of globals where you need a lot of time just to understand which elements affect which. The post is quite opinionated and puts every issue in a bucket, as if there is only one way to write CSS. A few examples would have been useful. Not using Nesting is the worst offender in the list.
- marrs 11y agoThe trouble is that untangling nested selectors can be a real challenge, especially if you have inheritance between them, and the implications can be chronic. On a project I was working on recently, a colleague reported to the team that the addition of one line of code to a SCSS file resulted in an increase in size of the target CSS by 800KB. Looking at the spaghetti code that had been written, none of us could work out how many rules were being combined out of the deceptively clean looking SCSS. A recommendation for that project was to lint for some ground rules forbidding certain behaviours, nesting being one of them. I've actually been considering avoiding SASS altogether in the future.
- k8tte 11y agothe author seems to be missing what HTTP/2 brings to the table [1] #1: https://http2.github.io/faq/#why-revise-http https://http2.github.io/faq/#why-revise-http
- canyonero 11y agoThis article demonstrates that the author has not worked a large-scale web application. Modularity in CSS has been difficult to acheive, and there has yet to be a perfect solution. However, I'll gladly work with an intermittent solution. If I stepped into a project that followed these recommendations for building an app of scale, I'd likely go insane.
- bshimmin 11y agoPeople said the same thing - that the author had not worked on a large-scale project - when he wrote this utterly insane piece about eschewing classes: http://www.smashingmagazine.com/2012/06/classes-where-were-going-we-dont-need-classes/ http://www.smashingmagazine.com/2012/06/classes-where-were-g... I think maybe he just enjoys being controversial. I have no idea how anyone could really encourage multiple developers to work on a project with a single CSS file - it seems practically almost impossible to me.
- err4nt 11y agoI dunno, I write CSS for a living so I got nervous when I saw the title, but when I read it I can tell this is advice from the frontlines. This guys understands CSS, and if you actually understand CSS you dont need tools like SASS, and you dont need rigid structures like BEM. The most beautiful (and seemingly ignored) aspect of CSS is that specificty cascade. Everybody seems to be trying to isolate their CSS into modules so they dont conflict instead of using the CSS together in harmony. After writing thousands upon thousands upon thousands of lines of CSS here are my quick opinions: - 1 global CSS files should take care of 95% of the styling, and if a specific views needs to override that global style, give it a teenty tiny bit of CSS - SASS is cool, but largely unnecessary, and so I believe that 80% of the time people use it it just creates more work (learning curve, project requirements, compliation step) than it saves. Again, I write CSS for a living and I have never found a place where SASS sould have saved me work if you actually know how to write CSS. - Nesting is awful, thats not how CSS works. I could abuse indents and arbitrarily block my code in JavaScript and if I did that everybody would assume I was an amateur who didnt know what I was doing. When I see nested CSS I go on high alert for bugs because it is clear the author doesnt understand CSS - while IDs and classes can be useful, So many frameworks now work in a way that they write all of the styles you might nedd in advance and then you 'tag' which elements get which styles ising classes. This is literally no better than inline styles, and is an abuse of HTML in an attempt to not have to write a small amount of CSS. If your markup is CLEAN and simplethen styling it with CSS is also very straightforward. I havent read the authors piece but in the past year I have noticed a drastic reduction in my own use of classes and other identifiers in HTML as my understanding of more advanced CSS selectors has increased. CSS is a beautiful, POWERFUL language, and I would recommend everybody to do a few things: - stop using CSS you didnt author - write your CSS by hand (no SASS, STYLUS, LESS) - Only ever copy-paste code youve written, if youre bringing external CSS into your codebase, retype what you need from it. I know those sound like youre going to be sitting there forever typing in thousands of lines of CSS, but operating that way VERY QUICKLY forces you to gain skill at discerning what is actually required or not. Whenever I do responsive consulting I feel like most sites are 5x overbuilt in the HTML, which means that your CSS is many many times longer than it needs to be. The biggest bottleneck to CSS simplicity is poorly thought out HTML markup.
- blowski 11y agoAs the author says, in SASS, nesting that produces deeply nested selectors like `body#homepage header .navbar:first-child li>a` should definitely be avoided. However, you can do BEM style selectors quite neatly in SASS: .navbar { &__element { &__hover { ... } } } which will produce a selector like: .navbar__element__hover { ... } This is a great compromise between readability, maintainability and performance. Also, the first point about keeping all your CSS in the same file works for smaller projects. But on bigger projects, managing a 5000 line CSS file is a nightmare. Better to break your project into multiple files, and import them as mixins or straight includes. Again, using BEM-style CSS helps with that. In the end, managing CSS is always a pain whatever approach you use. Too much of the advice on CSS doesn't talk about the context in which to apply or ignore the advice. What works for for a massive team working on a high-profile, big-budget, mission critical website will be enormous overkill for a small project with one front end developer.
- emn13 11y agoWhat's the motivation to pick .navbar { &__element { &__hover { ... } } } over .navbar__element__hover { ... } ?
- blowski 11y agoAssuming that .navbar contains lots of elements, and those elements have lots of modifiers, then repeatedly writing .navbar__ is not very DRY. Want to change .navbar to .primary-navbar? You have to change it for every selector in that block.
- marrs 11y agoI would actually argue that DRYness is to be avoided in this case. How many selectors you are specifying, and what they are, is something you should be explicitly aware of. You may find that your DRY SASS is producing very non-DRY CSS.
- paulojreis 11y agoI like and use that way of writing compound, nomenclature-based, selectors in SASS. There's a catch, though: you wouldn't find your style definitions by searching via the resulting selector (e.g. .navbar__element__hover). It's a smaller problem when you have the CSS split across files, but it's a problem nonetheless.
- mosselman 11y agoThere is nothing wrong with nesting in SASS. As with anything in life you just have to keep thinking about what you are doing. Nesting too much or to deep can make things hard to maintain or debug, but you can't say 'nesting is evil' just because you think you are not supposed to like it.
- mdc2161 11y ago"Then, when I wanted to scale things up at a min-width breakpoint, I’d just adjust the root font size, upon which everything else is proportionately based." The problem is that scaling everything up or down proportionally looks bad. https://css-tricks.com/rems-ems/ https://css-tricks.com/rems-ems/
- auvrw 11y agoonly recently started using less.js and thought nesting was helpful: i had a not-so-well organized css file, and systematic nesting quickly enforced a sensible grouping of statements. also, if you want to change an id attr in your html, say, being thorough about nesting ensures that you only have to change your styles in one place. that's a small win for maintainability? i agree that mixins are a much cooler feature of less/sass than nesting. it's not so much that avoiding nested structures is "a point of pride" in general-purpose programming languages (certainly not in lisp!) as it is that logical modularity makes stuff easier to read, maintain, and reuse. and as a practical matter, i can see how nested styles could make things difficult to read if there are too many levels of indentation.
- lsdafjklsd 11y agoThe no nesting thing is huge! We refactored a lot of CSS earlier this year and that was one of the biggest pain points. Coupling the structure of your template to your CSS makes changing things very painful. Nesting also creates ambiguous classes that have no obvious connection, consider the following: .my-component { .header { ... } } You would just see header floating around in the markup, unsure of where it's namespaced. Also I disagree that you shouldn't modularize your CSS. We now create a CSS file who's name corresponds with the class name. /styles /components my-component.css and in the markup <div class=".MyComponent-wrap"> <div class=".MyComponent-title"> ... </div> </div> With CSS like that you always know where a style is declared, and the order of the classes do not matter. More on the issue: http://nicolasgallagher.com/about-html-semantics-front-end-architecture/ http://nicolasgallagher.com/about-html-semantics-front-end-a...
- marrs 11y agoI tend to avoid nesting as well now. Wrt your modularisation, that seems like a reasonable approach, although where do rules go if you have nested components? From my experience, modularity really starts to bite when you also have inheritance. For a simple case, you have a module A that contains class rules that are used as prototypes for rules in other modules. You want to modify behaviour. Where do you modify it, in the prototype or in the subtype? The answer isn't always obvious and sometimes 2 conflicting answers can be correct depending on the metaphor used for deciding how to modularise. That's a simple case. A complex could be one where module A extends class rules from module B and module B extends class rules from module A. What happens when two rules extend each other? I've seen this in action, by the way. The SASS compiled without error so one presumes that there is a limit put on the recursion.
- Rezo 11y agoI've recently started keeping my CSS together with the UI components that I create in React. Essentially doing what is being advocated here: https://speakerdeck.com/vjeux/react-css-in-js https://speakerdeck.com/vjeux/react-css-in-js It defies existing good practices, but once I tried it I quickly realized that things that are tricky in CSS are mostly trivial in JS (namespacing, dependencies, code elimination / minification, isolation, constants, the whole tooling in general etc.). As a programmer and not a designer, I also find it easier to reason about JS. You end with something that looks very much like Web Components, but fully usable right now. In practice it means you can add a 3rd party component with "import TimePicker from 'material-ui/timepicker'", slap a <TimePicker/> into your JSX and you're done. See http://material-ui.com/ http://material-ui.com/ for a complete toolkit of React components created this way.
- rimantas 11y agoYou won't learn anything useful from this article, move on.
- bbx 11y agoMultiple files Considering everything is global in CSS, the importing order isn't important. It only is when using Sass where you have variables and mixins that must be defined before using them. And with Sass, it's very easy to setup separate files that you import all at once in a single file. Structure example: http://tech.streethub.com/styleguide/css/app.html http://tech.streethub.com/styleguide/css/app.html Nesting One of the biggest issue you encounter when writing CSS is _specificity_. Not only does nesting allow to match your Sass hierarchy with the HTML one, but it also naturally creates more specific selectors that saves you from keeping mind which rules are going to be applied. Pixel units Oh yes, using "em" is very elegant... but a pain in the long run. Font sizes need precise pixels to render correctly. Images need pixels for alignment. Borders need to be defined in pixels or end up disappearing. And you'll avoid crazy calculations with 4 decimals. I actually just wrote an article about it: http://jgthms.com/in-css-use-pixels-not-em.html http://jgthms.com/in-css-use-pixels-not-em.html Device breakpoints Breakpoints aren't meant for _devices_ but for your _element's_ size. It doesn't matter how your layout will end up looking on a 320px-wide screen. What matters is how your element will look like until 500px, and beyond that. With Sass I have 2 responsive mixins: +from($breakpoint) and +until($breakpoint). That's all you need.
- zaphar 11y agoThis is actually not strictly true and can trip you up if you aren't careful. Two rules with the same specificity depend use last one wins. In that case import order matters.
- untog 11y agoI have to disagree heavily with the idea that all CSS should be in one file. Therein lies madness. Use multiple files, and be sensible about it - scoping each file in a way that it won't overwrite other files.
- stevewilhelm 11y agoIt seems to me there is something wrong with a technology when how to apply it in its most basic and fundamental use cases is so controversial.
- deleted 11y ago[deleted]
- Loque 11y agoThe rationale from this post for not-nesting is incomplete and I personally think nesting has advantages (grouping markup together and mixins for example). Sure avoid the pyramid of doom and unnecessary nesting, but in general, nesting is not bad. Aside, BEM is a nice pattern but doesn't need to be followed religiously, you could say the same for most patterns; put together the best for your project/problem you are trying to solve... and if you have time, understand all the design decisions behind a pattern in order to do so appropriately. imvho