Question from a CSS dummy

CSS always sounds like a wonderful solution to all my cross-browser layout problems, and yet every time I use it, I end up completely baffled about how it can behave so completely differently from browser to browser. View this page in IE, and it behaves exactly how I want it to: http://www.codsquad.com/~galt/csstest.html View it in firefox, and it’s severely broken. Firefox seems to ignore my width and height specifications on my boxes, and doesn’t seem to do anything useful with “display: inline;”.

Now, I’ve specified my DOCTYPE as HTML 4.0 TRANSITIONAL, which should probably change, but my question for the CSS-savvy out there is: how do I achieve this simple layout behavior in a portable way?

The goal is to have multiple blocks of whatever that behave as atomic blocks, positioning themselves relative to one another in an “inline” manner, rather than in a “block” manner. And I want to do it without using absolute positioning, because the whole thing needs to flow as the window resizes.

Any ideas? Why so hard?

I’m not a CSS guru, but the first obvious problem I see is your nesting of the paragraph blocks (the “here are three paragraphs nested inside of one”). You should be using nested <DIV>s instead – e.g., wrap your three boxyboxes inside of a “container” <DIV>.

IE is notorious for screwing up the CSS standards; don’t put too much faith in its accuracy.

Anyway, I dinked around a bit and got it to work. Try this:



