Hacker News new | past | comments | ask | show | jobs | submit login
Things to Avoid When Writing CSS (medium.com/heydon)
47 points by petrey on Oct 26, 2015 | hide | past | favorite | 72 comments



Multiple 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.


I 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.


> 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.


The "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.


"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).


I 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.


The 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.


Couldn't agree more there. I tend to avoid nesting more than 3 levels deep, because I don't want someone else looking at my code and cry.


That approach - nesting everything inside section.myawesomesection- would hurt:

a) Performance (rule matching gets significantly harder as you nest);

b) Maintainability (did a change in the mark-up? Then check the CSS to see if it still matches);

c) Code reuse (obviously).

Using a nomenclature-based solution such as BEM, in the other hand, would avoid all these issues (complex, slow and over-specific selectors; DOM dependence; ease of reuse) while still avoiding style leaks. I'd argue BEM is even better at avoiding leaks: if you change all your global <ul> inside your section.myawesomesection, then it will - eventually, sooner or later - leak to a <ul> which you didn't want to style.


a) Granted. But we're talking about a specificity after compiling to CSS of: section.myawesomesection { h2{..} } to section.myawesomesection h2 {..}. Definitely not wanting to create nests that are so deep the specificity is insane.

Could I have just given a class to the h2? Yep. But performance difference between h2.myclass{..} vs section.awesomesection h2{..}? Worth worrying over?

Of course, if there really is a difference, it would add up I suppose over a mega-site. So thanks for the food for thought. I'll have to weigh it versus developer happiness I get from the tidy style rules.

b) Well, if the markup changes, that can just as well change your CSS too.

At some point, some change in the markup, you're going to reexamine the CSS for it. It's not like you write the perfect CSS and walk away because it will always work with the document and all its iterations.

Of course, like you said, maintainability is an issue but it isn't exclusive to SASS or my use of nesting via section.myawesomesection either.

c) Styles that are in many places get noted and placed so they can be reused. But that one special snowflake of a rule that applies only to this section of content because my designer wants to especially call it out? The rule can be specific.

I'm not creating 200 line section.myawesomesection definitions. Reusable items are resuable. Specific items are specific (most often to overwrite a global style say like font, color, this specific absolutely positioned icon, etc). Generally a dozen lines or so. If longer, just like a function getting too long, and I rethink/rewrite.

d) I absolutely 100% will check out BEM. I'm no slave to SASS, nesting, or anything like that. I have no idea about BEM will happily switch if it is better.


Bear in mind that BEM (CSS-wise) is just a nomenclature. What it addresses is exactly excessive nesting and dependence between mark-up and styling.

