Skip to content
loganfranken edited this page Jun 22, 2012 · 22 revisions

CSS Class Names

Eric proposes the following...

  • Reserve hyphens for module namespaces.
  • Use camelCase with first letter of first word lower cased.

CSS does not have "namespaces" in the sense of many object oriented languages like Java, C++ and PHP 5.3+. This naming convention comes from standards like the PEAR naming convention in PHP and early drafts of the PSR-0 specification before PHP 5.3 added the namespace construct explicitly.

Namespaces for Modules

Do we verbosely namespace modules or not?

This question arises comes from Research: Modular CSS

An example of namespaced modules might be <ol class="menu layout-col layout-col-six"><li class="menu-highlight">... whereas avoiding namespaces would be <ol class="menu col six"><li class="highlight">....

Advantages to module namespaces:

  • Easy to handle from the object-oriented approach in programming
  • Prevents side-effects when you're designing a module because you can't accidentally effect something else
  • If we provide a dynamic loader where you specify the modules you want as an end user, this makes a lot of sense

Disadvantages to module namespaces:

  • Unintuitive to an end user that isn't familiar with the modular implementation of the framework itself. This was the motivator for MWF 1.3 when we reduced a div like <div class="menu-full menu-padded menu-detailed"> to <div class="menu padded detailed">.
  • Goes against the idea of "pure semantics". If something is padded, it should be .padded regardless of which entity we're talking about.
  • Harder to create size-efficient stylesheets this way.

One option is that we provide some modules that require namespaces, and that these are the "dynamically included" ones that you specify when you compile the CSS or when you load the handler, whereas there are a set of base classes that are always available that we don't namespace. The idea would be if we did something like the MWF trigger/target library (see https://github.com/ucla/mwf/wiki/Roadmap%3A-Framework-v1.3%3A-JS-Interactivity), we could namespace that and you'd have to specify it in your handler, but that things like the fluid layout (with classes like .col and .six), we don't namespace because they're always included.

Naming Conflicts

If we do not prefix everything in some way, then an existing site may run into naming conflicts. For example, one might have an entity named .menu.

  • One option is to use the same approach that vendors use for CSS attributes where we prefix all of our class names with a hyphen. Our menu would then be .-menu. This is intuitive from a naming perspective, but is it too hard for an end user to remember when using our classes? For example, you might end up with a div like <div class="-menu -col -six">. Could also use an underscore here, but that requires holding the shift key while hitting the hyphen char, which is just an added bit of effort that "hardcore" coders don't like.
  • Another option is to actually prefix all of our elements with a single letter followed by a hyphen. This is less "weird" from a markup concept, and it fits with the namespacing idea listed above. You would end up with a div like <div class="f-menu f-col f-six">. We'd need to decide on a letter. An issue arises from the "hardcore" programmer perspective though where you're typing extra characters. I, for one, would rather program using just the hyphen in front and not worry about a letter.
  • Finally, we could just say "eff it" and go with unprefixed names and expect people to revise their markup.

[ALICE] on 6/19:

So for the most part I'm in agreement with what's being proposed here, except that I'm going to way in on a +1 for explicit namespacing. I've been prototyping our IT Services CSS deck with some of these ideas (Snook, Sullivan, etc.) and I'm finding a few things while I am working.

Yes, the explicit name-spacing causes a string of classnames that to a CSS newbie would be an adjustment. And I think I'm leaning towards Snook's take on this (a more minimal approach). He doesn't explicitly namespace entities that are what Sullivan calls "content objects" since his thoughts are that semantically they are pretty self-explanatory and for a pragmatic reason -- these modules are the most numerous. He does, however, explicitly namespace the other elements -- what Sullivan calls the "container" objects or the "skins". He uses a single letter namespace to convey things like l= "layout", s="state", etc. I'm also leaning towards this and here's why.

The OOCSS method of separation of "content from box" and "structure from skin" is really smart for reuse but also a very hard concept to understand for people who aren't used to working this way. I've been struggling with understanding which css rules belong in what category and the explicit namespacing is actually helping me identify this and write better more abstracted code.

