Friday, March 27, 2009

CSS Ideas

So I'm working with CSS, and for once I'm going to try to separate content from presentation from the outset, since that's such an in thing to do these days.

Immediately a pretty big limitation of CSS came to mind in regards to doing that, exactly what they're always beating you over the head with that you're suppposed to be using CSS for. I've already written a little bit about how CSS should have been different before, but here are some of the thoughts that came to mind now and some that have been brewing for a couple of weeks, ensuing my more recent work with Ecography.com..

So what tags do we have for containing content, other than div? Span would be nice, except that it has strange limitations: it can't contain certain other HTML tags, and apparently it can't even contain line breaks. So we just have div, and then whenever we don't want a damn margin, because all we want to do is demarcate data, we have to write CSS code to specify that. Divs also by default come below each other in sequence, unlike normal information which flows left to right, so that's another thing you sometimes have go out of your way to change in CSS.

So clearly we're missing something here, something in between div and span, or at least a span that likes people.

I've also seen ul's used with CSS, for menus. You have to modify them extensively to get rid of the bullets and margins, maybe make them go left-to-right, etc. It seems like they're being used in cases like these for something other than their intended purpose, and I tried doing the same thing in some other way than using ul's, and it didn't work. So that implies that ul's are being used to fill in for some other shortcoming.

What I really was thinking right now, though, is that the degree of separation of content from separation in CSS is very limited. Basically you can specify sequences of information-elements and in specific hierarchies, and then display those elements and hierarchies in any way you want, but if the way you want to display it involves changing the order of the information (without using absolute positioning) that's a no-go. That can only be done by editing the HTML or the scripting code. Since a CSS file is designed to define only attributes of classes/tags on a syntactic level, there really isn't remotely a way for it to specify order of information. It would have to be changed dramatically.

To preserve backward compatibility, and its ease of specifying attributes, a new kind of syntactical entity should probably just be introduced that can specify sequences and hierarchies of information. The content itself, which would be found in the HTML code, would simply be referred to by id attributes. In the interest of the XML movement and consistency with HTML, the new syntax should probably be HTML-like, perhaps a subset of HTML. But then again in the interest of consistency/simplicity, why limit the HTML? Just make it full HTML, the only difference being the referring to of information by id attribute. And what if the HTML itself contains id attributes? Just allow it to refer to those too, I think..

But this just begs for a much simpler and somewhat more generalized and versatile solution: a) allow *all* HTML to convey other parts of the HTML, referred to by their id attributes, and b) allow HTML to include other HTML files. B) isn't so radical, since HTML can already include .css, .js, and image files. We're only making it more consistent here.

Now the only problem is that there's the possibility for circular references. It's only a philosophical problem, though, since they can easily be detected and ignored. Meaning that the simple solution here is: Don't Code Circular References.

Admittingly, it is a little awkward to have to specify that the content be hidden so that it can be shown in the correct place. But there is a solution: relegate all such content to <content> tags, which are automatically hidden. Actually "content" is a rather ironic name for things that will be automatically hidden, but you get the picture: the tag can be called anything.

Another shortcoming, and this is really the one that bugs me most often, is alignment.

There's a *big* issue in CSS where all the CSS gurus yell DON'T USE TABLES, not for layout purposes. Now here's the rub: people use tables for a reason. It's *easy*. In HTML, and in almost every other area of computer technology and life itself, simple things should be able to be done simply. Doing the same things you can do with a table with CSS is a real P.I.T.A. It's not at all obvious how to do it (to understate the problem), it's not quick and easy, and even a highly paid web front-end guru admitted to me that CSS has shortcomings in this area, when I asked him if there should perhaps be a CSS-equivalent to tables.

Is there a way to create a feature something like tables, per se, for CSS? I don't know, because I don't know precisely what the contention is with using tables; i.e., in exactly what ways does using tables prevent one from customizing layout in CSS? Tables provide alignment. What do they disprovide, and would this same limitation apply to adding, per se, a table-like feature to CSS? How would we do that anyway, on a semantic level?

