Package home | Report new bug | New search | Development Roadmap Status: Open | Feedback | All | Closed Since Version 1.5.4

Bug #3920 Inappropriate style rule reordering
Submitted: 2005-03-22 19:17 UTC
From: jdickey at seven-sigma dot com Assigned: farell
Status: Closed Package: HTML_CSS
PHP Version: 5.0.3 OS: Independent (Windows and Linux)
Roadmaps: (Not assigned)    
Subscription  


 [2005-03-22 19:17 UTC] jdickey at seven-sigma dot com
Description: ------------ When writing output from an HTML_CSS object instance by explicitly or implicitly (e.g., from HTML_Page2), the styles involving multiple selectors (what the HTML_CSS API calls "group styles", e.g. "* body #right") are written out before the styles with a single selector (e.g., "body"). This is completely independent of the order in which those styles were added to the HTML_CSS object. Why is this a problem? Because relative ordering between single and group styles (such as the IE Star Body Hack) is often used in an attempt to work around defects or limitation in certain widely-used browsers. Any reordering of those rules through a mechanism such as PEAR's HTML_CSS class destroys the CSS author's ability to achieve the intended results. I recognise that this defect in HTML_CSS is unlikely to be fixed without serious redesign and reorganisation of the existing code. Specifically, a more object-oriented approach, with "single selector styles" and "group styles" deriving from a single CSS_Style class, a container of which is used by HTML_CSS to contain all styles added to the HTML_CSS object instance, properly implemented, would have prevented this from occurring. Additionally, having more self-contained "Style" objects would have made reuse (of individual styles and groups of styles) much easier. As it is, the interface to HTML_CSS is largely procedural, making it difficult to efficiently break out reusable objects in client code. Reproduce code: --------------- I have produced a small writeup at http://www.seven-sigma.com/pear_css_bug/ which demonstrates a simple HTML three-panel page based upon an example at http://glish.com/css/7.asp. Particularly interesting is this code fragment: $CSS1 = &new HTML_CSS(); /* ... */ $CSS1->setStyle( '#right', 'position', ' absolute' ); $CSS1->setStyle( '#right', 'right', '0px' ); $CSS1->setStyle( '#right', 'top', '100px' ); $CSS1->setStyle( '#right', 'background', '#fff' ); $CSS1->setStyle( '#right', 'border', '1px solid #000' ); $CSS1->setStyle( '#right', 'padding', '0px 5px' ); $CSS1->setStyle( '#right', 'width', '200px' ); $BodyRightGroup = $CSS1->createGroup( "* body #right" ); $CSS1->setGroupStyle( $BodyRightGroup, 'width', '189px' ); $CSS1->setGroupStyle( $BodyRightGroup, 'background-color', 'lightgrey' ); /* ... */ /* IE 5.5 */ $CSS1->setStyle( '#header', 'height', '81px' ); $CSS1->setStyle( '#header', 'border-top', 'solid #000' ); $CSS1->setStyle( '#header', 'border-right', 'solid #000' ); $CSS1->setStyle( '#header', 'border-left', 'solid #000' ); $CSS1->setStyle( '#header', 'voice-family', '"\"}\""' ); $CSS1->setStyle( '#header', 'voice-family', 'inherit' ); /* IE 6 */ $CSS1->setStyle( '#header', 'height', '99px' ); /* ... */ $Page = &new HTML_Page2(); $Page->addStyleDeclaration( $CSS1, "text/css" ); That code fragment is seriously distorted in the output from HTML_CSS, such that the 'height' style is written only once (with value '99px', the last value specified)) and the similar elision of the 'voice-family' style. Expected result: ---------------- The expected result of writing out the contents of an HTML_CSS2 object should be, at least by default, the reproduction of each style group and rule specified, in the order specified, with "duplicate" style specifications preserved in the order specified by the code. /* ... */ #right { position: absolute; right:0px; top:100px; background:#fff; border:1px solid #000; padding: 0px 5px; width: 200px; } * body #right { /* ... */ /* IE 5.5 */ height:81px; border-top:1px solid #000; border-right:1px solid #000; border-left:1px solid #000; voice-family: "\"}\""; /* kills IE5.x parsing */ voice-family: inherit; /* fixes everybody else */ /* IE 6 and the rest of the world */ height: 99px; /* height for compliant browsers */ } Actual result: -------------- In the verson of the page using an HTML_CSS object instance to write style information inline (at http://www.seven-sigma.com/pear_css_bug/test-object.php ), all group styles are listed before single styles. This is dreadfully unacceptable, as explained above. The code fragment quoted earlier is rendered in the output as follows: /* ... */ * body #right { width: 189px; background-color: lightgrey; } /* ... */ #right { position: absolute; right: 0px; top: 100px; background: #fff; border: 1px solid #000; padding: 0px 5px; width: 200px; }

