Tuesday, October 18, 2011

css selector 101

So, around a year and a half ago I started my new role as "UI Engineer" at Pearson, for the then unnamed College Readiness startup they were incubating, now known as Alleyoop.  I had a lot to learn when I started out... while I had always thought the work I did on my own websites gave me an edge as an engineer (I was used to doing sites front to back, including the frontends) I was kind of self-taught with a lot of the UI stuff, and a lot of best practices from the late-90s got stuck in my brain. (I know when I'm dealing with some old HTML of mine because I tend the tags in all caps: <TABLE><TR><TD>like this</TD></TR></TABLE>. Actually, in my heart of hearts I don't think it's a bad practice, it really makes it easy to see what's markup and what's content, but now it's so idiosyncratic, not to mention against all the "xhtml" standards, that even though it works and makes sense I don't do it.)

I was fortunate that some of the first alleyoop projects involved working on existing prototypes that made pretty decent use of jQuery and heavy use of CSS. (I had used CSS before, but generally just to replace bad old <FONT> tags and what have you. I had even done some fancy (for the time) work in in javascript, like this online editor for Atari 2600 sprites. It made heavy use of document.getElementById() rather than the sophisticated selectors that would be available later.) We had outsourced this work to some experienced people, and I was able to learn from it, even as I took advantage of my engineering history to improve on the javascript.


Anyway, recently I was helping one of the content people here manage a CSS template in Wordpress, and it made me realize I could put some learnings here, just in case I don't use CSS and jQuery for a while and forget, or in this blog's mission as a possible instructional guide. (This blog entry is probably jack of all trades, master of none, not low level enough to be good for beginners, way too simple to be useful to a veteran, and not comprehensive enough to be a reference! Ah well.)

So:
HTML elements will generally be identified for purposes of CSS styling by:

  1. the kind of element they are- often a CSS stylesheet will apply a look to all elements of a type 
  2. a style slapped on to the element itself, e.g style="property:val;"
  3. the class you assign directly to them with class="someclass" (and while any element should only have one class tag, an element can have multiple classes, e.g. class="someclass someotherclass")
  4. a style applied to an element with a certain id ala id="my_unique_id"
  5. A combination of 3 and 1 where it's elements of a certain class name, but only elements of a certain type.
  6. A combination of 1 and 3, like where an element gets a style when it's inside another element of a certain class (for example all the divs inside a class'd containing div.)
So for each of these, you have a different way of selecting them in the style sheet:

To review, in a stylesheet (or block of CSS style) the format is:
selector {
  someproperty:someval;
  some-pixel-property:10px;
}

So what's the selector for each of these cases?
  1. For all elements of a type, it's just the tag name, e.g div
  2. If you're doing inline styles, you don't need to worry about the selector!
  3. For class name, it's "." plus the name of the class, e.g. .someclass
  4. For an id, it's "#" plus the id of thelement, e.g. #my_unique_id
  5. For elements of a certain class AND of a certain type, you write the element type and then the classname, WITHOUT a space: e.g. div.someclass
  6. For elements of a certain type WITHIN an element of a certain class, you use spaces: e.g. .someWrapperClass div
  7. Finally, you can use commas when you want a block of style info to apply to different selectors, e.g.
    elemselector1,elemselector2,.classname{
      property:val;
    }
There is an art and balancing act to choosing the right type of selectors. In my early days, I noticed how classnames could be very similar to keys in the Hash Maps I used in programming languages like Perl and Java, so I tended to use a lot of unique classnames. Also, I wasn't yet comfortable with selector type 6, there, and could barely understand the code I was looking at. (On the other hand, it is very possible to get over specific with your selector hierarchies there! If you're too specific about that stuff, than you can't reuse the styling because it only works when embedded in that particular setting)

Another rule of thumb is, if there are competing selector patterns, the more specific one tends to win, a style added via id is more specific than something applied to a whole class is more specific than something at the element level, so the "id" would win if there are conflicting CSS properties from different selector. (Of course  if it's different CSS properties, they will be all applied, rather than having to fight it out.)

Also, I think people go a little nuts in avoiding inline styles; it violates the holy grail of "all beautification goes in the CSS file" but frankly trying to get a pure-content HTML page is a pipedream; and hell, that's what we have Content Management Systems for.) So if I need to nudge something a bit, and it's a style that is totally not reuasable, I might go ahead and style it inline. Sometimes it just makes more sense than making up an arbitrary key.


And that is how I cope with CSS selectors... I love, love, love that jQuery uses the same selector pattern. It makes like so much easier. 


Also, as a "well duh" bit of advice to newbies: you probably NEED to have firebug on your system NOW if it's not there already. (It's also built into chrome, but I find Firebug a bit more deft) Being able to right click on an item and "Inspect Element" is a HUGE benefit, especially how it shows you what file the properties came from, as well as what other properties got ignored when there's one of those aforementioned conflicts. (The overridden property is indicated with a strikeout.)

No comments:

Post a Comment