It roughly means that you imply structure via naming conventions instead of nesting (e.g. if you have a box inside a block, you'd style it via single class such as .my-block__my-box, instead of the traditional nesting approach .my-block .my-box). You can - and should - still use SASS (or other preprocessor) with BEM.

Some interesting resources regarding this:

http://philipwalton.com/articles/css-architecture/

http://philipwalton.com/articles/side-effects-in-css/

http://philipwalton.com/articles/extending-styles/

http://benfrain.com/the-ten-commandments-of-sane-style-sheet...


> you'd style it via single class such as .my-block__my-box, instead of the traditional nesting approach .my-block .my-box)

What you basically accomplished here is to transfer the problem of complexity from one domain (CSS) to another (HTML) not solving it.

Even if Sass provides a visual way to emulate hierarchy by using the & operator and breaking up the name at the significant points for instance:

  .myblock
    &-mybox
      color: black
It would be still a mess on the HTML side and there isn't really an equivalent workaround for it with tools like Jade or others.

In the end, if the penalty of using a shallow nesting architecture is to increase the specificity score by 1-2 points, I'm willing to take it in exchange of a more readable and maintainable codebase whether in CSS or HTML domain.


There are tools you can use to avoid this problem. BEM libraries for templating languages abound. When I worked at HuffPost on the current desktop rendering engine, I designed everything to be a system of nested components within a layout, and it was a pretty simple effort to make a helper that each component automatically got that was preinitialized with the component name as the BEM block and then within the template, all you had to do was provide the BEM element names and optional modifiers, and it spit out all the necessary classes. I just grabbed a link to the first article on the main page, throw it in dev tools to see what I mean: http://www.huffingtonpost.com/entry/parts-of-persian-gulf-co....

It's not completely free of pain points, particularly when it came to the JS, where we had to resort to some explicit usage of full BEM names. But that was very minor compared to the organizational benefits in the styles and markup.


> What you basically accomplished here is to transfer the problem of complexity from one domain (CSS) to another (HTML) not solving it.

Nop. I'm eventually polluting the mark-up with extra and uglier classes, but that's it. A small price to pay for less coupling - just use a class to bind styles to an element. No need to consider "what if this is a child element of X or a sibling of Y?".

> In the end, if the penalty of using a shallow nesting architecture is to increase the specificity score by 1-2 points,

It's not. It's style leaking, dependence between different system parts (content structure and styles), performance, less reuse...


HTML & CSS are like Siamese twins, you can't separate the one from the other and there will always be coupling between them no matter what and the solution you suggested is not optimal in my opinion as I said earlier that what you'd manage to achieve with this is just to shift the burden from CSS to HTML and to turn the organizational/hierarchical problem in CSS to a greater and unpleasant naming one in HTML that I personally try to avoid as much as possible


> HTML & CSS are like Siamese twins, you can't separate the one from the other and there will always be coupling between them no matter what

Yes, there will always be coupling. What I'm suggesting is minimizing the coupling, by using classes as simple "binders" and by stopping the use and implying of DOM structure in CSS files.

> I said earlier that what you'd manage to achieve with this is just to shift the burden from CSS to HTML

I think you're missing the big picture. You use classes anyway, I just suggest a) accepting them as needed to bind styles and content; and b) using more of them so that your CSS files don't reflect the HTML. In a way, some burden is in the HTML (more classes, naming convention) but you're missing the huge removal of HTML notions from CSS files!


Web devs have been using presentaional class names to style HTML elements ever since there was CSS around. So, this is not something new. What's new though is your recommendation to use class names as the exclusive method of binding between CSS and HTML, which in my opinion is not practical and moderately limiting for the aforementioned reasons I listed in a prior reply.

Also, it's worth mentioning that class naming and achieving consistency and predictability throughout a project is an extra work to do and from my experience it can be very daunting. I already suffer and I can barely cope with the organizational overhead that comes with naming files descriptively and consistently, and how to structure the project tree accordingly, and as you know a poor implementation is no better than having none.

So, I don't really need to map the original CSS problem to a naming one in HTML to make things worse for me. If it works for you, you should go for it but with the knowledge that there are other people out there who prefer another approach away from these "clerk" duties.

As with the other point you raised of the disadvantage of mirroring the HTML structure in your CSS, I'd like to get your feedback on some examples. Do you really think that having something like «ol > li» or «select > option» is excessive? Aren't these elements highly coupled by nature? You don't really expect a «div» or «section» to be a child of an «ol» element, do you?

I know that HTML parsers are forgiving by nature but expecting them to break the basic rules of the language is ridiculous.

Here's another example, I recently wrote a timeline module/widget that has a distinct style for both the start and finish points while another one for the other points. So, I opted for a tightly coupled solution for that using pseudo classes like «:first-child», «:last-child», «nth-child(odd):not(:first-child)» ...

Do you really think that this is unnecessary and difficult to reason about in the context of that the design is prescribed this way that the first and last elements share a certain style while the others share another one with slight modifications for odd and even elements?

Yeah you might it view this style as a bit verbose compared to going class-only but the styling of the module is very rational and predictable to the point that can be extended programmatically to other contexts with the help of mixins or other constructs.

In the end, the whole proposal of restricting styling to only class selectors is not enticing or compelling enough for me to make the switch, at least for now.


> Do you really think that having something like «ol > li» or «select > option» is excessive? Aren't these elements highly coupled by nature?

This is exactly your mistake: you seemingly can't conceive styles as something apart from content/structure/HTML.

Of course, a list item is coupled to a ordered/unordered list. A <li> as a descendant of a <ol> is the way to do it and they are effectively coupled by nature. But this is mark-up, only! The style you give to the list and the list items is a different subject. Imagine that, for some reason, you want to apply the exact same styles to a structure of anchors (<a>) inside a <nav>? Then your selectors (ol, ol > li) wouldn't apply anymore, you'd have to rework the selectors. If you just used classes for the list and the list items, reusing the styles would've been easier and trivial.

> In the end, the whole proposal of restricting styling to only class selectors is not enticing or compelling enough for me to make the switch, at least for now.

I can understand that, totally. I needed a few years of experience to come to the realization that the dumb and predictable "just use classes" was the way to go with CSS. I've been "smart" with selectors a thousand times; many of them came biting back - I just thought "why create an extra class if I can infer this via hierarchy and element relations?". Many, many times the structure changed and the selectors needed to be reworked; even more times, the styles "leaked" to elements I didn't want to style.


> This is exactly your mistake: you seemingly can't conceive styles as something apart from content/structure/HTML.

Like I told you before, people have been using class names as styling hooks since prehistoric times and what you have been proposing is not something new at all. As for me, I use classes EXTENSIVELY not EXCLUSIVELY and this is the main contention in this debate.

As with the example you cited, this is a pretty good example and use case for packaging the style module and slabbing a class name on it and pushing out the door but the problem with your approach is that you see EVERY and EACH CSS rule/ruleset as a viable candidate for potential reusability down the road when real world experience shows us that this is unnecessary and overkill. Not every CSS rule will end up as an independent module somewhere and in the eventuality that this happen for some of them, it's easy to remedy the situation with a few code lines and it's done without the need to invest upfront in a naming system that comes at a cost and has a considerable overhead at least from an organizational standpoint.

Regarding the last point, there's nothing smart-ass about my solution ( production-bound projects are not a suitable candidates for show-off or competitive coding contests and I guess you know that already ).

Again the problem is that you don't want to acknowledge that you don't solve the styling problem in CSS by simply passing the buck to HTML. Taking the earlier timeline as an example, if you'd go class-only in CSS and to throw away all the simple logic provided by those pseudo-classes, you'd still have to provide a similar solution in your HTML template files.

Please don't fool yourself that you wouldn't have to do this because there's no other way to supply those specific classes (one for the first and last item, one for the inner items and then extending it to even or odd item) other than programmatically. This logical problem needs to be solved and you'd have to come up with a scalable and reusable solution to meet the requirements. If you prefer to solve the problem in the HTML domain with the help of JS and you're capable of taking all the precautionary measures to avoid introducing errors in the template, it's your call but please note that there are other people who prefer to solve styling problems in CSS terms, if applicable, and not toss it around to other domains for the sake of just holding to a dogmatic position.


> Like I told you before, people have been using class names as styling hooks since prehistoric times and what you have been proposing is not something new at all.

No, not new at all. What I'm proposing is almost as old as the CSS spec, but still is at odds with what people typically do.

> As with the example you cited, this is a pretty good example and use case for packaging the style module and slabbing a class name on it and pushing out the door but the problem with your approach is that you see EVERY and EACH CSS rule/ruleset as a viable candidate for potential reusability down the road when real world experience shows us that this is unnecessary and overkill.

You're right; it's an "architect astronaut" kind of thing and I reckon you have your point - most CSS won't be reused and - quite honestly - most reuse I do is in the SASS/preprocessor domain, not in the CSS/packaged styles domain. Nevertheless, extensive experience and lazy coworkers solutions tell me that it's just a matter of time until:

a) the DOM-bound rules stop reflecting your DOM structure and you have to maintain both "structures"; b) the DOM-bound rules leak undesired styling to other elements; and c) people have to write even-more-specific selectors to override them.

