Laying out a school-timetable-like grid

I have a grid of data that I need to lay out with tight control over the layout.  Each row can have an arbitrary number of items, with arbitrary widths.  It's a bit like a school timetable:

|Monday |----- Maths --------|------------------ English --------------------|
|Tuesday|-- Maths --|--Science --|--Football--|-------Geography--------|

except that there are tens or hundreds of items per line, and their widths are arbitrary. The widths in a row always add up to the same total, so the whole thing is a rectangle.  The right-hand edge must be dead straight, as must any column within the grid (ie. a vertical set of items that start after the same cumulative total of preceding widths).

I'm converting this from a document that has exact layout (imagine it's a PDF), and I need to maintain its layout.  If I use pixels for the widths it all works perfectly, but then you can't view it at different text sizes (as in View / Text Size).

My thought was to use float:left divs for the items.  Here's an example:

<html>
<body>
<div style='width: 20em;'>
<div style='float: left; width: 4em; background-color: orange;'>Div A</div>
<div style='float: left; width: 4em; background-color: pink;'>Div B</div>
<div style='float: left; width: 4em; background-color: orange;'>Div C</div>
</div>
<div style='clear: both; width: 20em;'>
<div style='float: left; width: 3em; background-color: orange;'>Div A</div>
<div style='float: left; width: 5em; background-color: pink;'>Div B</div>
<div style='float: left; width: 4em; background-color: orange;'>Div C</div>
</div>
</body>
</html>

That should show the two 'Div C's lining up 8em from the left margin (the only difference between the two rows is 4em/4em vs. 3em/5em).  But in IE6 at the Smaller text size, they're off by one pixel.  There's also a problem in Firefox whereby single-pixel white horizontal or vertical gaps appear between the items at various font sizes, for which I have a partial workaround (http:Q_21201514.html), but it's not ideal.

These problems are almost certainly caused by rounding errors in the browsers, as they render my em units into pixels.  Similar problems occur if I use percentages.  How can avoid that?  How can I achieve the fine control over the layout that I need, and yet still have the page scalable using View / Text Size?
LVL 14
RichieHindleAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

RichieHindleAuthor Commented:
Just to clarify something: when I say "I'm converting this" I should say "I'm writing a C program to convert this" - I can't make any assumptions about what the grid contains beyond what I've said above.  And my program won't be able to make human judgements about how best to do its job.
0
krakilin2001Commented:
Why not simply use tables.  You can use the colspan and rowspan attributes to join table cells.  You would start by calculating the maximum number of divisions (hours, minutes, etc) and then join cells of different time periods to create the table.
0
RichieHindleAuthor Commented:
krakilin2001: I need to precisely control the width of the items.  Setting the width of table cells causes the same problems as I get with setting the width of divs - for example:

<html>
<body>
<table border='0' cellpadding='0' cellspacing='0'><tr>
<td style='width: 4em; background-color: orange;'>A</td>
<td style='width: 4em; background-color: pink;'>B</td>
<td style='width: 4em; background-color: orange;'>C</td>
</tr></table>
</body>
</html>

In Firefox 1.0, I get white gaps between B and C when I go Ctrl+Minus to reduce the font size.  The margin-left: -1px workaround suggested in http:Q_21201514.html causes text truncation in IE.
0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

krakilin2001Commented:
Could you give us an example of what exactly you are trying to lay out.  I feel this could help get us on the right track.
0
RichieHindleAuthor Commented:
It's the output of a report writer.  The file format is binary and needs a proprietary viewer, so there's no point making an example available, but I've put a sketch of how the output might look here: http://entrian.com/report.gif

The underlying format is a character grid, with pieces of text laid out on it.  So for instance, the item "Really Good Electronics" is at roughly position (15, 5), 15 characters in and 5 rows down (assuming rows 2 and 4 are blank).  Pieces of the output are tabular, but that's up to the report designer - the layout can be arbitrary.

If the whole thing were in the same fixed-width font, you could lay it out using <pre> and it would look fine.  But the user can change the fonts, which changes the layout.  If you put "12th November 2004" into a huge font, the first 18 character columns of the grid would grow wider to accommodate it, pushing the other items across the page so that everything still lined up.

It's that underlying character grid that makes the layout like a school timetable.  Imagine a timetable divided into 10-minute columns, where each column can have its own width.  For an 8-hour day, there would be 48 columns.  Now imagine a 48-character-wide report: same thing only with narrower columns.  Each character column can have its own width, determined by the fonts of all the items that intersect that column.

Looking at the example, you'd be tempted to convert to HTML by using a sequence of tables, one for "12th..." and "Page 1", one for "Total...", one for "Really Good..." and the address, one for the data grid, and one for "(This is...".  But note how "(This is..." lines up with "Really Good...".  That's why I need precise control over the layout - that sort of relationship must be preserved.  Also note how the data for Australasia is indented by one character under the heading - subtleties like that must be preserved as well.

If I didn't care about users changing their browser's font size, I could lay it all out by specifying pixel widths and it would be fine, but I need it to work at different browser font-size settings.

Sorry for the lengthy explanation, but it's a difficult problem to describe!  If I could award more than 500 points, I would.
0
COBOLdinosaurCommented:
Given the athe requirement is that an arbitray number of variables arbitray value can be presented without restrictions on format; and the expectations is to produce a predictable layout my response is that the requirements are not reasonable and unless there is some limit to the variabilty of the input then the only reliable prediction of output is that it will produce out with unpredictable properties.

