html columns whose width automatically changes according to their content

Discussion in 'Web Design' started by erelsgl, Jul 24, 2012.

to remove all ads.
  1. erelsgl

    erelsgl New Member

    Messages:
    8
    I create dynamic HTML pages with 3 columns. Each column can contain a variable amount of text - from 0 to 1000 words. I want the text in the 3 columns look approximately the same height. So, I want to have the column widths change automatically according to the amount of text they contain.

    In HTML, this happens automatically in a table, when each cell has a single div of text, see the top table here:
    http://jsfiddle.net/erelsgl/RJa2k/3/

    However, when the cells contain several divs, this doesn't work anymore, see the bottom table there. The leftmost column is very narrow and tall, instead of being wider and shorter.

    Adding a "width" attribute to the leftmost column (by clicking the button) shows the expected result. However, I do not know in advance what column should be what width.

    Is it possible to have it adjusted automatically?
     
  2. chrishirst

    chrishirst Well-Known Member Staff Member

    Messages:
    2,662
    Yep.


    Use a table.
     
  3. Edge

    Edge Member

    Messages:
    461
    It's possible using either javascript or jquery to calculate the ratio of width to height and then reset width based on your result - bit of fun with maths and JS but nonetheless doable. However, as already commented, perhaps just swallow your semantic coding pride and just use a table.
     
  4. chrishirst

    chrishirst Well-Known Member Staff Member

    Messages:
    2,662
    What has "semantic coding" got to with it??

    If the data is tabular, which is what it appears to be. Then a table IS what should be used.
     
  5. chrishirst

    chrishirst Well-Known Member Staff Member

    Messages:
    2,662
    Although you could use the CSS3 mutiple column properties, which of course is NOT supported by Infernet Exploder as yet.
     
  6. erelsgl

    erelsgl New Member

    Messages:
    8
    Thanks, guys, but - I DO use a table! And it works well when each TD contains a single div, but when each TD contains several divs - it breaks. See the second table here: http://jsfiddle.net/erelsgl/RJa2k/3/
     
  7. erelsgl

    erelsgl New Member

    Messages:
    8
    CSS3 columns looks good, but, if I understand correctly, it is for a SINGLE piece of text that should be displayed in 3 CONTINUOUS column, while in my case, there are 3 different pieces of text, each should be displayed in its own column.
     
  8. chrishirst

    chrishirst Well-Known Member Staff Member

    Messages:
    2,662
    Fundamental HTML visual rendering rules.

    Table:
    Cells in the same row will all have the height of the "tallest" cell
    Cells in the same column will all have the same width as the widest cell.
    columns widths will be fixed width of table/column count.

    block elements: Will be as wide as the parent container or a defined width, height will vary with content.

    inline elements: Widths and heights will vary as the contents make them. The width until the padding edges of parent element restricts horizontal expansion and the content will then "wrap" to the next horizontal row, thus increasing the height.


    Now: Which set of rendering rules suits your requirement?
     
    Last edited: Jul 25, 2012
  9. PixelPusher

    PixelPusher Super Moderator Staff Member

    Messages:
    1,077
    First off, don't use a table. That is not the intended purpose of that HTML element. Resorting to it because you dont have a solution is a cop-out and this exact thinking is what leads to poor markup.

    Even Width
    Setting even width is simple, use percentage based values for your column widths.

    Even Height
    Setting an even height for all is not too difficult either. Use javasctipt/jquery to check the columns and set their height based on the tallest one.

    Example: Auto Height Columns
    (markup below)

    HTML
    HTML:
    <body>
    	<h1>Columns with Even Height</h1>
        <a id="toggle" href="#">Show/Hide Columns</a>
        <div class="cols">
        	<div>
            	<h2>Column One</h2>
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ipsum mi, dignissim in elementum eget, fringilla a velit. Nullam eu ligula tellus. Sed dui magna, hendrerit id tincidunt vitae, faucibus et est. Proin sed diam id nisl dignissim varius vitae sit amet ante. Donec sodales consequat magna, pharetra dignissim erat dapibus ut. </p>
            </div>
            <div>
            	<h2>Column Two</h2>
                <p>Etiam bibendum vestibulum leo vitae mollis. Nam vehicula est eu lorem tincidunt aliquam. Fusce sed urna et felis elementum feugiat. Fusce neque erat, commodo non fringilla id, euismod auctor augue. Integer rutrum elit a felis tristique at scelerisque leo mattis. Aenean vel justo eget tortor posuere posuere ut sed tellus. Pellentesque iaculis semper suscipit. In hac habitasse platea dictumst. Pellentesque et odio arcu, a feugiat lorem. Nunc eleifend, neque non accumsan semper, ante tellus tempor risus, at porttitor erat nunc quis justo. Sed turpis quam, placerat non molestie sed, semper eu justo.</p>
            </div>
            <div>
            	<h2>Column Three</h2>
                <p>Integer vestibulum dui ipsum, vitae fermentum urna. Integer quis faucibus urna. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
            </div>
        </div>
    </body>	
    
    CSS
    Code:
    html, body, div, p {
    	padding:0;
    	margin:0;
    }
    html {
    	background-color:whiteSmoke;
    }
    body {
    	font-family:'Lucida Sans', Helvetica, Sans-serif;
    	font-size:75%;
    	color:#333;
    	width:80%;
    	margin:6em auto 2em;
    }
    h1 {
    	font-family:Georgia, "Times New Roman", Times, serif;
    	font-size:2.7em;
    	color:#666;
    	text-align:center;
    	text-shadow:1px 1px 1px rgba(255,255,255,1);
    	padding:0 1em;
    	margin:0 1em 2em;
    	border-bottom:1px dashed #aaa;
    }
    h2 {
    	font-size:1.5em;
    	color:#68A700;
    	margin-bottom:1em;
    }
    p {
    	line-height:1.5;
    	margin-bottom:0.5em;
    }
    div.cols {
    	overflow:hidden;
    }
    div.cols > div {
    	float:left;
    	width:33.33333%;
    }
    div.cols h2, div.cols p {
    	padding-left:20px;
    	padding-right:20px;	
    }
    #toggle {
    	display:inline-block;
    	font-size:1.1em;
    	color:#C60;
    	text-decoration:none;
    	padding:0.5em;
    	margin:1em;
    	background-color:#ddd;
    	border:1px solid #ccc;
    }
    #toggle:hover {
    	background-color:white;
    	box-shadow:1px 1px 3px rgba(0,0,0,0.15);
    	-moz-box-shadow:1px 1px 3px rgba(0,0,0,0.15);
    }
    .visible {
    	background-color:#eee;
    }
    
    JS
    Code:
    <script src="http://code.jquery.com/jquery-1.7.2.min.js" type="text/javascript"></script>
    <script type="text/javascript">
    	$(function () {
    		var maxHt = -1;
    		var col = $('div.cols > div');
    		function setHeights() {
    			col.each(function(i, e) {
    				$(this).css('height','');
    				maxHt = maxHt > $(this).height() ? maxHt : $(this).height();
    			});
    			col.height(maxHt);
    			maxHt = 0;
    		}
    		
    		setHeights();
    		$('#toggle').click(function() { col.toggleClass('visible'); });
    		
    		$(window).resize(function() {
    			setHeights();
    		});
    	});
    </script>
    <style>
    
     
    Last edited: Jul 25, 2012
  10. chrishirst

    chrishirst Well-Known Member Staff Member

    Messages:
    2,662
    Why? To make an arbitrary decision about the HTML structure without knowing what the data to be displayed actually is seems a little rash.

    Using a jquery framework for a simple task like setting equal height columns is always something of an overkill.

    Eight or nine years ago I wrote 13 lines of javascript that did just that without needing the extra overhead of jquery.
     
  11. erelsgl

    erelsgl New Member

    Messages:
    8
    Thank you for the detailed code sample (which I put here: http://jsfiddle.net/57b39/7/ )! However, that is not exactly what I need. I don't want the columns to be equal width, on the contrary, I want their width to adjust according to their content, so that columns with more content are wider, and columns with less content are narrower. This way, the height of the content will be approximately balanced.

    This is easily achieved by a table, IF each td element contains exactly one paragraph. Can it be done without a table?
     
  12. PixelPusher

    PixelPusher Super Moderator Staff Member

    Messages:
    1,077
    He did mention he was having three columns with paragraphs in each. I assumed this was a layout for the main content of his page. If that is the case, my point stands. If not, then I stand corrected. Tables should not, in fact never, be used as a main structural basis for a website's content.

    jQuery overkill? Just for this perhaps. I see your point. However, there could well be other aspects of his site that he has not mentioned that would require js. In which case he is in prime standing.

    Plus, pulling the core from a CDN really doesn't create that much overhead (~60K).
     
  13. chrishirst

    chrishirst Well-Known Member Staff Member

    Messages:
    2,662
    WHY???????

    That sounds like the WORST possible example of a readable or usable layout I can imagine.

    There could exist a situation there where a "column" may be only one or two words wide!!!

    It is going against the natural reading habit/methods/teaching/rules of ALMOST EVERY LANGUAGE ON THE PLANET!!!!!

    Now if your documents are going to be Tategaki, then fine go ahead, but if you want them to be read in ANY western language, I would rethink the idea.
     
  14. PixelPusher

    PixelPusher Super Moderator Staff Member

    Messages:
    1,077
    Exactly!

    OP:
    The problem with your table solution is, like Chris stated, if you have a paragraph large enough it will crush the other two cells to a state that is barely readable. Meaning, you need to set width on the cells to limit this. Hence, back to my example.
     
  15. PixelPusher

    PixelPusher Super Moderator Staff Member

    Messages:
    1,077
    Your welcome, but wouldn't you rather have a consistent appearance to your site? Continually changing column widths seems odd to me :confused:
     
  16. erelsgl

    erelsgl New Member

    Messages:
    8
    Because I want the height to be as small as possible. The layout is used not only for web, but also for print. The more height - the more pages needed for printing it.

    If I set the column width to a constant, then in some cases one column will be very high, and will spill over to a new page, that will contain only the continuation of that column. I think it would be more convenient to make the column wider, so that it will all fit in a single page.
     
  17. chrishirst

    chrishirst Well-Known Member Staff Member

    Messages:
    2,662
    Laying out for print documents and designing layouts for web documents are different disciplines and making a dogs breakfast of your web layout should NEVER take precedence over a usable HTML document layout

    If you need a different print layout using CSS, then have a different style sheet for print using the media="print" attribute value.

    You can also use media queries to define different rule sets.

    ALSO

    page-break rules can be used in print style rulesets, whereas they do not have any effect in screen rulesets.
     
  18. PixelPusher

    PixelPusher Super Moderator Staff Member

    Messages:
    1,077
    Couldn't have said it better myself.
     
  19. erelsgl

    erelsgl New Member

    Messages:
    8
    Great insight, thanks!

    So, my original question pertains to this print-specific CSS: what should I put in that CSS, in order to have the column widths adjust to their content, and achieve minimum height?
     
  20. chrishirst

    chrishirst Well-Known Member Staff Member

    Messages:
    2,662
    This is off the cuff thinking and not actually tried and tested.

    Give the html and body elements 100% height to make them fit to the content length rather than stopping at the viewport height/length.

    Set display: table; with a 100% width and height on a "wrapper" element.
    Set display: table-row on a child element of "wrapper" with 100% height, Put your "columns" as child elements of this inner element, with 100% height and display: table-cell;.

    That should be a starting point at least. Not forgetting to allow for padding and margins in the 100% length/height calculations.
     

Share This Page