5

I'm working on a large JavaScript-heavy app. Several pieces of JavaScript have some related CSS rules. Our current practice is for each JavaScript file to have an optional related CSS file, like so:

MyComponent.js  // Adds CSS class "my-comp" to div
MyComponent.css // Defines .my-comp { color: green }

This way I know that all CSS related to MyComponent.js will be in MyComponent.css.

But the thing is, I all too often have very little CSS in those files. And all too often I feel that it's too much effort to create a whole file to just contain few lines of CSS - it would be easier to just hardcode the styles inside JavaScript. But this would be the path to the dark side...

Lately I've been thinking of embedding the CSS directly inside JavaScript - so it could still be extracted in the build process and merged into one large CSS file. This way I wouldn't have to create a new file for every little CSS-piece. Additionally when I move/rename/delete the JavaScript file I don't have to additionally move/rename/delete the CSS file.

But how to embed CSS inside JavaScript? In most other languages I would just use string, but JavaScript has some issues with multiline strings. The following looks IMHO quite ugly:

Page.addCSS("\
  .my-comp > p {\
    font-weight: bold;\
    color: green;\
  }\
");

What other practices have you for keeping your JavaScript and CSS in sync?

Rene Saarsoo
  • 13,580
  • 8
  • 57
  • 85

4 Answers4

2

My perspective on CSS files is that they describe rules that define the theme of an application. Best practices generally state that content, presentation, and behavior should be kept separate so that it is relatively easy to change that theme. By having multiple CSS files, this becomes slightly more difficult, as a designer would have more files to deal with.

Additionally, CSS (Cascading StyleSheets) rules are affected by their position in the CSS document. By having multiple CSS files with different rules in each, it may become more difficult to prioritize which rules take precedence.

Finally, if you want to find out what CSS selector in your JS file matches what CSS file, try using a cool search tool, like grep, if you're on linux. If you're using a good IDE, you can also use it to quickly search for the rules, then you can just jump to the line number. I really see no advantage in keeping the CSS rules in different files; it will only complicate matters.

Additionally, I would advise against the idea of putting the CSS inline. By doing this, you will inevitably make it more difficult for your web designer to quickly and easily swap out the styles. The whole point of external CSS is so your web designer can change the theme or provide multiple themes for different users. If you embed the CSS in the JavaScript or HTML, you've then tightly coupled the content, behavior, and presentation.

Best practices generally suggest keeping content, behavior, and presentation separate for this very purpose.

jamesmortensen
  • 33,636
  • 11
  • 99
  • 120
  • You point on theming is a valid one I hadn't much thought about. Although we currently have no theming, I wouldn't rule it out for the future - at least for the color scheme. But I still would consider most of our CSS structural, not really subject for theming. But as I sayd - you are raising a valid point. – Rene Saarsoo Jan 08 '11 at 22:10
  • As for the cascading nature of CSS - I try to mostly rely on the specificity of selectors, not on the order of them. – Rene Saarsoo Jan 08 '11 at 22:13
  • 1
    But I'm definitely not going to place all CSS back to just one or few files. We already did it that way in the beginning and it was a maintenance nightmare. – Rene Saarsoo Jan 08 '11 at 22:22
  • @Rene - Can you describe what made it so hard to maintain? In my experience, the opposite is true. I had to re-theme one of our applications and it tool forever because I had to go through several files. In many cases, rules were duplicated, so it was more busy work as I made similar modifications over and over again. Tt felt more like busy-work than application engineering. In this case, time would have been saved if I wasn't constantly changing the same colors over and over again. I am curious to hear your experiences with having CSS in less files. – jamesmortensen Jan 08 '11 at 22:27
  • It was a constant problem that when somebody deleted JavaScript he forgot to delete the related CSS. This resulted in a lot of rules in CSS files that nobody knew if they were still needed or not. So they were often kept just in case. There was also a question of where to put the rule in the CSS file - new rules were often just added to the end of the file without noticing there bing already some styles present for the same component. – Rene Saarsoo Jan 08 '11 at 22:50
  • 1
    I think it's a tradeoff between JavaScript and CSS side of the app. For theming you would like to have all CSS as separated from JavaScript as possible. For maintaining JavaScript you would like to have CSS as close to the JavaScript code that references it as possible. In our case I think the JavaScript side is more important - we are really JavaScript heavy and quite low on CSS. – Rene Saarsoo Jan 08 '11 at 23:00
  • @Rene - If someone leaves extra CSS, that CSS can be deleted later without needing to worry about breaking anything. I would think a "search" with a good IDE could tell you what CSS rules are being unused. But if you mix JS, CSS, HTML, and then try to manage it later at redesign time, you'll likely encounter bugs. Additionally, I can't possibly see how leftover CSS rules could harm the performance of a project. I'm sure the load times are negligible and definitely not worth the opportunity costs of having to unravel tightly coupled code later on down the line. – jamesmortensen Jan 09 '11 at 05:38
  • IMHO it's the same as with any dead code. Sure, there are ways to detect it, but it's better not having to worry about it at the first place. – Rene Saarsoo Jan 09 '11 at 13:33
