Random fun question. If you had to pick a W3C technology to implement next in WebCore, which one would you choose? Justify your answer. ;)
Respond with comments or trackbacks.
(1) XSLT
(2) XForms
(3) SVG
(4) MathML
(5) CSS3
(6) XHTML2
(7) __________ (Other)
I just finished up fieldset and legend support. By complete coincidence it renders like Mozilla's implementation (which I've actually never even looked at before). Although this code exists in the KHTML trunk, I rewrote it in order to actually get the legend up into the border and to not alter the DOM (the KHTML code was moving the legend in the DOM so that it was the first child).
One of the first comments in the feedback for my previous XBL blog entry was "XSLT can do this and is more powerful than XBL. Why wouldn't I just use that, since it's a W3C standard?"
First of all, I should say that the purpose of these XBL blogs is to argue for XBL from a technical perspective and not from a practical perspective. Obviously XSLT is implemented in Internet Explorer and XBL is not, so XSLT is the clear solution for the real world.
So let's imagine a hypothetical world where both technologies were implemented in all Web browsers. In this imaginary world, the author has a choice to make: XSLT or XBL?
Here's why I believe XBL is better than XSLT on the client side. This discussion should be prefaced with an admission that I am not an XSLT expert, so I could in fact be wrong about some of my statements regarding what XSLT can and cannot do. As usual, I welcome corrections and criticism. :)
XBL does not have this limitation. If you define a binding for all paragraph tags that gives them nested borders and complex adornments, you can still dynamically create new paragraph tags using the DOM, insert them into the document, and watch them immediately pick up the complex presentation that all the other paragraph tags in your document have.
Since XBL only adorns the source document, it only adds new anonymous content. It does not have to waste space or time creating the same content nodes in a second result document.
Now once you have this result document, you will then (obviously) need to style it with CSS. This result document still has to evaluate the computed CSS information for all of its elements! It has to do this in any CSS-aware layout engine, regardless of how little or how much CSS you use. This phase of document construction called style resolution happens for any document presented in a browser.
XBL piggy-backs on top of CSS selectors, which means that since you have to resolve style anyway, you can compute the correct binding at the same time. XBL will therefore be faster, since both XSLT result documents or XBL-adorned source documents still have to resolve their computed CSS styles, but only XSLT requires an extra XPath selector matching phase.
That means we get an entire new document created, an entire new XPath matching phase, a whole new markup tree created, a whole new style resolution phase, and *most importantly* no ability to preserve the current state of the displayed document.
With XBL, you just rebind, re-resolve style only if things have changed, destroy and create only the markup you need to change, and most importantly, you preserve the current state of the document, e.g., your scroll position, contents of forms, any changes that were made dynamically via script, etc.
There is no way to do this via XSLT.
It's my opinion that for presentation, client-side XBL is far superior to XSLT in most respects. In fact, a good use of XSLT would be to take an XML document and adorn it with presentational markup that non-XBL capable browsers could then receive while still sending the pure unpolluted markup to XBL-aware browsers for styling with CSS and XBL. ;)
comment (48) -I talked in an earlier entry about how XBL could address the problems of additional spans polluting your source as is the case in Zen Garden. Eric Meyer says in his latest blog entry, "Sign me up! I had no idea XBL was capable of this sort of thing."
It is indeed, and I'll prove it using Zen Garden as an example.
The source of the page has markup like this:
<div id="pageHeader">
<h1><span>css Zen Garden</span></h1>
<h2><span>The Beauty of <acronym title="Cascading Style Sheets">CSS</acronym> Design</span></h2>
</div>
Note the presence of the spans. They serve no semantic purpose and are clearly only included in the source markup to provide an element that can be used as a style hook for CSS.
With XBL, we can eliminate the spans. Let's look at one of the stylesheets that makes use of these spans for styling and convert it over to using XBL instead.
The default stylesheet, called tranquille, wants to use images in place of the original descriptive markup text, so it applies background images to the header tags and then sets the spans to display: none.
From the stylesheet:
#pageHeader h1 {
background: transparent url(h1.gif) no-repeat top left;
margin-top: 10px;
width: 219px;
height: 87px;
float: left;
}
#pageHeader h1 span {
display:none
}
#pageHeader h2 {
background: transparent url(h2.gif) no-repeat top left;
margin-top: 58px;
margin-bottom: 40px;
width: 200px;
height: 18px;
float: right;
}
#pageHeader h2 span {
display:none;
}
First let's remove the spans from the original markup. This results in the following:
<div id="pageHeader">
<h1>css Zen Garden</h1>
<h2>The Beauty of <acronym title="Cascading Style Sheets">CSS</acronym> Design</h2>
</div>
Much better, isn't it? Now in our CSS, we remove the rules for the spans and add binding declarations. We can even reuse the same binding for both the h1 and the h2, since the effect we want to achieve is exactly the same!
Our new CSS looks like this:
#pageHeader h1 {
background: transparent url(h1.gif) no-repeat top left;
margin-top: 10px;
width: 219px;
height: 87px;
float: left;
}
#pageHeader h2 {
background: transparent url(h2.gif) no-repeat top left;
margin-top: 58px;
margin-bottom: 40px;
width: 200px;
height: 18px;
float: right;
}
#pageHeader h1, #pageHeader h2 {
-moz-binding: url(tranquille.xml#imageheader);
}
Now we create the XBL file. An XBL file is just an XML file that contains one or more bindings. In this case, we define one binding called imageheader.
<bindings
xmlns="http://www.mozilla.org/xbl"
xmlns:html="http://www.w3.org/1999/xhtml">
<binding id="imageheader">
<content>
<html:span style="display: none">
<children/>
</html:span>
</content>
</binding>
</bindings>
The content tag above introduces an anonymous content template. We create an anonymous span that ends up immediately underneath the bound element, the header tag to which the binding is attached in the main document. The span has a style of display:none. To keep the example simple, I've used an inline style attribute, although the XBL file is capable of loading a scoped stylesheet to style its anonymous elements if so desired.
Underneath the span is the children element. This says where to place the original explicit DOM children within the anonymous content subtree. In effect, we've just wrapped all the original children in a span that has been interposed between the header and its content.
And that's all there is to it! We've now created a generic reusable binding that can be used on *any element* to hide all its children!
Click here to see the example in action! In browsers that don't support XBL, you will see the header text drawing on top of the background images. In Mozilla, you should see only the background images, since the binding has effectively hidden the text.
comment (30) -I received a lot of suggestions for how to solve the Aqua form control margin problem. I thought I'd summarize them in a new blog entry. In all of the solutions I will refer to the extra space required by Aqua form controls as intrinsic margins.
(1) Make the intrinsic margin part of the control itself. In other words, if CSS says to make the form control 100px wide, then the intrinsic margin becomes part of the control. This has the advantage that the widget won't disrupt the surrounding layout of the page, but the obvious disadvantage is that the widget itself won't be the exact width that the Web designer asked for. You also couldn't easily turn off the intrinsic margins without adding an extra CSS property, e.g., safari-intrinsic-margin.
(2) Specify the intrinsic margin using the margin property, but Implement the CSS box-sizing property with a value of margin-box, and then width values could implicitly include margins. With this solution you could override the margins to get rid of them. However with this solution, the form control could still disrupt layout when explicit margins are used in conjunction with widths.
(3) Lay out the form controls without intrinsic margins applied at all. Once everything has been positioned, examine the form controls to see if they are too close to any other content, and if so, apply the minimal intrinsic margin needed to distance them from surrounding content. The problem with this solution is that it's non-trivial to detect your surrounding content efficiently. You could limit the solution to only form controls themselves, but then you could potentially overlap non-form control content like text. This solution can also still result in a disruption of proper layout when the widget applies the margins to distance itself from surrounding content.
(4) This is my own solution, and I think the one I'm going to use. Make the application of the intrinsic margins conditional. If an explicit width is specified for a form control, simply drop the intrinsic left/right margins. Similarly, if an explicit height is specified, drop the top/bottom intrinsic margins. Otherwise, apply the intrinsic margins only if the page did not override with its own margin values.
This approach has one crucial advantage over the previous three options, namely that the widget never disrupts the layout of the page. The disadvantage is that there will be scenarios where the controls might be too close together; however, I don't think such scenarios will be common, especially given that the horizontal and vertical intrinsic margins are applied separately.
comment (42) -I've been wrestling with a nasty problem in WebCore. Safari's form controls are native Aqua widgets, which means that they are not designed to butt up against each other. When an input field gets a focus ring around it, you really don't want that focus ring to be drawn on top of other widgets.
The problem is that this isn't how the Web has been designed. Just go look at Google in a browser other than Safari, and you'll see that the text field is so close to the buttons that - were a focus ring to be shown - it would overlap the buttons underneath the text field.
The reason you don't see an overlap in Safari is because of a hack in Safari's built-in CSS file. Input fields, buttons, list boxes, and dropdown lists all have margins applied by default.
The problem with this solution is that it breaks Web sites who use table cell layout with fixed widths and assume that when they set a width on a form control that it will be exactly that width with no extra margins around it. When Safari throws in the extra margins, the site's layout gets messed up.
An example of this is Ben Goodger's blog. There are plenty of others.
Another problem I've created by using margins is that when input fields say they want to have a width of 100%, I actually have to not apply the margins in that case, since objects can then end up spilling out of containing blocks. So Safari conditionally applies the margins on the form controls, which is even nastier.
The good news, though, is that on most sites, having the margins makes them look much better. The question is, how can I get the spacing I need between controls in such a way that I don't break Web sites? Any ideas?
The second problem with Aqua widgets is that they weren't designed to be scalable. Web sites like Orbitz style <select> dropdown lists by setting both an explicit width and a tiny font size using CSS. Safari's dropdown lists can't scale, which means that we honor the width but not the font size, and so you end up being unable to read what's selected in the dropdown list at all.
Not honoring the width of course is not an option, because then page layout is completely hosed. Not honoring the font size also hoses layout because the page frequently expects the widget to be a certain approximate height because of the small font size setting.
It's essentially absolutely critical now that widgets on the Web be fully scalable and support all properties in CSS that affect size, because that's how the widgets on Windows work.
It's kind of amazing to think that, because of Internet Explorer's dominance, the very way widgets have to be designed in order to avoid bad page layout must necessarily match the way widgets are designed on Windows. And people wonder why so many browser engines don't use native widgets...
A third problem with native widgets is the difficulty in supporting other CSS properties like colors and borders, although this is minor compared to the need to support size-affecting properties.
What's a Web browser to do? :)
Eric Meyer writes about Zen Garden also. He notes the use of span tags in the source and then goes on to say the following:
There are quite a few span elements littered throughout the Zen Garden's source, but as I've been finding recently, this is almost necessary. It's troublesome to me that really interesting CSS-based visual design should require that we clutter the document structure with gratuitous elements, but there truly doesn't seem to be a good way around this. It may be that future CSS, or some other styling language, will allow the author to create multiple layout boxes (or other shapes) for a given element and style them independently. The syntax would probably be weird compared to what we have now, but it would allow for a lot more design flexibility.
This is *exactly* a problem that XBL solves. You attach XBL to an element through CSS, and XBL can generate a complete anonymous content subtree that can then be styled using a scoped stylesheet applied to those elements. You can even scatter the real content however you'd like within the anonymous content tree.
XBL is a perfect tool for implementing complex layouts at the presentational level and preserving the purity of the main source document. XBL can even execute scripts for fancy animation effects or rollovers, all without the source document being polluted at all.
Currently XBL only works in Mozilla though, but you never know... ;)
comment (10) -Zeldman, sporting a new girlie blog look, writes about a cool site called Zen Garden by Dave Shea that demonstrates a bunch of cool CSS themes. Quoting Zeldman:
Currently, one or two of Dave’s layouts display incorrectly in Safari, but they work perfectly just about everywhere else, and Safari workarounds are apparently in the works.
No, don't work around bugs! Well, ok, work around them, but not before dropping by my blog here and giving me some nice reductions of the problems so I can fix 'em for you. Put me to work, Mr. Shea!
comment (9) -Do not attempt to adjust your Web browser. Redesign in progress. :) Pardon the mess.
Yikes. This bug is my fault. I only handle multiple generated content values if they're all text. Mixing text and images causes little Safari some serious pain. I'm working on a fix now.
Two cute examples of abuses of the English language in everybody's favorite layout engines (KHTML and Gecko).
The first is from KHTML. When an object in HTML (e.g., a <p> tag) has had its dimensions determined and has been placed somewhere, the method that is invoked to indicate that the layout is complete is setLayouted. To ask if an object needs a layout or not, you call layouted.
The term layouted is so insidiously catchy that it actually crept into my vocabulary.
"I don't get why this isn't laying out right!"
"Well, try stepping through the code!"
"Oh look, it's already been layouted! I guess it doesn't need to be layouted again."
ARGH! :)
The second is from Gecko and is my favorite. The act of laying out objects in Gecko is called reflow. However, when you flow an object for the first time, it's called the initial reflow. That's my favorite.
"Yes, that's right, I'm flowing it again for the very first time!" Uhh, say what?
Oh well, it could have been worse. At least I haven't seen too many abuses of it's vs. its in either engine lately. ;)
comment (35) -Those of you with Movable Type blogs may have noticed that the banners at the tops of your pages misrender in Safari v73. The reason is that the default Movable Type template stylesheet (styles-site.css) is invalid. It contains the following parse error:
letter-spacing: .none;
This is exposing a bug in Safari where rather than simply discarding only the single bogus declaration, Safari discards the whole rule. I have fixed this since v73, but if you want to work around the problem on your blogs, just remove this bad declaration from your CSS file.
It's a shame that the default template used by Movable Type doesn't even validate. Perhaps this has been fixed already in the newest version.
| Sun | Mon | Tue | Wed | Thu | Fri | Sat |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 | 31 |