In the old way, all the css elements (skin,containers,content, structure) all of it gets declared within one object. A .menu class would have the colors,type treatments, padding and positioning declared on that .menu. This of course means that if there were strong patterns for a particular positioning or color treatment/behavior etc. it couldn't be abstracted and reused/shared across other elements, but the plus was if I wanted to edit the .menu classes it was a snap -- look for .menu. So comes in the new way... .skinA .layout .menu .behaviorType ... OK ... as someone who isn't used to working this way it's really hard to pick out -- where am I looking for the padding elements for .menu if they are no longer in .menu?

As I've been working on the prototype, I've found that the explicit namespacing has been helping me with both debugging and authoring new code; I've been using v="visual" for skin elements and it actually helps me better isolate and remember when writing css that ... right ... the declarations for repeatable skin treatments -- separate them from the core/essential declarations that make an atomic "menu" a menu. In addition, as I work on the prototype, it really does help my debugging once I "get" that "l" = layout etc. I'm able to scan the code and if I am having issues with the padding in a specific area -- I know that it's gotta be in the l-name class.

Though at first sight the namespacing is "ugly" and "scary" I think when applied consistently to the principals of "separate structure from skin" and "separate content from container", it's actually something that works very elegantly and helps rather than hinders.

I'm a +1 for explicit namespacing from the practicality of someone who needs to grasp that the code for css (in this way of writing modular reusable code) needs to be separated into 4 domaines. I know there's a valid argument that if we get the classnames 'right' the concern for naming conflicts won't be necessary -- I can totally agree with this, but, I'm finding in reality, it's not simply about getting the class names perfect so they don't conflict. The namespacing actually helps me distinguish between the 4 domains. With a huge CSS deck -- it's just not pragmatic for me to be able to know by memory which names are associated with the layout, which are are behaviors and which are the content objects themselves -- explicit namespacing helps offload that need to for me to remember and I'm happily able to spot the prefixes and be on my way.

So, I agree that the layering of classes is hard for a newbie to parse ... but I'd say that the real hard part is the fragmented css elements (4 objects, instead of one object) and less the namespacing prefixes. I find that the prefixes actually help to give me a clue to this while I adjust to this new way of thinking.

I think the trick here is to make the namespacing prefixes as minimal and un-obstrusive as possible (single letter seems to be a common convention I see).

On Semantics for CSS

This comes from many valid arguments raised by the semantics folks regarding the problem with style/presentational frameworks such as in grid frameworks and twitter bootstrap. At the same time, there are many valid counter-arguments coming from scalable/modular css folks related to practical reuse and scaling of code. These issues were first brought up in the Frameworks Components Page and the Research: Modular CSS Page.

Particularly important to think through is the issue of what "semantic meaning" is when we are looking at css class names. By no means do we have to be either/or about it -- in fact many people are both recognizing a need to have reusable css styles that make sense to styles and for them to be more future proof and less brittle to changes. Many are looking to pre-processors to help with this issue while others are calling for a reconsideration of what "semantics mean for css".

So, my question is ... how are we defining semantics for CSS? If we are strictly holding css class names to "data/content" semantics than really, the only way we can achieve this and have reusable style-based components is to use a pre-processor like SASS or LESS. If, instead we expand on semantic meaning for css to allow for style (from the logic that style-elements have semantic meaning in the CSS context -- i.e. they are style sheets), then we can have sensibly future-proof class names that are semantic to styles and not only content/data.

Articles to consider:

From Semantic Folks:

From Scalable CSS Folks:

[Alice] on 6/19

My concern is for those who are not using a pre-processor already, making this a requirement produces an extra overhead for these folks. In other words can we support both camps -- create good reusable classes that do not require SASS/LESS but also provide those same elements as SASS/LESS mixins to those who do? I'd like to see us be more "open" and build future-proof better named semantic class names w/o being afraid to use "presentational" elements when they are truly that (i.e. a .gridCol6 is semantically correct when it describes a 6 Column Grid -- to call it anything else would seem to be obscuring what it is). But I see a difference between say .brandPrimaryBar and .blueLine -- with the first being more robust than the latter. I'd also like for us to use data semantic styles to describe content objects i.e when we're talking about the core elements for a gallery -- let's call it .gallery.