<HEAD>
    <STYLE TYPE="text/css" MEDIA="screen">
        body
        {
            text-align: center;
        }
        
        P { border: 2px solid #FF0000; }

		div.contain { align: center; }
		div.bottom { clear: left; }
		        
        .boxybox
        {
        	display: inline-block;
            border: 5px solid #000099;
            background-color: #eeeeff;
            overflow: hidden;
            padding: 10px;
            margin: 10px;
        }

    </STYLE>
</HEAD>
<BODY>
    <DIV>
        <H1>Here is a heading</H1>
    </DIV>
    <P>
        <DIV CLASS="dboxybox" STYLE="width: 200px;">
            Here is a box in a <P> by itself.
        </DIV>
    </P>

    <P>And here are three boxes in a single <P>:</p>
        
<center>
    <div class="contain">
        <DIV CLASS="boxybox" STYLE="width: 200px; height: 200px;">
            This is the first box.
            This is the first box.
            This is the first box.
            This is the first box.
            This is the first box.
        </DIV>
        
        <DIV CLASS="boxybox" STYLE="width: 200px; height: 200px;">
            This is the second box.
            This is the second box.
            This is the second box.
            This is the second box.
            This is the second box.
        </DIV>
        
        <DIV CLASS="boxybox" STYLE="width: 200px; height: 200px;">
            This is the third box.
            This is the third box.
            This is the third box.
            This is the third box.
            This is the third box.
        </DIV>
    </div>
</center>

	<div class="bottom">
    <P>
        Note that when you resize the window, these three boxes reflow
        to fit, much like <IMG>s would.  They can sit side-by-side
        if they fit, because they specify <code>display: inline;</code>
    </P>
    <P>
        This only works in IE.  How should this be done portably?
    </P>
    </div>
</BODY>


Things to note:

  1. The “boxybox” style uses “inline-block” to keep the boxes as blocks, but positioned inline.

  2. The various <DIV>s help organize the page elements and allow them to be properly nested/separated.

  3. The <CENTER> tags keep the “contain” <DIV> (holding the three floating boxes) on the center of the page. I think there’s a more CSS-elegant way of doing it, but it’s rather late here and I’m too lazy to play with it more. :wink:

Element positioning in CSS is not a trivial thing to learn, but it lets you do a lot once you figure it out. I recommend going to Position Is Everything and dissecting their examples.

Oh, and I put the red lines around the <P>aragraphs just to make it easier to see where the paragraphs were being laid out. Very useful trick for debugging CSS positioning.

I’m a little confused by your response. You say I have nested paragraphs, but I don’t. I have 3 DIVs inside a single P. What’s wrong with that?

Also, your example doesn’t seem to work for me. It’s at http://www.codsquad.com/~galt/csstest3.html and all the boxes get put on their own lines, even if there’s room for them all on one.

In case you’re interested, this site has some excellent tips about avoiding the cross-browser problems that you are likely to encounter when using CSS. They also have some excellent general CSS tutorials, and links to other great sites.

My mistake; that’s why I don’t do web work past midnight. :wink: But I’m pretty sure nesting <DIV>s inside a <P> is a no-no.

Hmmm; it works fine for me on Safari and IE for the Mac. Could it be a bug with IE6 for Windows?

I note that if you replace “display: inline-block;” with “display: inline;” in the .boxybox style descriptor, it works – but then I’ll bet it won’t work for other browsers again. Not sure if a passing CSS wizard can suggest a solution, but it might be worth investigating using three separate box styles (.leftbox, .centerbox, .rightbox), along with a combination of floats and margins, to get the effect you want.

If so, it’s also a bug in firefox for windows. I can’t get firefox to do anything that remotely makes sense with “display: inline-block;”

Tough question. After reading the CSS specs (I think spec. writers must write insurance policies for fun; I get cross-eyed looking at either) think that the problem is that according to CSS2, an inline element cannot specify its width or height. I’m not at all sure about this, though, and I don’t feel like reading closely enough to be sure.

The only way I’ve figured out to get similar behavior here in Mozilla is to specify the elements not as display:inline but as float:left. They will stack nicely left-to-right to fill the available width, although they are left-justified and not centered as with IE. The other problem is that any extra space on the right side will happily fill up with following text. To avoid this, give the next DIV element a clear:left style so it won’t sit to the right of any floats:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" >
<HTML>
<HEAD>
    <STYLE TYPE="text/css" MEDIA="screen">
        body
        {
            text-align: center;
        }
            
        .box1box
        {
            width: 200px; height: 200px;
            border: 5px solid #000099;
            background-color: #eeeeff;
            overflow: hidden;
            padding: 10px;
            margin: 10px;
        }
            
        .boxybox
        {
            width: 200px; height: 200px;
            border: 5px solid #000099;
            background-color: #eeeeff;
            float: left;
            overflow: hidden;
            padding: 10px;
            margin: 10px;
        }

    </STYLE>
</HEAD>
<BODY>
    <DIV>
        <H1>Here is a heading</H1>
    </DIV>
    <DIV>
        <DIV class="box1box">
            Here is a box in a <P> by itself.
        </DIV>
    </DIV>
<BR>
    <DIV style="display:block">
        And here are three boxes in a single <P>:
        <DIV CLASS="boxybox">
            This is the first box.
            This is the first box.
            This is the first box.
            This is the first box.
            This is the first box.
        </DIV>
        <DIV CLASS="boxybox">
            This is the second box.
            This is the second box.
            This is the second box.
            This is the second box.
            This is the second box.
        </DIV>
        <DIV CLASS="boxybox">
            This is the third box.
            This is the third box.
            This is the third box.
            This is the third box.
            This is the third box.
        </DIV>
    </DIV>
    <DIV style="clear:left">
        <P>
            Note that when you resize the window, these three boxes reflow
            to fit, much like <IMG>s would.  They can sit side-by-side
            if they fit, because they specify <code>display: inline;</code>
        </P>
        <P>
            This only works in IE.  How should this be done portably?
        </P>
    </DIV>
</BODY>
</HTML>

Ick. That occurred to me a while ago, and I tried in vain for a while to compensate for the boxes trying to float to the left or right (by, for example, enclosing them in a centered DIV that is just big enough to accompany them), but got nowhere. Thanks for the try, though.

Still waiting for some CSS-proponent to come in here and tell me how easy it is to perform such a simple bit of layout. :smiley:

IE6 lets you get away with all sorts of sloppy content structure. I’m brand new to Firefox so I haven’t had a chance to play around with the CSS yet.

Your CSS validated at the W3C validator, but your HTML has problems.

Looking through the Transitional DTD (and if you thought the CSS spec was tough reading don’t even try reading a DTD), valid content for a <p> tag is an entity called %inline; which in turn can consist of ny combination of several things:

#PCDATA (plain text)
%fontstyle; (the elements tt, i, b, u, s, strike, big, small)
%phrase; (the elements em, strong, dfn, code, samp, kbd, var, cite, abbr, acronym)
%special; (the elements a, img, applet, object, font, basefont, br, script, map, q, sub, sup, span, bdo, iframe)
%formctrl; (the elements input, select textarea, label, button) for when the <p> element exists in a form.

Not a <div> tag to be seen. IE6 will let you do whatever you please, it doesn’t even follow the recommended rules for how to properly put together a DTD from entities, I have found. Firefox has a reputation for sticking a little closer to the standards, so it may choke on faulty construction.

Width properties, in fact, do not apply to inline boxes according to the standard, but I’m getting a problem with inline-block display as well.

Viewing the OPs link at this time stamp …

  1. Don’t design your CSS page while using IE. Use a better standards-compliant browser to design the page and build according to standards. Get the look to work according to standards, and then apply known CSS hacks tweaking the code to work in non-standard IE.

  2. Kill the inline CSS for your DIVs and incorporate them into the page CSS. While you can use page CSS and inline CSS, it is better to define additional classes, even if the additional classes differ only slightly.

  3. Look up IE box hack. Part of the problem may very well be you are not following the advice in #1 above. The IE box hack is well known and used to overcome some of the more glaring IE CSS deficiencies.

  4. Review the actual standards. One of the best (and easiest) web sites for CSS is http://www.w3schools.com/ I see you already found out there is no CSS for display: inline-block; You will soon realize that you cannot build a design with a single ID or CLASS. Sometimes you will have to combine several to achieve the desired effect. That’s why it’s called cascading style sheets.

  5. Build your boxes as a single defined class since each box is identical to all the others. Then position the boxes within different DIV classes. While the CSS gurus are great at compacting CSS and emphasizing the cascade designation, while you learn the code don’t be afraid to create redundant code with different named classes and IDs.

  6. I bet if you tweak this code you will arrive at close to what you want, it will work in standards-compliant browsers and the hacks should make in work in crappy IE.

Just remember that if it works only in IE, then that’s not the way to go, no matter how pretty it appears. :smiley:

I understand that designing for IE and hoping other browsers follow along is not the way to go. The way the example page is written is irrelevant. It’s just a way of illustrating the behavior I want, and could have been an MPEG file, for all the difference it would make. Don’t bother looking at the code, or you’re going to get bogged down worrying about minutae like your #2 piece of advice. We are not playing “what’s wrong with this code.”

I’ve tried tweaking every example I can get my hands on (including the one you point out, Duckster), and they all seem to have fundamentally different goals (most seem to involve the elusive three-column layout, which is also bafflingly difficult). This last example nicely positions three boxes side-by-side, but when the window resizes, it either pushes them off the side of the screen (the middle box), or it allows them to overlap the others (the righthand box), neither of which are desireable.

A concise description of what I’m looking for is some kind of box which keeps a fixed size and shape under all circumstances, but is positioned inline. In other words, layout-wise, it behaves like an IMG tag, but instead of having an image in it, it contains HTML.

Oh, that. Just wrap your top-level HTML inside one root <DIV> container, then set the width of that:

<body>
<div style=“width: 800px;”>
All your usual argle bargle stuff here
</div>
</body>

Assuming I’m not drunk out of my gourd, that should keep everything on your page inside an 800-pixel-wide box, which you can lay out as desired.

You are, in fact, drunk out of your gourd. :smiley: I don’t think you caught the gist of my description. The three individual boxes (“this is the first box”, “this is the second box”, “this is the third box”) should behave the way I described, not the entire document. Also, anything which makes assumptions about the window size (e.g. that it’s 800 pixels wide) is to be avoided.

Nice trick, especially since I haven’t touched anything stronger than Diet Pepsi today. :wink:

It’s not for making assumptions about window size, it’s for imposing a window (container) size. Whether or not you wish to do so depends on what layout you want, of course.

OK, now I understand. But your explanation poses two issues:

  1. The ability to offer horizontal inline boxes that become vertical inline boxes when the browser window width changes, in this case, smaller. (Is there standards-compliant code that will do this?)

  2. The need of such code in all circumstances. (Why do you want to do this?)

So why do you want to do this?

Then use percentages instead.

Just to let you know it works fine in Opera.

Another option–this is so ugly I hesitate to mention it–would be to use IFRAMEs as your boxes. These seem to flow like you want (centered, inline, wrapping as necessary) in both Mozilla and IE. Of course, this requires more work to get the content into the IFRAME.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" >
<HTML>
<HEAD>
    <STYLE TYPE="text/css" MEDIA="screen">
        body
        {
            text-align: center;
        }
        .boxybox
        {
            width: 200px; height: 200px;
            border: 5px solid #000099;
            background-color: #eeeeff;
            padding: 10px; margin: 10px;
        }
    </STYLE>
</HEAD>
<SCRIPT>
  function insert() {
    v = [ "top", "first", "second", "third" ];
    for ( i = 0; i < v.length; ++i ) {
      d = document.getElementById(v*).contentWindow.document;
      d.open(); d.writeln("<html><head></head><body bgcolor=#eeeeff>");
      for ( j = 0; j < 12; ++j ) d.writeln( "This is the " + v* + " box." );
      d.writeln("</body></html>"); d.close();
  } }
</SCRIPT>
<BODY ONLOAD="insert()">
    <DIV>
        <H1>Here is a heading</H1>
    </DIV>
    <DIV>
        <IFRAME ID="top" class="boxybox" FRAMEBORDER=0></IFRAME>
    </DIV>
<BR>
    <DIV style="display:block">
        And here are three boxes in a single <<STRIKE>P</STRIKE> DIV>:<BR>
        <IFRAME ID="first"  CLASS="boxybox" FRAMEBORDER=0 SCROLLING="no"></IFRAME>
        <IFRAME ID="second" CLASS="boxybox" FRAMEBORDER=0 SCROLLING="no"></IFRAME>
        <IFRAME ID="third"  CLASS="boxybox" FRAMEBORDER=0 SCROLLING="no"></IFRAME>
    </DIV>
    <DIV>
        <P>
            Note that when you resize the window, these three boxes reflow
            to fit, much like <IMG>s would.  They can sit side-by-side
            if they fit, because they <STRIKE>specify <code>display: inline;</code></STRIKE>
            are inline elements.
        </P>
        <P>
            This <STRIKE>only works in IE</STRIKE> sort of works in both IE and Mozilla.
        </P>
    </DIV>
</BODY>
</HTML>

Told you it was ugly.