I think a more generalized/flexible solution would be to provide some kind of alignment tokenization. Like you insert a token A at point B, then at point C say align this edge or that edge of this element with token A. Since you don't really have a place *in* HTML *at* the right/bottom/etc edge of a layout element, then either Token A has to specify which edge of the padding, margin or border it's binding to, or Token A can simply bind to a layout element and Token B would specify which edge and such of Token A to align to.

It can be much simpler than that, though. You'll almost always want to align a left edge with a left edge, a right edge with a right edge, a border with a border, a content edge with a content edge, etc. This symmetry can be the only thing allowed, or it can be assumed by default allowing a simpler syntax in the most common usage, probably just by leaving out extra parameters: for example, you could align B's left border with "A" (implying A's left border), "A/content" (implying the left edge of A's content), "A/right" (implying A's right border), or "A/right/content".

There should probably be even further shortcuts: for aligning both the top and bottom with another element, both the left and the right, or the content, margin and border all at once. To align B's top and bottom with A's top and bottom, at all three box layers, we could just align "B/horiz" with "A". To align only the top and bottom borders, align "B/horiz/border" with "A".

Then of course, we could also use relative positioning via the normal syntax to shift Element B's left or right content, margin, or border left or right of A's, if we so wanted.

I've decided the only way to specify tokens we need is the id attribute. So A is called A because that element's id="A". This simplifies things.

Exactly how to specify the alignment remains in question. Associating somehow "B/left/border" with "A/margin" doesn't really fall into either CSS's or HTML's syntax. There are just no conventions for associating two relatively arbitrary values. We could just say, within B's definition, align-top-border: A/bottom, but then that would combinatorily create 12 to 24 new CSS key words. If CSS's syntax were a little more flexible, we could say align {top-border}: A/bottom, or better, something like position: relative; top-border: {align: A/bottom; whatever: 2px} (to align B's top border with A's bottom border and shift it down 2 pixels).

And perhaps it should be. Then we could even then do this, for example:
top-margin: {position: absolute; whatever: 100px}
bottom-margin: {position: relative; whatever: 2px}

Or perhaps it would be
top-margin: {position: absolute; 100px};
bottom-margin: {position: relative; 2px}


Of course another idea would be to simply have a completely separate alignment table:
align 
{
B/horiz/border: A/content;
C/horiz: D;
}
That syntax would have to exist alongside one of the other formulations if at all, though, because it allows no cascading definitions, it's not object/class-oriented, and it can't be done in-line.

This idea so far can't do everything tables do. It can't size a bunch of cells (divs) according to the widest or highest automatic size. Do we *really* need to do that for content layout, though? (Actually, i think we do.) And what if we wanted to align two or more left or top margins where they would naturally go if it were one long margin? So in these cases we're not specifically aligning A after B, nor B after A, but we want those margins all in the same alignment class. What could we do? Probably the best solution is just to align them to an arbitrary common name, the same way in which we would otherwise use an id. This name would never be followed by /top, /horiz/content, etc., though, because that would be meaningless.

*Now* our alignment can do everything tables can do (I think?).

But this behavior should not be an automatic fall-back when no object happens to have the given name as its id, because it's doing a rather different thing. But instead of inventing new key words to align this way, we probably should just precede the name with a special symbol, like a %.
<div style="align-top: %hitop; align-bottom: %hibot; float:left">
This div's<br/>
height adjusts<br/>
to the height<br/>
of its text.
</div>
<div style="align-top: %hitop; float:left">
This div is smaller.
</div>
<div style="align-top: %hitop; align-bottom: %hibot; float:left>
This div goes down just as far as the first div does.
</div>
That was just an example to summarize and to show how simple it can all be, but it also raises a minor issue I hadn't thought of: how can we do a "horiz" or "vertical" align (implying left & right or top & bottom) with a %-preceded name? Well I can't think of a sound and consistent way, so we may have to do it just as coded above. We *could* just have the right or bottom margin be a second value that's used only for "horiz" or "vertical" alignments, while anything else referring to that name simply uses the top or the left value, and if only *one* element does a horiz or vertical align with it, but other elements do single aligns, then said element would only align its left or its top side. But that's if CSS has a "tolerant" coding philosophy, which I know browsers do but I don't know if the w3c does.

No comments: