I am trying to create CSS for the following layout. This is very similar to a table, but I am using it to render XML that does not contain tabular data.
I want two or more columns and one or more horizontal rules (invisible lines) running through those columns. The vertical space between the rules is determined exactly like a table's row height, by the maximum height of content in that row's cells.
All "cells" in this "table" contain two optional blocks. The upper block is aligned below the upper rule. The lower block is aligned above the lower rule. Here is an illustration:
The above and below blocks are both optional, so each "cell" will have one of the following configurations. The blocks do not have a fixed height; they may contain text that wraps depending on the width of the "cell".
Since this is so much like a table, I tried rendering it with display:table
. First problem: how can I create both upper and lower blocks inside a single table-cell
? Here's my first attempt.
I think this is equivalent to the problem of "floating" a block at the bottom of its container. The accepted answer to this question suggests this may not be possible.
XML fragment
Here is a simplified sample of the XML I'm trying to render.
<block>
<horizontal-rule>
<column>
<above-rule>When in the Course of human events</above-rule>
</column>
<column>
<above-rule>to dissolve the political bands</above-rule>
<below-rule>it becomes necessary for one people</below-rule>
</column>
<column>
<below-rule>which have connected them with another</below-rule>
</column>
</horizontal-rule>
</block>
In attempting to get this to work, I have been experimenting with a modification to my original XML schema. In this second XML sample, instead of grouping by the adjacent horizontal rule, I'm trying a more "table"-like grouping by row. In the translation, the <above-rule>
becomes <cell-bottom>
and <below-rule>
becomes <cell-top>
. I prefer the original one, but I've made more progress with this one.
<block>
<row>
<cell>
<cell-bottom>When in the Course of human events</cell-bottom>
</cell>
<cell>
<cell-top>it becomes necessary for one people</cell-top>
<cell-bottom>to dissolve the political bands</cell-bottom>
</cell>
<cell>
<cell-top>which have connected them with another</cell-top>
</cell>
</row>
</block>
A Really Ugly Solution
I have one idea that is particularly ugly. I can modify my XML schema and require the entire XML <block>
to be repeated twice with the exact same content. Then I put both copies of the <block>
in a wrapper element <block-wrapper>
and I define separate styles for the first child of the wrapper and the last child of the wrapper.
The first child aligns cell contents at the top and hides the <bottom>
blocks. The last child aligns cell contents at the bottom and hides the <top>
blocks.
I use position:absolute
to make the two rendered tables overlap exactly.
Here's an implementation of this idea.
Questions
- Is there a better way of doing this?
- I've read lots of debates about tables and CSS. Is
display:table
a smart approach? - Is there any way of using my original XML schema?
- I'd like to be able to distribute just the XML document and a user with the CSS can view it in a browser. But would it instead be better to insert a XML-transformation step, to create an intermediary XML schema that is easier to render with CSS? (My ugly solution might not be so bad in that case.)