views:

686

answers:

10

As you most likely already know, it's simple in JQuery to select all elements in the document that have a specific CSS class, and then, using chaining, assign common event handlers to the selected elements:

$(".toolWindow").click(toolWindow_click);
$(".toolWindow").keypress(toolWindow_keypress);

As usual the class "toolWindow" is also normally defined in CSS and associated with some visual styles:

.toolWindow{
   color:blue;
   background-color:white;
}

The class attribute is now responsible for indicating not just the appearance (visual state) of the element, but also the behaviour. As a result, I quite often use this approach and define CSS class names more as pseudo object oriented classes then visual only CSS classes. In other words, each class represents both state (CSS styles) and behaviour (events).

In some cases I have even created classes with no visual styling and simply use them as a convenient way to assign behaviour to elements.

Moreover, the jQuery LiveQuery plugin (and the live() built-in function) make this approach even more effective by automatically binding events to dynamically created elements belonging to a specificed class.

Of late I am primarily using class names as defining a common set of behaviour for associated DOM elements and only later using them to define a visual style.

Questions: Is this a terrible misuse of the CSS "class" attribute, if so why?

On the other hand, perhaps it is a perfectly valid approach to further implementing "separate of concerns" and improving the maintainability of HTML/DHTML pages?

+1  A: 

It depends on what you mean by 'behavior'. For example, if your behavior is really just a fancy styling effect, I might let it slide as just a more advanced style.

Otherwise, I still think it's okay but I would probably define a separate (empty) css class to control the behavior, to preserve the separation of concerns.

Joel Coehoorn
+20  A: 

The "class" is actually part of the document data (and hopefully semantically relevant) not the style or design of it.

This is why it's okay to use for both.

BC
Good point. "CSS class" is an often used, but misleading name, when talking about the DOM element class attribute.
Ash
Agreed. Let us not forget the usage of classes in the real-world.
Kezzer
Semantic is the ideal, although not always possible. I try to think in terms of meaning or function, from the users perspective.
Sam Murray-Sutton
Indeed. In the HTML specs, "class" is referred to simply as an "identifier". While CSS is used as an example of ways to use classes, it clearly does not establish any "ownership" of the attribute by CSS. Ref: http://www.w3.org/TR/html401/struct/global.html#h-7.5.2
Ben Blank
+1 it's in the spec. In fact, the metadata plugin uses the 'class' attribute by default.
Wayne Khan
+3  A: 

I don't think there's anything wrong with it. To be safe, you can always make sure that the classes you are using for behavior are separate from the classes you use for presentation.

At its root, jQuery's strength is its use of the CSS selector syntax for DOM manipulation. That syntax was intended for CSS, for presentation, in the beginning. However, using it to define behavior (whether you're selecting classes or not) has turned out to be a really powerful technique. Who could object to that?

Adam Bellaire
+3  A: 

I try to use IDs wherever possible and avoid classes. Thats not to say its bad using them, quite the contray. But I believe if you use IDs, your in a sense forced to use a very structured and meaningful semantic markup. If you spit out classes everytime you need an element to look at certain way -- your probably doing it wrong.

This is quite a controversial topic, so thats just what I'm throwing into the pan.

Gary Green
I agree about using IDs, but if I have multiple elements that require the same behaviour/styling we are IDs are not much use if we do not want to repeat styles/code.
Ash
Its AMAZING how hard developers work to make sense of and apply structure to html/css.....
Adrian
an element can have multiple classes - so it could one for appearance and another for behaviour. class="BlueButton ActivateMissiles"$(".ActivateMissiles").click(launch);
Adrian
Where can I play this html atari game? In all seriousness though, pages have a lot of structure. You could break this page down into its core aspects and then add styling depending on in what context i.e. the text is in.
Gary Green
There's an important distinction between id and class... You can use an id only once; classes are reusable. As a rule of thumb I decide which to use by asking if it's "a toolWindow" or "the toolwindow".
Andrew Vit
+5  A: 
  1. It is perfectly valid approach to do so.
  2. Class attributes don't define behaviour - JS does it, via CSS selectors (thank you jQuery).
  3. Class attributes don't define visual styles - CSS rules do it.
ohnoes
+2  A: 

It's a perfectly sound approach, and very much what the class attribute should be used for.

I would say that if a class is only consumed by jQuery and not by CSS, it's good to have a clear naming convention which indicates usage - if not for yourself, then at least for anyone else who may be working with your code, see a Class which isn't referenced in CSS and then delete it :)

I tend to have a specific class name which identifies the purpose of an object, and further, often quite generic sounding, class names which specify state of an object. eg

class="toolTip" - the tooltip class="toolTip open" - the tooltip in displayed state

This way you can generalise naming convention for behaviours easily (and potentially JS code for them too).

Also, by using CSS to define the presentation of the different states, your JS code is much more elegant than if you manage it all through JS. eg:

$('div.toolTip').addClass('open');

rather than

$('div.toolTip').css({display: 'block' ... etc etc });

ps. I don't think this is the place to get into the Class vs ID question, that really is a different debate!

mdja
I like the naming convention idea. So some class names represent objects while others can indicate the states those objects are in, interesting.
Ash
+1  A: 

I've used that to install keypress filters for numeric only fields. The class would be "numeric", "decimal", "negative decimal" or "decimal list" (allow comma and space). That was very easy to read, too.

Aaron Digulla
+3  A: 

I think it's perfctly valid.

The only rule I try to stick to is that class names should have semantic value. No need for them to have any associated CSS or JavaScript if you don't want too. Just make the class name descriptive of the content.

Bad class names (according to my rule):

<span class="brightRedBold">Wear Protective Gloves</span>
<a class = "openInNewWindow" ...>

To my mind those are just as bad as writing in-line styles and javascript

Good class names:

<span class="urgentWarning">Wear Protective Gloves</span>
<a class = "offSiteLink" ...>

You can attach whatever styles and behaviours you want to those classes and come up with a much more consistent and maintainable design. Try defining a spoken style for "brightRed" for example.

Noel Walters
+1  A: 

I keep thinking about this. Right now I think multiple classes is still the best approach and as people said, not incorrect. But it makes for a messy DOM if nothing else, when you have a hundred elements like:

<div class="draggable sortable droppable list-item editable text">text</div>

There're some things, like flags, you can assign with the data() method in jQuery. I'd love to see jQuery's data() evolve into a tool like how we're using classes.

Corey Maass
+1  A: 

As a convention I like to use a prefix on my classes so that I know a class in the css file is tied to Javascript code. For example using a "Js" prefix:

.JsButton { ... } .JsToggleElement { ... }

Another convention would be simply to use normally only lowercase letters for css classes and ids (beware that some browsers are case sensitive!), and use CamelCasing for Javascript-tied classes.

The why of all this is that often times a class tied to a behaviour will conveniently take styling rules.

I've considered also creating classes purely for Javascript behaviour, and use a seaprate class for styling, but that's a lot of splitting hairs for nothing. Instead I'd rather just define clearly the classes in the Javascript code:

mySuperObject =
{
    CSS_TOGGLE: 'JsToggle',
    CSS_HIDE:   'JsHide',

    initialize:function()
    {
        var elems = SomeJsLib.getElementsByClassname(document, 'a', this.CSS_TOGGLE);
        ...
faB