Dynamic user-controlled layout in a CMS

This article is meant to hold some of the thoughts that I've been having about allowing a user to control the layout of a page, in particular for use within a content management system (CMS). The system would need to be able to support a user creating templates easily, but hopefully without the use of tables.

In the CSS Advanced Layout Module, there is a draft specification for Template-based positioning.

This uses @, . and letters to specify not only how the content is to appear, but also where the content appears. That is, . are used for whitespace and letters and @ are used for content placeholders.

For example, a first page of a newspaper might have the following template (bottom of 3.7):

display: "A  A  A  A  A  A  A  A  A" / 5cm
            ".  .  .  .  .  .  .  .  ." / 0.25cm
            "B  .  C  C  C  C  C  C  C"
            "B  .  C  C  C  C  C  C  C"
            "B  .  C  C  C  C  C  C  C"
            "B  .  C  C  C  C  C  C  C"
            "B  .  C  C  C  C  C  C  C"
            "B  .  D  D  D  D  D  D  D"
            "B  .  D  D  D  D  D  D  D"
            "B  .  E  E  E  .  F  F  F"
            "B  .  E  E  E  .  F  F  F"
            "B  .  E  E  E  .  F  F  F"
            * 3em * 3em * 3em * 3em *

This would give a header (A), an article spanning the full left-side of the page (B), two main stories (C and D), and two smaller stories (E and F). The specification also has information about sizing, which you see at the far right and bottom.

While I like this, ultimately for the Web you'll have content that fills it's slots, usually. So, we could simplify this, I think, by making it as follows:

display: "A  A  A  A  A  A  A  A  A"
            ".  .  .  .  .  .  .  .  ."
            "B  .  C  C  C  C  C  C  C"
            "B  .  D  D  D  D  D  D  D"
            "B  .  E  E  E  .  F  F  F"

In addition to dropping the sizing information, I've removed any duplicate row. While it doesn't immediately give us an indication of what the page will look like, as the first case does, it's actually pretty close - we still can determine what the content is, and how it spans.

However, I'm not sure that this adequately states the layout that is desired. If you examine the image that was used, copied below, you'll notice something.

W3C example newspaper layout

First, using the far left-side column as our guide, we've actually got five columns on this page (look at the very last 'line' on the page). In other words, the following line is incorrect.

"B  .  E  E  E  .  F  F  F"

Instead, this should actually be as follows.

"B  .  E  E  .  F  F"  

Obviously, this would continue on up through all the lines.

Also, spacing can be determined via other CSS methods, and should not be a part of the template itself. It seems unnecessary to using periods for spacing, when we've already defined content areas.

Therefore, I believe we could end up with something like the following, using this system.

display: "A  A  A  A  A"
            "B  C  C  C  C"
            "B  D  D  D  D"
            "B  E  E  F  F"

This states the following:

Content A should span the entire top of the page. Below this, content B should span the entire left-side of the page, with content C, D, E and F on the right. Content C is displayed first, on its own row, followed by content D, with the same behaviour. Finally, content E and F are displayed, to the left and right, respectively, of the other. Content C and D should be twice as wide as content E and F. Likewise, content E/F should be twice as wide as content B.

To continue, what would need to be parsed is the content within the quotes, and whitespace doesn't really matter. Therefore, we have the following as the core 'code.'

A A A A A
B C C C C
B D D D D
B E E F F

To the computer, assuming no more than 26 elements on a page (or 52 if lowercase characters were determined to be different than uppercase), this would be the same:

AAAAA
BCCCC
BDDDD
BEEFF

However, since spacing helps us, and to allow for the most content, we'll leave spaces in. (This could also allow a greater number of 'blocks' to be added to a page, even excluding allowing uppercase to be different than lowercase. For example, allowing AA and AB to be used.)

Getting back on track, I believe there's a different, and better, way to call out this content.

As stated above, we basically have a 5-column layout, of x width. The layout contains six elements of variable height.

The first row consists of one block spanning all five columns.

The second row consists of two blocks, one spanning one column, another spanning four.

The third row also consists of two blocks, one continuing to span one column, another spanning four.

Finally, the fourth row consists of three elements. The first column continues the element from the previous two rows, while the next, and last, two span two columns each.

Using only numbers, we have a layout something like the following.

5
1 4
1 4
1 2 2

However, based upon this layout alone, we don't know what content belongs where. Also, we can't clearly see that there is a left-side column that spans three rows. Using the following, however, might suggest that.

5
1 4
0 4
0 2 2 

I use a 0 here because while there is an element there, it is not the first instance, or primary location, of that element. This system instantly gives us access to not only the placement of elements, in a general way, but also how many 'blocks' the content consists of.

If we were to create a layout for the standard three-column template, with a full header and footer, we'd have something like the following:

3
1 1 1

Here, while the blocks are designed by the template to be the same size, we could use CSS to effectively make the middle column much larger, instead of using the following:

5
1 3 1

Using these same CSS techniques, a standard two-column interface:

2
1 1

Perhaps in the three-column interface we no longer want the footer to display under the left-side column?

3
1 1 1
0 2

Don't display it under the right column either?

3
1 1 1
0 1 0

Now what if we want to put the left-side column up within the header, and put back our footer to span the full length of the bottom of the page?

1 2
0 1 1
3

How about on the right-side instead?

2 1
1 1 0

Since the first row would always contain the number of columns, we could simply do the necessary math to determine the number of core columns. If there is more than one number, you simply add all numbers together.

This also allows you to put the entire layouts information in one string. Using our last example, we could have something like "2 1; 1 1 0; 3;" (adding semi-colons at the end of every line, even the ending one). Or, "2 1, 1 1 0, 3," or any other character we may desire as a standard.

However, there's one thing that we may have missed.

AAAAA
BCCCC
BDDDD
BEEFF

5
1 4
0 4
0 2 2 

As you can see, there's no easy way to link elements up with the content that they contain. What if we wanted to switch the second and third rows? With the first instance, that would be done, while in the second, it would need to be done outside of the core template.

On the one hand, the 'separate content from display' hand, that's okay. On the other hand, there's something to be said about keeping these things together.

Using the W3C proposal as a guideline, we could solve this by adding characters to our numbers.

5:A
1:B 4:C
0:B 4:D
0:B 2:E 2:F

5:A , 1:B 4:C , 0:B 4:D , 0:B 2:E 2:F ,

It's questionable whether it's necessary to have 0:B instead of 0. However this would make it easier to add CSS without the use of another parser, such as a CMS (which would read/write this, as well as allow classes and ids to be assigned to the elements).

Also, the colons could change to something more applicable, such as a . or # (# would be similar to the existing CSS practice of using this for id declarations in CSS).

Thoughts? Are there instances where this wouldn't work? Would this be a suitable way for someone to learn how to create a layout, or is it at least easier than the W3C proposal ( :) )?

My next step with this will be to determine if a solution could be created that would read a string formatted like this, and then create a page based upon it, probably using tables before moving onto CSS.