2

Having one CSS file per JS file seems a good thing for me. It's clean, and easy to understand and to maintain. The only problem would be to have dozens of CSS files on every page, but I suppose you combine those files to one big file, so this problem does not exist in your case.

How to embed CSS in JavaScript? It depends on the environment you have, and how the build process is done. The easiest thing is to have a large comment at the beginning of every JavaScript file, something like this:

// <...>Your copyright notice here</...>

// <css>
/*
body{color:red;}
div{border:solid 10px lime;}
// ... other ugly styles.
*/
// </css>

Then during the build, you have to search for <css>...</css> blocks and extract the CSS by trimming the /* and */.

Of course, it creates a problem: if you are using an IDE with auto-completion, embedding CSS into a JavaScript file will make it impossible to use auto-completion in this case.

Arseni Mourzenko
  • 50,338
  • 35
  • 112
  • 199
  • Comments look like a great solution for embedding. For small bits of CSS I guess trading away syntax highlighting etc is worth it. – Rene Saarsoo Jan 08 '11 at 22:01
  • 2
    This also gave me an idea for implementing heredoc-style strings in JavaScript: `(function(){/* Your multiline text here */}).toString()` – Rene Saarsoo Jan 08 '11 at 22:38
1

My preferred method is to keep all the CSS files separate and then have a build process that compiles them into a larger CSS file on deployment.

I would avoid merging your JS with your CSS. It may sound like a cleaner solution from the file-level, I think it'll get messy fast. That, and you'll lose the highlighting and syntax assistance your editor gives you.

Chris Van Opstal
  • 36,423
  • 9
  • 73
  • 90
1

Check out Csster. I wrote it to solve just this problem.

You embed your CSS rules directly in your Javascript, using Javascript object literal syntax. It's no uglier than raw CSS.

Csster.style({
  h1: {
    fontSize: 18,
    color: 'red'
  }
});

The rules are inserted into the DOM on the client side. This architecture simplifies your build process and reduces client requests.

You can use it like you describe, but Csster also provides a couple other niceties:

  • nesting to DRY up stylesheets
  • color functions like darken and saturate
  • built-in macros for common CSS idioms like clearfix, rounded corners, drop shadows.
  • extension points for custom behavior or cross-browser support

It's well tested and I've used it on quite a few projects. It is independent of jQuery, but plays well with it.

I'd love to have more people use it and provide feedback.

ndp
  • 21,546
  • 5
  • 36
  • 52
  • This looks interesting. Have to try it out. I see some downsides like not being able to simply copy-paste the styles between CSS file and JavaScipt. Also there doesn't seem to be a way to automatically extract the CSS rules from JavaScript code. – Rene Saarsoo Jan 09 '11 at 00:24
  • Thanks. I'll improve the docs. No, there's no easy way to paste in existing CSS rules... I run some regular expressions and it doesn't take long-- but I could provide a tool for this if you want... As far as "extract" (going the other way), I was going to implement this, but after using it the first time, I realized it is really easy to do this with Firebug. There's also an extension point where you get this info within Javascript. Thanks. Let me know how it goes. – ndp Jan 09 '11 at 04:08