[ERIC] on 6/19

I'm seeing two different discussions here:

  1. Preprocessors
  2. Semantics

PREPROCESSORS

Let me give my thoughts on preprocessors first...

As far as I see it, building a large UI framework without a CSS preprocessor induces an added level of work that we cannot afford.

This is the definition for a horizontal gradient background in CSS:

.myObject {
  background-color: #333;
  background-image: -moz-linear-gradient(left, #555, #333);
  background-image: -ms-linear-gradient(left, #555, #333);
  background-image: -webkit-gradient(linear, 0 0, 100% 0, from(#555), to(#333));
  background-image: -webkit-linear-gradient(left, #555, #333);
  background-image: -o-linear-gradient(left, #555, #333);
  background-image: linear-gradient(left, #555, #333);
  background-repeat: repeat-x;
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#{darken(#555, 1%)}', endColorstr='#{darken(#333, 1%)}', GradientType=1); 
}

And this is it with a preprocessor using the Twitter bootstrap mixin:

.myObject {
 @include gradient-horizontal($startColor: , $endColor: #333)
}

From a development sustainability perspective, the former is cumbersome.

Another reason for preprocessors is to allow for customization by advanced users. The Twitter bootstrap does exactly this, allowing one to tweak colors where they see it necessary. We're creating a framework here where the end user should be able to create a site as soon as they pull this down - and if they want to tweak a color, they should be able to do it in the "CSS way" rather than scripting up a small parser to do it.

Finally, I think possibly the most significant reason to use a preprocessor is because they do too. When you look at Twitter Bootstrap, 320andup, Golden Grid System, Semantic.gs, etc., they all use them. It's because of code reusability. Going down this vein, how would one take advantage of Twitter bootstrap in some framework we make if we don't use a preprocessor? Modifying the Twitter Bootstrap code itself? This is completely unsustainable, because as soon as the next Bootstrap release comes out, we have to go through the painful process of merging our changes with theirs. With a preprocessor, you use @extends, mixins, etc., so you take advantage of the framework(s) picked as a base without actually modifying their code files.

HOWEVER, '''this is not to say that our end users ever need to use a preprocessor'''. In my opinion, such tools are reserved for developers and advanced users. In every build we ever produce, we would of course provide the .css files themselves, meaning that one can take it straight from the box and use it without ever thinking about the preprocessor. This is the same way that those other frameworks I mention above do it too.

SEMANTICS

Now, as for semantics...

Although I land in the camp of preprocessors, my motivations are not to drive single-class patterns as Gallagher terms them. In fact, I would say I like multi-class patterns, as is evident from the way that MWF defines things like .menu.content.detailed rather than .detailed-content-menu.

I agree with Gallagher that it is more scalable because you don't end up with as much clutter in the namespace (permutations in names versus in use). However, the greatest benefit I've seen in practice is not a scalability one, but rather a "developer experience" one. If a developer becomes accustom to accentuation classes like info, primary, error, warning, etc. (just as an example), and they realize they can use them in many places, then rather than having to consult documentation for the right name permutation, they simply drop in the class name that makes sense where it makes sense.

The thing is, though, in our brainstorming for Web Type Names (and the accompanying section in Components), we're talking about "content objects". These are essential in a UI framework because we're trying to say "these are a set of elements that fit the UCLA identity". At the underlying base, many of these objects share common attributes, but we shouldn't rely on the end user to know which common classes we expect them to use - hence where the preprocessor fits back in. If I'm making a blog, I want to simply be able to write my code like this:

<section class="blog">
    <article>
        <header>
            <hgroup>
                <h1>... title ...</h1>
                <h2>... subtitle ...</h2>
                <time pubdate="2009-11-13T20:00+00:00">... friendly time format ...</time>
             </hgroup>
        </header>
        <p>... new content ...</p>
        <footer>
            ... about the author, copyright, etc. ...
        </footer>
    </article>
    <article>
        .... another article ...
    </article>
    ... more articles ...
</section>

The alternative would be to rely on the author to give presentational hints:

<section>
    <article class="span12">
        <div class="row">
             <div class="span8">
                 <header>
                     <hgroup>
                         <h1>... title ...</h1>
                         <h2 class="light">... subtitle ...</h2>
                         <time pubdate="2009-11-13T20:00+00:00" class="light">... friendly time format ...</time>
                      </hgroup>
                 </header>
                 <p>... new content ...</p>
             </div>
             <div class="span4">
                 <footer>
                     ... about the author, copyright, etc. ...
                 </footer>
             </div>
        </div>
    </article>
    <article>
        .... another article ...
    </article>
    ... more articles ...
</section>

From the framework perspective, the latter takes control out of our hands in terms of how the UI elements look and instead relies on the end user to get more creative - as opposed to using UI objects we've given them. Of course, since this premise might be that we package Bootstrap into the base of a framework, then they'd still be able to do the latter - but the former would be encouraged because it would ensure a unified experience across all the apps using the framework.

As such, I think we should have a mix of "content objects" and "presentational qualifiers".

Javascript Libraries

Eric proposes the following...

  • Base class with some prefix like _
  • Namespaces are implemented as objects like _.module.submodule
  • Use camelCase for functions and members in a module like _.module.submodule.funcName() or _.module.submodule.varName

Naming Conflicts

Using a single character base class is a common way to avoid cluttering the global namespace, and we need to do it. However, the question is whether we use a single character or a full name.

Options:

  • Single Symbol (_): This is similar to how jQuery uses $. However, because jQuery uses $, we wouldn't want to use this one. Instead, we could pick underscore as it's the other symbol that's allowed to start a Javascript name. The advantage is not much to type, but the disadvantage is that users often forget to include it and end up with Javascript errors - I (Eric) use this sort of convention a lot when I write my libraries, and even as the library writer, I sometimes forget to include the _ and then I get errors and have to go back and fix.
  • Single Character: If we use a single character in CSS (see ''CSS Class Names: Naming Conflicts''), I suggest we use the same single character here too. If we don't for CSS, we could still use it for Javascript. This has the advantage of being harder to "forget" than an underscore _ but the disadvantage is really that we have to pick a character that isn't likely to be used as a temporary (people often use letters like a, b, c, i, j, k, r, s, t, u, v, w, x, y, and z as temporaries and there might be others). It's far less likely people use an underscore as a temporary, because they don't even realize it's an allowed single character.
  • Multiple Characters: No matter what we go with in terms of a single character or symbol, it will be an alias to a multi-character name. jQuery does this with $ being equivalent to the object jQuery. We could forego a symbol/letter altogether and just provide a name, or we could even allow the user to run in "compatibility" mode, only using the full name if they find it creates a naming conflict in their particular app. We just need to settle on a name for the framework to decide this name.

[LOGAN] on 6/19

Just a quick note that the underscore character is used as a prefix in the aptly named library Underscore.js (http://underscorejs.org/). It's not as popular as jQuery of course, but it's popular enough (especially due to its relationship with Backbone.js) that we may want to consider a different character.

[ERIC] on 6/20

Good catch... thoughts on others? Really only underscores and dollar signs allowed besides letters. Maybe we just pick a letter...

[LOGAN] on 6/21

Yeah, I realize it's not as sexy, but once we decide on a name for the framework, I think a letter (or two) echoing that name would work. Knockout.js (http://knockoutjs.com/) uses "ko", for example, which I think works well within the code (it's short, but stands out).

Actually, now that I'm thinking about it: are we planning on having the shorter character(s) be an alias for the longer named namespace object or have it be the actual namespace object itself? (i.e. $ == window.jQuery) At first thought, I feel like this would simplify a noConflict scenario (just in case): https://github.com/jquery/jquery/blob/master/src/core.js#L330, but Underscore.js handles this just fine by caching the previous owner of the alias: https://github.com/documentcloud/underscore/blob/master/underscore.js#L903, so that argument is moot. I do feel that it might add some clarity and structure to the code, but if the shorter character matches the namespace close enough, there's probably little point (i.e., if it's called Web Blocks, then there's no real ambiguity with a "wb" namespace).