Where is the correct place to define CSS for a directive

7,534 views
Skip to first unread message

Ryan Wells

unread,
Sep 13, 2013, 12:00:13 PM9/13/13
to ang...@googlegroups.com
I've asked a SO question on this with the full details of the question and some justification that I've tried to argue but I realise I now should have asked this here.

My problem context is any directive that is written to be a reusable section of HTML and will used in multiple pages and completely disjoint projects. I'm trying to work out where the most logical place to define CSS for a directive is. Neither what the pages or projects are matter - there is no guarantee there is any overlap between projects or pages. With this in mind, what is the generally accepted method of defining CSS for a directive like this?

So far I've thought of:

  • Inline css on elements in the template: This is always bad and goes against my moral standings, however it is very explicit in what the exact css for a directive is and it removes the possibility of CSS collisions/overwriting with other page elements and vice-versa.
  • Style/link tag inside html template: A style tag keeps the bad parts of inline css at bay but can be a hassle to maintain in text editors (emacs for instance doesn't format it correctly). A link to the stylesheet could be added instead into the template but should we really be adding CSS links midway down a page?
  • External stylesheet: The traditional "right" way of including CSS also doesn't seem to quite fit as collisions, like what I mentioned in the first bullet, can happen. Moreover I now need to remember to add this as a link tag at the top of the page which doesn't seem to align with the way of defining a directive - I don't need to explicitly add a link tag for the template (providing I'm importing templates through "template_url" in the directive definition) so why should I need to do this for the style?
I know we can avoid collisions entirely by putting all CSS declarations under a .directiveName class and adding that class to the root node of the directive and add this as a <link> node in the directive but I'm still not convinced this is the best way to do this.

I realise this isn't an "I've got a problem please help me" question but I want to know what the community thinks about this. And I also would like to see other developer's opinions about the "right way"!

This question is prompted by a directive definition allowing a "templateUrl" to load HTML templates and got me thinking about other external resources.


Thanks for reading so far, I look forward to any discussion! :)

Ryan Wells

Kai Groner

unread,
Sep 13, 2013, 1:24:44 PM9/13/13
to ang...@googlegroups.com
Hi Ryan,

You can use a css injection service to facilitate directives that want to bring their own styles.  This allows you to keep any resource declarations close to the directive definition.

Personally I'm not horrified by the idea of css links appearing in the middle of the page, but the template is a bad place for them if you have a directive that will appear more than once on a page.

Here's a plunker showing an example of such a service.

I made the service pretty dumb.  There's lots that could be done to make it more robust and support more dynamic uses, but I think this gets the idea across.


Kai



--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/groups/opt_out.

Rhett Lowe

unread,
Sep 13, 2013, 8:13:38 PM9/13/13
to ang...@googlegroups.com
I am definitely not a CSS designer but as a programmer I don't want the style to touch the directive at all.
The directive should be declarative in its classes and it is up to the view of the moment to handle asthetics. If it's an overlay it should claim class overlay or a span that acts as an up button should be span.up.button but it isn't the job of the directive to care how it looks.

That said the only 2 options are external CSS of its own (ex: 'angular-spinner.css') or if you will use it everywhere in YOUR app but never in someone else's app just add it to the main CSS.

I like Kai's idea of putting it in its own CSS and auto/lazy loading it.

Good luck,
-- Rhet :D

Olex Lapshyn

unread,
Sep 14, 2013, 7:32:07 PM9/14/13
to ang...@googlegroups.com
Hello, 
just wanted to point out, well, angular.js itself has directive that brings its own css with it, and it's being done like this:
angular.element(document).find('head').prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide{display:none !important;}ng\\:form{display:block;}</style>');
So, in case you're doing this only once, you can go off with something like this, but in case you're doing several of those, it might be a good idea to adopt something more centralized, just like style injector thing by Kai.
BTW, did you know you had insertRule and addRule methods at your disposal?
Good luck.

Ryan Wells

unread,
Sep 25, 2013, 6:35:50 PM9/25/13
to ang...@googlegroups.com
Hello,

Thank you everyone for your answers! 

This is a really quick response - I've been very unwell this past week and haven't had a chance to explore these ideas. I've got an approach similar to Kai's that I'm going to implement and post in here.

I appreciate everyone's answers, and again apologies it took me so long to say so!

Ryan


--
You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/4JxPadccs14/unsubscribe.
To unsubscribe from this group and all its topics, send an email to angular+u...@googlegroups.com.

Sander Elias

unread,
Sep 26, 2013, 12:17:13 AM9/26/13
to ang...@googlegroups.com
Hi Ryan,

I take a bit of a different approach on this. My projects are orders so, that everything that belongs to a certain feature (this might be a single directive), is in its own folder in my filesystem. an example might be handy here. Lets say I have an specialList directive.
do my directory structure would look something like this:

ProjectName -> src -> specialList
                              -> Main
                               -> components
                               -> ...

in the the folder specialList is everything I need for that. (If it is a really large feature, there might even be subfolders). This means the specialList.js, specialList.tpl.html speciallist.spec.js specialList.css and so on are in the same folder.

My gruntfile goes over all folders and put's everything in place for the app. Basically this means, the build tool, concatenates all CSSS into 1 file, that gets read by the app. all templates get processed to0, and the JS files also get's concatenated. Doing it this way, If I need the specialList in another project, I can just link or copy it in. 

Does this make sense to you?
Regards
Sander
Reply all
Reply to author
Forward
0 new messages