Comments

 [2005-03-24 13:30 UTC] tibolists at free dot fr
Hi, I do not that it is a bug. In fact the voice-family is a hack for ie. and pear HTML_CSS just manage the best way he css, it does not have to take care of browsers incompatibility, but must me compliant to the CSS standard.And it is. Hope that M$ will solve their ie bug is most important, than modifying the HTML_CSS class...
 [2005-03-24 13:35 UTC] thesaur
I see that this can be a problem, and that it would require significant restructuring of the class. However, I think the problem with IE shouldn't prevent this class from doing things "right". So I'm considering simply adding a "rawCss" set of methods to allow people to dump whatever they want into the file. I would place this at the very beginning of the CSS output. Would you have any problems with this?
 [2005-03-24 16:11 UTC] jdickey at seven-sigma dot com
Klaus, I think you'd probably want to be able to dump raw CSS at both ends of the file, something like a 'setRawCssAtTop()' and/or 'setRawCssAtBottom()' pair of methods. Unless I'm missing the point entirely and you're talking about just *replacing* the output from the styles array with the new 'raw CSS'? If this is a supplement rather than a replacement, I'd argue for naming the new method to indicate where in the CSS its output will be dumped. And can someone please explain to me (off list) why the group styles are treated separately from the single element styles? It seems to me that a) if this was all in one array, it would make this whole problem go away and b) that if you wanted to handle *processing* separately, you could make two passes through the combined array. And that still doesn't solve the issue of one style being specified more than once, as with the #header selector's 'height' style in my example stylesheet ( http://tinyurl.com/4zc4y ).
 [2005-03-24 18:05 UTC] jdickey at seven-sigma dot com
Just a quick followup to an earlier comment - people who know me know that I'm no fan of Microsoft for any number of reasons, especially quality issues, but saying things like <em>"Hope that M$ will solve their ie bug is most important, than modifying the HTML_CSS class"</em> is just plain disingenuous. HTML_CSS, like PEAR, like PHP itself, is a <em>tool</em> for building a particular class of artifact, a browser-based application. While MS may have the most obsolete, least W3C-standards-compliant browser in current use, it is the <em>predominant</em> browser in current use. Knowingly writing or using code that is known to break the 900-pound gorilla of HTML clients is a good way to tick off your actual and potential clients who are saddled with using the ruddy thing. One of these days, they will join The Enlightened Few (currently)) who use a proper, standard-compliant, easy-to-code-for browser, but until IE usage drops by an order of magnitude or so, we're stuck with having to support it as well as the clients we'd "like" to support. Historically, there have been two ways to accomplish this, both of them bad. One is to write a single style sheet that, by careful ordering and knowledge of browser-specific defects and quirks, manages to give acceptable output on both compliant browsers and Internet Exploder. That was the genesis of the current bug; taking a pure HTML/CSS demo page and rewriting it as an HTML_Page2 / HTML_CSS PHP script. (The other, of course, is to use something like Net_Useragent_Detect and multiple style sheets - I used to use one for IE, one for Netscape 4, one for Opera, and one for everything else. Blech.)
 [2005-03-24 18:26 UTC] thesaur
Thanks for the additional info. I will implement the possibility to add raw text to the beginning and the end of the stylesheet. As well as adding raw header data to HTML_Page2 (currently a feature request). These two items should mesh seamlessly as much as possible. I may also try to find time to rewrite HTML_CSS (or create HTML_CSS_Advanced) to provide more flexible handling while maintaining the current API as much as possible. At one point I also considered implementing a box hack shortcut, but haven't found time to do that. One of the advantages of HTML_CSS vs. static CSS is that you potentially check the useragent and serve the appropriate stylesheet based on useragent. I've also long planned on using Net_Useragent_Detect to provide an easy way to serve alternative stylesheets. Another item on the long-range roadmap is the possibility of taking a stylesheet and automagically altering it for common useragents. However, that isn't quite so easy and will probably be in the plans for a very long time :)
 [2005-06-30 09:28 UTC] farell
This problem was fixed with cvs version (2 weeks ago). Even if there are not yet a new release published or planned, could you have a look on this latest cvs version, and give us your feedback. Thanks in advance Laurent Laville
 [2005-07-27 07:05 UTC] farell
Thank you for your bug report. This issue has been fixed in the latest released version of the package, which you can download at http://pear.php.net/get/HTML_CSS This bug was fixed with the public publish of first release candidate of version 1.0.0 Thanks to Klaus !