> it's easy to remedy the situation with a few code lines and it's done without the need to invest upfront in a naming system that comes at a cost and has a considerable overhead at least from an organizational standpoint.

Come on... the overhead of writing BEM-like selectors? This gives you - besides the performance and IMO maintainability - predictability, a common standard for naming among the team members and a nomenclature which yields more meaning upon reading. I think this easily compensates the overhead.

Also, please notice, you said "remedy" the situation. Nothing particularly wrong with that, but that's not a solution - adding another CSS rules is just a "patch", and those patches will accumulate up until they're a "lot" of your CSS. Again, nothing wrong with that, but it's architecture vs. lack of architecture; what I'm proposing is a upfront solution to avoid this and to reframe style rules upon finding failures, which is different than "remediation".

> Again the problem is that you don't want to acknowledge that you don't solve the styling problem in CSS by simply passing the buck to HTML.

I really think you're seeing this wrong. Having more classes is not passing the buck to HTML.

> Taking the earlier timeline as an example, if you'd go class-only in CSS and to throw away all the simple logic provided by those pseudo-classes, you'd still have to provide a similar solution in your HTML template files.

First-child and last-child kind of stuff is usually where I open up exceptions. I tend to do the opposite if I'm using a JavaScript framework which I trust, to render modifiers in classes for first/last element (e.g. .timeline__element--first; .timeline__element--last), but I'm not against using CSS for this. Also, I don't propose adding a class via JS to do :hover. :)


