Announcement

Collapse
No announcement yet.

De-tabulating vBulletin Forumdisplay

Collapse
X
Collapse
 

  • Kier
    started a blog post De-tabulating vBulletin Forumdisplay

    De-tabulating vBulletin Forumdisplay

    A major feature slated to debut with vBulletin 4.0 is a new front-end style marked-up with semantic XHTML and styled with CSS.
    The task of producing the new templates using this scheme has thrown up all manner of questions, challenges and show-stopping problems, one of which I will discuss here.

    Background

    In vBulletin 3.x, the primary markup vehicle was the HTML <table> tag and almost all elements on vBulletin pages could be summarized as having the following basic structure:

    HTML Code:
    <table class="tborder">
    <tr>
    	<td class="tcat">Main heading</td>
    </tr>
    <tr>
    	<td class="thead">Sub-heading</td>
    </tr>
    <tr>
    	<td class="alt1">Some content</td>
    </tr>
    <tr>
    	<td class="alt2">Some more content</td>
    </tr>
    <tr>
    	<td class="tfoot">Block footer</td>
    </tr>
    </table>
    <br />
    Using this scheme, there is semantically no more value to the main heading than to any other tag in the block. Furthermore, the <table> tag and its contents strictly dictate how the element will appear; CSS has only a limited scope to change the fundamental structure of <table> elements.

    Itís worth noting at this point that the use of the <table> tag for this (or any other) purpose does not mean that the markup is not valid XHTML. In fact, the majority of pages in vBulletin 3.x validate against the standard to which they are built, namely XHTML 1.0 Transitional.

    However, itís clear that a major part of a move to semantic XHTML will involve using more suitable markup for page elements, making use of tags that more accurately describe their content and contextualize it on the page.

    Threadbit

    One page that presents quite a conundrum is forumdisplay.php: the page that shows the list of threads in a forum. Letís take a look at how the thread list has been presented in past versions.

    Firstly, we have vBulletin 1.x.



    Here, the thread data is presented in classic tabular fashion, with a single data point in each column, with the exception of the ĎLast Postí column, where we show both the time and the writer of the most recent post to the thread in question.

    This is how the thread list looked in vBulletin 2.x.



    The data is still largely tabular, though we are starting to see content other than just the title in the ĎThreadí column, namely the icon to represent a thread containing attachments and the ĎPoll:í prefix.

    With vBulletin 3.x, there was an attempt to cut down the number of columns.



    We can see that the name of the thread starter has moved into the same column as the thread title, placed on a new line. The rating stars have also migrated into the same column and there are several more icons representing different attributes of the thread.

    The question is:
    Is the vBulletin 3 thread list still tabular data?

    At first sight, yes it is. We have a number of columns each containing data and the arrangement looks like a grid. But do we consider the thread list to be tabular data simply because it is arranged in this way?

    If we extract all the data and put each individual item into its own column, as should arguably be the case in order for the use of <table> to be semantically correct, we would end up with the following columns:
    1. Status icon (read/unread, hot, moved, locked, posted-by-viewer)
    2. Post icon
    3. Prefix
    4. Title
    5. Thread poster
    6. Replies
    7. Views
    8. Rating
    9. Last post date / time
    10. Last poster
    11. Poll indicator
    12. Sticky indicator
    13. Attachment indicator
    14. Tag indicator
    15. Subscription indicator
    16. Deleted thread indicator
    17. Contains deleted posts indicator
    A table with this many columns is not going to win any design awards. It would be fine to view in Excel, but as an immediately accessible, visually attractive web page, itís going to look pretty terrible.

    The Requirements

    The basic structure I require visually is that of a table. I need a liquid column (one that stretches to occupy available space) followed by a number of fixed-width columns. Each column must be capable of supporting a background colour or image that will fill the cells.

    The old way to achieve this would be to use a <table> tag with rows styled in the following way:
    HTML Code:
    <tr>
    	<td bgcolor="#FF9999">(liquid column)</td>
    	<td bgcolor="#99FF99" width="50">(fixed 1)</td>
    	<td bgcolor="#9999FF" width="100">(fixed 2)</td>
    	...
    </tr>
    Of course, we want to avoid using a <table> tag if at all possible, given that our thread list is not strictly tabular data. Happily, most modern browsers give us an alternative that offers all the benefits of a <table> but without the semantic ambiguity, namely the CSS attribute display:table-cell. This would allow us to produce a layout visually identical to a table, but using semantic mark-up, such as this:
    HTML Code:
    <style type"text/css">
    .table { display:table; width:400px; }
    .row   { display:table-row; }
    .cell  { display:table-cell; }
    .liquid { background:#FF9999; }
    .fixed50 { background:#99FF99; width:50px; }
    .fixed100 { background:#9999FF; width:100px; }
    </style>
    ...
    <li class="row">
    	<h3 class="cell liquid">(liquid column)</h3>
    	<div class="cell fixed50">(fixed 1)</div>
    	<div class="cell fixed100">(fixed 2)</div>
    	...
    </li>
    This screengrab shows how Firefox 3 renders the two different HTML snippets. Itís obvious that they are visually identical.



    This markup allows radical restyling of the appearance of the thread listing and completely avoids the problematic <table> element. So, problem solved? Unfortunately not. There is one teeny tiny problem that is getting in the way of our goal. Itís called Microsoft Internet Explorer.

    Making IE Work

    Although support for display:table-cell has been introduced in Internet Explorer 8, the reality of the situation is that IE8 is not yet out of beta, leaving IE7 as the current primary version. Whatís more, a significant portion of the web-browsing population is still using (shudder) IE6. Prior to IE8, display:table-cell is not supported at all in Internet Explorer. Given that Internet Explorerís market share still represents a significant majority, there must be a workaround so that Internet Explorer users are not presented with a disastrous mess when they visit sites running vBulletin.

    If we feed IE7 with the same CSS as we present to other browsers, IE7 will ignore the display:table-cell instruction, resulting in the cells being represented as horizontal blocks.



    Inline-Block

    Internet Explorer 7 does implement a CSS property that can offer some help in this instance, namely display:inline-block. We donít want other browsers to see the inline-block instruction, so we will create a new stylesheet surrounded by Internet Explorer conditional comments.

    Unfortunately, IE7 seems to have some bugs related to inline-block that need to be carefully prodded to make the system work. For some reason, a simple declaration of display:inline-block seems to have no effect, but it can be made to work by following it with a display:inline call. Yes, itís that weird.
    HTML Code:
    <--[if lt IE 8]>
    <style type="text/css">
    .cell {
    	display:inline-block;
    }
    .cell {
    	display:inline;
    }
    </style>
    <![endif]-->


    We can see from the preceding screengrab that IE is now attempting to place the blocks next to each other rather than stacking them vertically, but the liquid column is expanding to fill the whole width of the container, rather than only occupying the space left by the fixed columns. For the time being, weíll fix this by specifying a fixed width for the liquid column. Weíll come back to the liquid problem later.



    Finally, IE7 is displaying all the blocks horizontally in table fashion, but unlike a true table, the cells are not all of equal height.

    Equal Height Cells

    We start by specifying vertical-align:top for all cells, which will cause them to be aligned along a single top edge rather than the bottom edge.

    The next task is to make all the cells of equal height Ė all must expand or contract automatically according to the natural height of the highest cell in the row.

    We start by adding a massive amount of padding (9999px) to the bottom of all cells, such that it will extend well past the bottom of the browser window. We then reign that back in with a negative value (-9999px) for the bottom margin. This will look extremely strange and drop all the cells of the bottom of the page, until we instruct the row to hide any overflowed content.
    HTML Code:
    <!--[if lt IE 8]>
    <style type="text/css">
    .row {
    	overflow:hidden;
    }
    .cell {
    	display:inline-block;
    	vertical-align:top;
    	padding-bottom:9999px;
    	margin-bottom:-9999px;
    }
    .cell {
    	display:inline;
    }
    </style>
    <![endif]-->


    Single Liquid Cell

    We now have (what looks like) cells of equal sizes, which expand and contract vertically as they should. The last thing that remains is to get our liquid column working.

    Internet Explorer supports expressions in CSS, which is a very powerful system allowing CSS values to be generated by Javascript. We will make use of this system to calculate the amount of space left in the row container after the fixed width cells have been inserted. The remaining width will be applied to the liquid column. I wrote a little function called liquid_td to handle this.
    HTML Code:
    .liquid {
    	width:expression(liquid_td(this));
    }


    No-Javascript Failsafe

    Everything now looks correct, though our use of expression falls over if we encounter a visitor running Internet Explorer with Javascript disabled.

    To handle this worst-case scenario, we must abandon our liquid-fixed-fixed layout and switch to a completely liquid system, specifying all the widths in percentages. This will require a further stylesheet, this time surrounded by <noscript> tags to hide it from browsers that donít need it.

    Unfortunately, this flings us headlong into Internet Explorerís lack of common sense when it comes to math calculations. One might expect that 60% + 15% + 25% = 100%, but Internet Explorer disagrees from time to time. The problem appears to be one of unintelligent rounding. Here are a pair of examples that illustrate the problem.

    Example 1: Container width = 400px.
    • 60% of 400 = 240
    • 15% of 400 = 60
    • 25% of 400 = 100
    • 240 + 60 + 100 = 400.
    • Result: all columns fit.
    Example 2: Container width = 399px.
    • 60% of 399 = 239.4, rounds to 240
    • 15% of 399 = 59.85, rounds to 60
    • 25% of 399 = 99.75, rounds to 100
    • 240 + 60 + 100 =400
    • Result: last column drops because 400 pixels do not fit into 399 pixels.
    To deal with this problem, we need to set the width of the first cell to 0.1% less than the desired value. This appears to instruct IE to round down instead of up, resulting in the correct number of pixels being calculated.

    Conclusion and Discussion

    Our final system works like this:
    HTML Code:
    <style type"text/css">
    .table { display:table; width:400px; }
    .row   { display:table-row; }
    .cell  { display:table-cell; }
    .liquid { background:#FF9999; }
    .fixed50 { background:#99FF99; width:50px; }
    .fixed100 { background:#9999FF; width:100px; }
    </style>
    <!--if lt IE 8]>
    <style type="text/css">
    .row {
    	overflow:hidden;
    }
    .cell {
    	display:inline-block;
    	vertical-align:top;
    	padding-bottom:9999px;
    	margin-bottom:-9999px;
    }
    .cell {
    	display:inline;
    }
    .liquid {
    	width:expression(liquid_td(this));
    }
    </style>
    <noscript>
    <style type="text/css">
    .liquid { width:59.9%; /* we actually want 60% */ }
    .fixed50 { width:15%; }
    .fixed100 { width:25%; }
    </style>
    </noscript>
    <![endif]-->
    So, now we have a working system to emulate table cell behavior in our target browsers.



    The question now is:
    Was it all worth it, just to avoid using a <table> tag?

    • nwingate
      nwingate commented
      Editing a comment
      Any more progress updates? These are great to see.

    • GHOwner
      GHOwner commented
      Editing a comment
      Be sure to add additional names to the tags so we can alter the look of certain thread displays, possibly by adding class="cell forumid2" or so.

      Also, although much of the new styling works well with the default skin, be sure to make ALL aspects customizable. You wouldn't want to just see clones of your work and hardly any alterations, yeah? I say this for lots of the new products (blog, new templates, etc) seem limiting and not friendly on customization with basic style tools. They also seem to not follow the framework too well because of the new style of coding.

      I'm all for innovative, but be sure to not force it. I do love the one-icon use for the thread listing. One thing I've wanted to do is make the icons more understandable by first impression, as it'll give more use and exposure.

    • petteyg359
      petteyg359 commented
      Editing a comment
      Backwards compatibility FTL. If all the idiots out there still using IE6 start seeing that nothing on the internet is working for them anymore, maybe they'll get their butts updated...
    Posting comments is disabled.

Related Topics

Collapse

Working...
X