[Javascript] separating structure, style, and behavior
Paul Novitski
paul at novitskisoftware.com
Thu May 6 10:13:55 CDT 2004
Mike,
ye scribed:
> I like the idea of controlling display with css, but taking everything
> "out" to the style sheet makes the inline code a bit less readable. (ok,
> so i'm lazy too)
What I've found is that ever since I've been consciously separating html
structure from javascript behavior from css style, my own code has become
MORE readable and manageable, and more often I know exactly where to go to
solve a particular problem because there's so little overlap between the
three domains. Previously, if a page element didn't look or behave
properly, I'd have to look in two or three files to track it down.
Here are some vivid examples of the sucessful separation of structure from
style, in which the same html skeleton is fleshed out dramatically
differently using CSS:
Listamatic http://css.maxdesign.com.au/
The CSS Zen Garden http://www.csszengarden.com/
In practice, I'm finding that I can't separate the three completely. In
order to get some CSS structures to work, I find that I must tweak box
dimensions at onload() or during interaction. Until CSS4 and HTML7 and
Browser10 come along and solve all of our problems forever (you bet!),
we'll be shambling along as best we can with incompletely formed
limbs... But even with today's imperfect technology one can get quite
close to the ideal.
> How do you deal with multiple properties using that strategy? If i
> want to change both the background color (for enable/disable) and
> font-weight (for select/deselect) - is there a way to use CSS class,
> without having to define 4 classes for this one object?
Well, there are various approaches. First of all, I actually don't find it
onerous to define four classes if that's what the design calls for:
cssEnabled{background-color: lightblue;}
cssDisabled{background-color: ghostwhite;}
cssSelected{font-weight: bold;}
cssDeselected{font-weight: normal;}
That way I can assign these classes to my elements singly or in pairs:
oThang.className = "cssEnabled"
oThang.className += " cssDeselected"
The point is that I'm using html & javascript to apply metaphorical class
names rather than explicit style attributes. Given a single html
structure, I can tweak its appearance merely by changing its stylesheet. I
can more easily allow a generic widget to be adapted to many cosmetic
contexts. I can more easily use the same page for different purposes by
creating alternative stylesheets -- whether for different browsers or for
different media (display/print). Another benefit of separation is that
it's easier to build pages that degrade gracefully -- they may not look
terrific if the browser doesn't support CSS or Javascript, but at least
they won't break as easily as they would if the scripting languages were
thouroughly intermixed.
One of the cool things about CSS is that you can have more than one class
name per object -- just separate them with spaces:
<select class="cssEnabled cssDeselected cssFrankie cssJohnny ...">
This allows a page element to belong to more than one cosmetic group, which
can often come in handy.
In a page where certain items can have more than one class name, I often
use RegExp replace logic. Instead of:
oThang.className = "cssActive"
I write:
oThang.className = oThang.className.replace(/cssIdle/, "cssActive")
so that I can toggle one set of class names without disturbing others.
Since CSS requires that multiple class names be delimited by spaces, it's
easy to capture them in a Javascript or VBscript array:
var aClassNameArray = oThang.className.split(" ")
Of course, most often you don't need to declare a special class name for
default states like "disabled" or "deselected", because without a class
name an element will render using the default properties of its type, e.g.:
/* default properties for drop-down lists */
select
{
background-color: ghostwhite;
font-weight: normal;
}
/* special states */
select.cssEnabled
{
background-color: lightblue;
}
select.cssSelected
{
font-weight: bold;
}
That way you're really only juggling two class names, not four, but with
the same effect as four.
Another cool thing about CSS is that you can use the a:hover selector in
place of many Javascript onmouseover behaviors. (IE is limited to applying
:hover to anchor tags, while some other browsers will apply it to any tag.)
HTML:
<ul id="Amphibians">
<li><a href="#">Frog</a></li>
<li><a href="#">Salamander</a></li>
</ul>
CSS:
#Amphibians a:hover
{
background-color: lightgreen;
}
You can even use this to drive dynamic menus, causing sub-menu items to
appear & disappear with hover:
HTML:
<ul id="PlantList">
<li><a href="#">Trees
<ul>
<li>Larch</li>
<li>Spruce</li>
</ul>
</a></li>
<li><a href="#">Shrubs</a>
...
</li>
</ul>
CSS:
/* hide submenus by default */
#PlantList a ul
{
display: none;
}
/* show submenus on mouse over */
#PlantList a:hover ul
{
display: block;
}
More later...
Paul
At 06:12 AM 5/6/2004, Mike Dougherty wrote:
>>Rather than explictly changing an element's backgroundColor in
>>Javascript, I recommend that you change its className instead, and set
>>the color specifics in your stylesheet. If you can confine as many of
>>your stylistic effects as possible to css, you'll always know where to go
>>to tweak the cosmetic and you won't have to worry about css/javascript
>>conflicts.
>
> How do you deal with multiple properties using that strategy? If i
> want to change both the background color (for enable/disable) and
> font-weight (for select/deselect) - is there a way to use CSS class,
> without having to define 4 classes for this one object?
>
> I like the idea of controlling display with css, but taking everything
> "out" to the style sheet makes the inline code a bit less readable. (ok,
> so i'm lazy too)
More information about the Javascript
mailing list