I 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.


The 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.


I 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.


The 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/) - i.e. inline styles. But you're probably best off combining that with conventional styles for all the easy, reusable bits.


> Do you really need nested ifs all over the place?

A maximum cyclomatic complexity level of 3 is rather acceptable and also the technique of compounded class names you're pushing for is no different than nested selectors since the same abstract logic operations, namely «if» and «and», are at play too under the hood for both cases

> If you're nesting styles, your styles are likely extremely tightly coupled with your html structure.

That's the whole point of encapsulation. I prefer to draw the encapsulation line at the component level not the sub-componenent level.

It's like an application of the "open/closed principle" where the component is open for the outside world to be manipulated as a single unit but it's closed and obscure from the inside.

This achieves in my opinion a greater degree of re-usability and portability. You just import the component where you need it and apply the styles you wish and then the component functions the same no matter where you place it because of the loose coupling with the outside world and the tight coupling and high cohesion inside.

However, if you'd like to carry out changes on a sub-component level and there isn't any exposed interface already, for instance through a Sass mixin that would allow you to tweak the inner parts, unfortunately you'd have to know what you're doing whether on CSS or HTML front to make sure you are not breaking anything and getting things done correctly.

To summarize, the main point of disagreement between me and you is where each one of us would draw the encapsulation line, I prefer a more "macro" approach while you're in favor of more "micro" and granular control over the building blocks of your software which should work fine for either of us simultaneously.


This 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.


People 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-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.


I don't think that was utterly insane. Perhaps not practical, but a useful mental exercise, at least. Jukka Korpela made some similar points a long time ago[0], showing how the use of classes in CSS mixed up styling with semantics.

[0] http://www.cs.tut.fi/~jkorpela/styles/harmful.html#pos


I 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.


Thanks for taking the time to write this longer response to my relatively flippant one. It's also pleasant to see some positivity here about CSS, which in these halls is often decried as being complete junk (rather unfairly - not many things have stood the test of time so well, and remain mostly usable even when applied in a wildly different context from their initial humble origins).

That said, I'm a little surprised you see no value at all in CSS preprocessors; having spent over a decade writing CSS by hand (from the CSS 1 days), it was a moment of sheer joy when I started using Sass - probably more than five years ago now - and discovered variables and mixins could be used with CSS (and to a lesser extent nesting - though it's immediately obvious to anyone who looks at the actual output or thinks for a moment about how this works that it isn't a great idea to overuse it). I would find it very hard to go back to writing raw CSS.

If you're working on a team of developers all contributing CSS to a project, do you find that one CSS file is actually manageable? Do you not get merge conflicts? Does it require vast discipline?

100% agree with you about the quality of actual markup in 2015. It's miserable.


> That said, I'm a little surprised you see no value at all in CSS preprocessors

