Why the CSS display property sucks
According to W3C the display property can take a number of different values (inline, block, list-item, none, etc.). Without getting into too much details, the display property controls how the given element affects the document's layout. Most rendering agents assign given elements a default display behavior, which is why paragraphs (<p>) and headings (<h1>, <h2>, <h3>, <h4>, <h5>, and <h6>) are rendered by default as block, and the head element (<head>) is never displayed (it has a default display of none). For more in-depth information on this issue, you can always check out Eric Meyer's excellent post: Really undoing html.css.
So what?
The biggest problem is that the display property simultaneously handles what could be considered as two different properties of an element: whether or not it is displayed and, if it is, how it is displayed.
But how does that really affect us?
Well, with JavaScript gone mainstream again, lots of websites rely, at some point or other, on scripting to hide and show given elements.
Hiding an element
The only way this can currently be done is by modifying the element's display property. For hiding an element, it is pretty easy, just set its display property to none:
element.style.display = 'none';
As using the element's style.display property is equivalent to directly setting the element's inline style, and as inline style has the highest precedence of all (well, except for styles marked as !important but that is another story), the above will override whatever display rule might have been set in a stylesheet and hide the element.
Showing it
Showing hidden elements, however, is much more complicated. There is no generic value which shows an element: all display values but none effectively do, but they also affect the layout in different ways. For instance, list items (<li>) have a default setting of ...well, list-item. But this default setting is often changed in stylesheets to display lists differently, for instance, to create suckerfish dropdown menus. As we thus cannot rely on a specific default display value for a given element, we are forced to rely on CSS precedence rules to display a hidden element.
Huh?
Setting an an element's display value to '' (an empty string) like so:
element.style.display = '';
is equivalent to just removing the inline style, and whatever style has been set in your stylesheet will be rendered instead. But this has a very serious implication: you can only show elements which have their inline style set to none.
This will work:
// html:
<div id="div_1" style="display: none">lorem...</div>
// js:
document.getElementById('div_1').style.display = '';
This will not:
// html:
<style>
#div_1 {display: none;}
</style>
<div id="div_1">lorem...</div>
// js:
document.getElementById('div_1').style.display = '';
a solution?
The only solution to this issue would be to either
- create a new boolean CSS property (
showmaybe?), which could be set to eithertrueorfalse, orshoworhide, or - create a new, more generic value for the
displayproperty (defaultmaybe?) which would revert to whatever had been set previously by the stylesheet.
My preference goes to the first option, but there might be some implications in either which I'm not aware of.
Until then, we will be stuck using inline styles. And that sucks!
Apr. 21, 2008 UPDATE: Look's like HTML5 will solve that issue.
Comments
-
If you’re showing and hiding elements out of the normal flow, like positioned menus, you can use ‘visibility’, which would seem to avoid the problems you describe.
I have to admit, though, that I’m not sure I understand the precise problem. I can see what you’re saying from a language design standpoint, and can agree with you there; but in practical terms, I haven’t encountered a problem. I don’t set inline display styles, and yet I toggle display on and off via JavaScript all the time. At least in the browsers I’ve used, there hasn’t seemed to be a problem. Is this because I always know what display role the elements should take, and you’re describing a problem in the more generic case?
Mon, January 01 at 09:42 AM
-
I have had this issue as well and have found that creating default CSS classes to support my desired effects, I could then subject my elements to multi-classing and control their appearance without the use of JavaScript’s crappy CSS controls.
Example:
CSS: /* This one strips the element from appearing completely./ .uiDeleted { display: none; visibility: hidden; }
/ This one hides the element, but prevents it from breaking the layout */ .uiDisabled { visibility: hidden; }
I then have some element:
HTML:
My ContentI then want to hide and show this header using the above default classes I have made.
JS:
// Completely hides the header $(‘section1Header’).addClassName(‘uiDeleted’);
// Hides the header, but doesn’t break the layout $(‘section1Header’).addClassName(‘uiDisabled’);
// Shows the header without the fuss of the .display = ’’ property $(‘section1Header’).removeClassName(‘uiDeleted’);
// Shows the header without the fuss of the .visibility = ’’ property $(‘section1Header’).removeClassName(‘uiDisabled’);
I have been using the above methods for quite some time and have written over 450 lines of extensions to prototype.js to enhance its functionality. I hope the above helps you!
Justin
Thu, January 25 at 09:09 AM
-
What about:
http://groups.google.com/group/prototype-core/browse_thread/thread/f2be0b6dc0180ae2/
Fri, January 26 at 07:14 AM
-
The fact is, that it does work, cause my code takes care of “block” and inline>
http://aka-fotos.de/blog/prototype-ausreizen (in German)
Mon, January 29 at 13:21 PM
-
You also enter into the issue of Internet Explorer not properly support those additional display types. Since it is unlikely that it ever will within a reasonable time frame and it is unlikely that the display attribute will be easily resolved through styles version style object conflicts, I resort to my CSS classing to manage them and so far, they have served me well.
Now, I can understand trying to incorporate something that can just handle any CSS situation it comes into and just be fine, but that will happen when browser makers actually do their jobs and support standards and make the style object, you know, actually work.
Fri, February 02 at 10:17 AM
-
My thought’s were on the lines of The Honorable Meyer’s (!).
I think I see what you’re getting at, and again I don’t quite see why visibility isn’t the answer: surely you still know the display attribute value when objects are invisible.
If visibility doesn’t do it practically, how about z-index, just put the objects under the canvas … must check to see how that affects positioning. Or, push off to the side (like some FIR schemes). Yes I realise these are hacks.
Wed, March 28 at 21:15 PM