In other words given the current requirements... not going to happen with the browser technology currently available in this universe.  You need a piece in the middle to convert to a predictable format for the browser.

Cd&
0
COBOLdinosaurCommented:
An XML dataset might be the intermediate format you need.

Cd&
0
krakilin2001Commented:
I agree with COBOLdinosaur.  The way you are describing the layout, it would be very difficult to accomodate all circumstances.  An XML document could work well.  If well-designed, you would simply need to create an XSLT document afterwards.  However, you may also want to consider creating some type of graphic image format or even PDF.  In either case, if you already have the coordinates of each element calculated, you should be able to position each element with relative ease.
0
RichieHindleAuthor Commented:
I was right with you, nodding sadly, thinking you were right that what I want is beyond current browsers, until you started talking about XML.  Now I'm wondering what I've missed.  Why would using XML/XSLT change the limits of how the browsers can render the data?  As I understand it, the XSLT would convert the XML into HTML/CSS and I'd be back where I started.

As for using a more suitable format like PDF, yes, the product can already do that.  The requirement is for purely browser-based report viewing, without any reliance on plugins.  We already have HTML output for this, but it's not as WYSIWYG as we'd like.  This is an attempt to use modern HTML/CSS to make the HTML output more WYSIWYG.
0
COBOLdinosaurCommented:
Insert tags or attributes during generation of the xml file to indicate the infromation about size and co-ordinates; or anything else that is need for rendering.  Then when the xml is processed through xslt the additional information makes dynamic styling much more a task in coding a few rules instead of data content analysis.

Cd&
0
COBOLdinosaurCommented:
You could also put the raw xml file in the page as a data island and use Javascript to parse it and generate the HTML, but that will be less efficient and marginally less reliable.

Cd&
0
RichieHindleAuthor Commented:
Sorry, I really don't follow.  Using XML/XSLT can move some of the work to the client, sure.  But at the end of the day, either the browser can render the data how I want, or it can't.  The delivery mechanism doesn't matter - whether I do all the work in C, or move some of it to XSLT, I'll still get little white gaps in Firefox.  I can't even hand-craft HTML to work properly (which is where we came in).  I'm inclined to agree that "given the current requirements... not going to happen with the browser technology currently available".
0
GrandSchtroumpfCommented:
Now if you want to use the margin -1 trick, you will need to add -1 per number of unit elements of your div, this way you'll get the same total offset at the end of each line, no matter how many divs are in the line.  e.g.  if your div is 3 unit-increments, you will use left-margin = -3.
This will work for all divs except for the first one of course... so, you would need to find another trick for that... but it would be a big headache.

However, if you use tables with 'table-layout: fixed', everything looks perfect in both browsers:
You set the total width of your table (either an 'em' value or a '%' value) and use colspan do define your cell weight.  It's very flexible.  The only thing is that the colspan values must be positive integer values and the total for each line should be equal.  It's now up to you to divide your timetable in as many cells you want.

The only thing is that IE does not handle the size of the cells too well... take a look at the 100% table and resize your IE window.  You can see that the resize is made by chunks while in FF is seems very smooth (that's the great thing about FF not rounding the values).  If you multiply the colspan values by 10, you'll see it even better.  So, here is one more point for FireFox.
Anyway, if you use a table, you'll be certain the borders of the cells in different lines will align correctly.

here is the code:


<div style='padding: 3em;'>

<table class='TimeTable' border='0' cellpadding='0' cellspacing='0' style='table-layout: fixed; width: 12em;'>
<tr>
<td colspan='4' style='overflow: hidden; background-color: orange;'>A</td>
<td colspan='4' style='overflow: hidden; background-color: pink;  '>B</td>
<td colspan='4' style='overflow: hidden; background-color: orange;'>C</td>
</tr>
<tr>
<td colspan='3' style='overflow: hidden; background-color: orange;'>A</td>
<td colspan='5' style='overflow: hidden; background-color: pink;  '>B</td>
<td colspan='4' style='overflow: hidden; background-color: orange;'>C</td>
</tr>
</table>

</div>
<div style='padding: 3em;'>

<table class='TimeTable' border='0' cellpadding='0' cellspacing='0' style='table-layout: fixed; width: 100%;'>
<tr>
<td colspan='4' style='overflow: hidden; background-color: orange;'>A</td>
<td colspan='4' style='overflow: hidden; background-color: pink;  '>B</td>
<td colspan='4' style='overflow: hidden; background-color: orange;'>C</td>
</tr>
<tr>
<td colspan='3' style='overflow: hidden; background-color: orange;'>A</td>
<td colspan='5' style='overflow: hidden; background-color: pink;  '>B</td>
<td colspan='4' style='overflow: hidden; background-color: orange;'>C</td>
</tr>
</table>

</div>
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
RichieHindleAuthor Commented:
GrandSchtroumpf: That looks very promising!  Many thanks - I'll see how well I can apply it to my problem and report back.
0
RichieHindleAuthor Commented:
GrandSchtroumpf: Your 'table-layout:fixed' technique works very well - many thanks!
0
GrandSchtroumpfCommented:
you are welcome Richie, <:°)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
CSS

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.