I find value in CSS preprocessors in a few limited cases:

- auto-prefixing for added browser support. Especially with CSS animations this is one place where automatically generating the browser-specific CSS can be a time-saver

- for expressing design patterns that may be present in CSS in a more succinct, clear way as a way of teaching or demonstrating a pattern to others

- as a master copy to generate CSS that will be edited and maintained by hand. Suppose I built custom WordPress themes for a client I could have a SASS reset and base set of styles and then for each new project generate my CSS file and go from there

> If you're working on a team of developers all contributing CSS to a project, do you find that one CSS file is actually manageable?

I am more of a responsive specialist so I'm usually brought into existing projects where other programmers and designers have managed to get the code into a knot they can't untangle, so I don't change the existing codebase unnecessarily just to condense things, but for the project I author I will usually deliver a global CSS file that includes all layout, typography, form, button, and responsive styles, and then it's common to include an additional stylesheet for each plugin you might be using. If you have a responsive table plugin then it likely has one JS and one CSS file that need to be included and I would link them in as external files instead of inlining them in my global CSS. We then work with it as a team from there and it's been working well for us keeping things more simple.

> Do you not get merge conflicts?

Working this cleaner way has greatly reduced the merge conflicts we used to get when we were fully working within the 'Bootstrap' mindset and using 'classy HTML' and frameworks. Now we write clean markup, we pass over it with JS and enhance it how we need and use CSS and a CSS polyfill that adds element-based responsive queries as well as scoped CSS and the code is pretty terse. Not much there to conflict with :)

> Does it require vast discipline?

Yes! But I'm surprised at how little HTML, CSS, and JS is actually required to build some really cool stuff. On thursday I was experimenting with the web audio API and I made this teeny tiny HTML5 app that I bookmarked on my phone and tablets and was able to play with over the weekend. It only took a few lines of HTML, CSS, and JS to make a fully fuctioning web app - why would I write more than I need to to do the same thing? I can iterate pretty fast when I know how little code is actually required.

http://staticresource.com/synth.html

And that obfuscated blob at the bottom is nothing special, it gets unpacked to become a set of instructions to build the favicon and app icon using a canvas tag and attach it to the document. I encoded it using another teeny tiny HTML5 app I built http://staticresource.com/encode.html

You can view the source code of these by using another tiny tool I built that loads the requested page's source code and displays that instead. This way you can 'view source' even when using your phone or tablet. http://staticresource.com/inspect?/synth.html

If I was trying to use React or Node with Bootstrap and jQuery for every project I tried to build it would be a headache trying to build all these tiny little tools and apps. No wonder people need all this crazy front-end tooling. If you know HTML, CSS, JS, and learn the command line for manipulating files and batch operations, as well as for ow to automate routine tasks you do that's pretty much all you need in your toolbelt.

Whenever I work with teams I adapt to fit their pre-existing style decisions and tools because that's part of what I'm being contracted to do, and I desire to provide the most value while providing the least amount of friction.

Edit: and the significance of being able to build HTML apps so tiny is that you can write them on the devices you use them on! These are entire apps that you can sit down and write in Vim without it being awkward. I wrote this little page to learn how to detect multitouch on my ipad one morning on vacation. It's so simple: http://staticresource.com/touches.html I wouldn't have an easy way to write and test code using libraries on my tablet, but I could write this and test it and I learned a lot. This is huge considering Amazon just relased a decent tablet for $50, we can finally use these devices for creative work building HTML5 apps and stuff is simple enough now that just HTML, CSS, and JS is needed to build things.


Thanks for this response too! I don't have much to add other than to say that you sound like you would be a pleasure to work with.


I do write all my CSS by hand but I'm not good with it; I'd like to improve: what article (or book) would you recommend to help one actually "get" CSS?

(I'm also not sure what is meant by "nesting": combining selectors like this "div p" or "div > p"? Or is it something specific to SASS?)


The thing that has helped me the most is reading CSS. It's a lot easier to write CSS than it is to read it. Start with CSS you already have that works and re-type that into a new file and you'll soon start experimenting with what you can leave out, or just what does what.

One thing that really helps me read code is using a syntax-highlighting editor with a decent colour theme. You don't need auto suggesting, automatic tag closing, or anything. Every keystroke you press on the keyboard should map to one character being added or removed from your document.

Soon you'll find a formatting style that helps you quickly scan and read. For quickly skimming CSS it's best if it's all on one level. Selectors can be long, so starting them at arbitrary indents makes it a mess.

What they mean by nesting would be grouping 'blocks' of CSS together by indenting them. This might be one way somebody would nest button hover state under a CSS rule for a button:

    button {
      background: darkgreen;
    }
      button:hover {
        background: green;
      }
This is a super clean example, but in a big CSS file it can get pretty messy pretty quickly.


More likely this article demonstrates that the author has worked a large-scale web application and has the war scars to prove it. See my post elsewhere in the comments about a single line of SCSS writing out hundreds of lines of CSS.


As 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.


I 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.


True, and I've experienced that very problem. It's not a solution, but SASS does at least output the line number of each rule set on the generated CSS file.


What's the motivation to pick

   .navbar { &__element { &__hover { ... } } }
over

   .navbar__element__hover { ... }

?


Assuming 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.


I 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.


I'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

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/ for a complete toolkit of React components created this way.


Using 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.


>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?


Yeap, i'm using LessCSS for this. 1 less file for each "component" (classes are prefixed with component name to prevent collision). At build all less files are compiles into 1 big css file


I 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.


Typically, 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.


I 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.


This 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.


> as they seem not fully aware of the standard order of conflict resolution

I'd say it's the other way around - a lot of usages of !important are due to lack of understanding of CSS specificity, usually as a symptom of something else like using IDs in selectors..

If you avoid using IDs in selectors and avoid deep nesting of classes, then overriding styles works as you expect - apply a more specific selector to override the style.

Selector order only comes in to play rarely, and you can structure your files to start with less specific (base) styles first.

I see !important as more of a workaround than a solution, and I don't think it is used as it was originally intended.


I was talking more specifically from a debugging perspective as most of the frustration and anti-!important sentiment in the community stems from the effort and time taken in the process to fix a layout issue only to find after a half an hour of mental exercise and acrobatics an !important flag was raised somewhere and hence was this unexpected layout behavior.

I'd say that people who debug this way are at fault here not the language itself or this specific methodology followed because the order of cascading and inheritance in CSS is as follows: importance, origin, specificity and finally source order.

So, people who debug layout issue shouldn't jump first to diagnose specificity problems but importance and to lesser extent the origin albeit it's less common now to encounter a prob in this domain, and when everything is clear, you go and inspect specificity and source order.

That's why I am not sold on the complete avoidance of !important when writing CSS but I am of the opinion that you should only use them when necessary when you need to override a certain style in a very specific context and not more.


Chrome devtools sort selectors by specificity by default and you can quickly see what order the selectors / properties were applied in and what overrided what.

Most of the !important uses I've seen are more due to "Why doesn't this work? Dunno, I'll just put !important on it.."

Since !important only applies to a specific property, it's not that useful for making structured CSS components, and makes it harder to override (using !important again on every property)

I can't think of many cases where using !important would be better than overriding with specificity. Maybe when using 3rd party styles or making styles that are embedded in an external page (e.g. widgets).


yeah, 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


We have Sass partials for that but not as a part or official extension of the language itself.


I prefer using rems over ems, as ems are a pain to deal with for large applications (due to the nature of compounding).


However, 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.


Right 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.


Well, 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.


Multiple 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

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

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.


This 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.


The 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-a...


I 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.


"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/


There 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.


The 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


I 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.


You won't learn anything useful from this article, move on.


It 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.


only 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.


I 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.


I'm on mobile, so I'm unable to link to it, but Google CSS modules. Seriously, it's a godsend for achieving true modularity.


the author seems to be missing what HTTP/2 brings to the table [1]

#1: https://http2.github.io/faq/#why-revise-http




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

Search: