I've created a dummy layout for my latest design, but when I resize the window in ie7 to check that the min-width works, it kicks the content area to below the sidebar, whereas in all other browsers (including ie6) it behaves exactly as it should do.
Demo Link
Can anyone see what the problem is that's causing this random couple extra pixels that kick it off?
Yes, there does seem to be a bug in IE where the min-width elements are getting float-like clearing behaviour.
You can easily avoid it in this case by applying the min-width to the #container instead of both the child elements. (It is in general best to put layout-related min-width fixes on the highest possible parent element.)
(Also, you don't need the float-100%-width rules on the bar/content.)
Related
My Question(s)
Are any of these methods preferred by a professional web designer?
Are any of these methods prefereed by a web browser when drawing the website?
Is this all just personal preference?
Are there other techniques I'm missing?
Note: Above questions are in regards to designing a multi-column layout
float:left;
http://jsfiddle.net/CDe6a/
This is the method I always use when creating column layouts, and it seems to work just fine. The parent does collapse on itself though, so you just need to remember to clear:both; afterwards. Another con that I just found was the inability to align text vertically.
display:inline;
This seems to correct the problem of the collapsing parent, but adds whitespace.
http://jsfiddle.net/CDe6a/1/
Removing whitespace from html seems to be the easiest fix this problem, but is not desired if you are really picky about your html.
http://jsfiddle.net/CDe6a/2/
display:inline-block;
Seems to behave exactly like display:inline;.
http://jsfiddle.net/CDe6a/3/
display:table-cell;
http://jsfiddle.net/CDe6a/4/
Works perfect.
My thoughts:
I'm sure I'm missing a ton of stuff, like certain exceptions that will break the layout but, display:table-cell; seems to work the best, and I think I will start replacing float:left; as I always seem to mess up on clear:both;. I've read many articles and blogs about this on the web, but none of them give me a definite answer on what I should use when laying out my website.
Of the options you asked about:
float:left;
I dislike floats because of the need to have additional markup to clear the float. As far as I'm concerned, the whole float concept was poorly designed in the CSS specs. Nothing we can do about that now though. But the important thing is it does work, and it works in all browsers (even IE6/7), so use it if you like it.
The additional markup for clearing may not be necessary if you use the :after selector to clear the floats, but this isn't an option if you want to support IE6 or IE7.
display:inline;
This shouldn't be used for layout, with the exception of IE6/7, where display:inline; zoom:1 is a fall-back hack for the broken support for inline-block.
display:inline-block;
This is my favourite option. It works well and consistently across all browsers, with a caveat for IE6/7, which support it for some elements. But see above for the hacky solution to work around this.
The other big caveat with inline-block is that because of the inline aspect, the white spaces between elements are treated the same as white spaces between words of text, so you can get gaps appearing between elements. There are work-arounds to this, but none of them are ideal. (the best is simply to not have any spaces between the elements)
display:table-cell;
Another one where you'll have problems with browser compatibility. Older IEs won't work with this at all. But even for other browsers, it's worth noting that table-cell is designed to be used in a context of being inside elements that are styled as table and table-row; using table-cell in isolation is not the intended way to do it, so you may experience different browsers treating it differently.
Other techniques you may have missed? Yes.
Since you say this is for a multi-column layout, there is a CSS Columns feature that you might want to know about. However it isn't the most well supported feature (not supported by IE even in IE9, and a vendor prefix required by all other browsers), so you may not want to use it. But it is another option, and you did ask.
There's also CSS FlexBox feature, which is intended to allow you to have text flowing from box to box. It's an exciting feature that will allow some complex layouts, but this is still very much in development -- see http://html5please.com/#flexbox
I usually use float: left; and add overflow: auto; to solve the collapsing parent problem (as to why this works, overflow: auto will expand the parent instead of adding scrollbars if you do not give it explicit height, overflow: hidden works as well). Most of the vertical alignment needs I had are for one-line of text in menu bars, which can be solved using line-height property. If I really need to vertical align a block element, I'd set an explicit height on the parent and the vertically aligned item, position absolute, top 50%, and negative margin.
The reason I don't use display: table-cell is the way it overflows when you have more items than the site's width can handle. table-cell will force the user to scroll horizontally, while floats will wrap the overflow menu, making it still usable without the need for horizontal scrolling.
The best thing about float: left and overflow: auto is that it works all the way back to IE6 without hacks, probably even further.
I'd say it depends on what you need it for:
If you need it just to get 3 columns layout, I'd suggest to do it with float.
If you need it for menu, you can use inline-block. For the whitespace problem, you can use few tricks as described by Chris Coyier here http://css-tricks.com/fighting-the-space-between-inline-block-elements/.
If you need to make a multiple choice option, which the width needs to spread evenly inside a specified box, then I'd prefer display: table. This will not work correctly in some browsers, so it depends on your browser support.
Lastly, what might be the best method is using flexbox. The spec for this has changed few times, so it's not stable just yet. But once it has been finalized, this will be the best method I reckon.
I prefer inline-block, although float is also useful. Table-cell isn't rendered correctly by old IEs (neither does inline-block, but there's the zoom: 1; *display: inline hack that I use frequently). If you have children that have a smaller height than their parent, floats will bring them to the top, whereas inline-block will screw up sometimes.
Most of the time, the browser will interpret everything correctly, unless, of course, it's IE. You always have to check to make sure that IE doesn't suck-- for example, the table-cell concept.
In all reality, yes, it boils down to personal preference.
One technique you could use to get rid of white space would be to set a font-size of 0 to the parent, then give the font-size back to the children, although that's a hassle, and gross.
For the record only, to add to Spudley's answer, there is also the possibility to use position: absolute and margins if you know the column widths.
For me, the main issue when chossing a method is whether you need the columns to fill the whole height (equal heights), where table-cell is the easiest method (if you don't care much for older browsers).
I prefer inline-block, but float are still useful way to put together HTML elemenets, specially when we have elements which one should stick to the left and one to the right, float working better with writing less lines, while inline-block working well in many other cases.
The new display:inline-block attribute seemed like a useful alternative to doing display:block + float:left/right, but the strange spacing/white-space behavior it introduces seems to negate that convenience.(See here and here) On top of that, browser support is spotty and needs fixes, though that will obviously change.
According to this Yahoo UI uses it heavily, but why? Is there a compelling case for using inline-block?
One useful situation is when you want to have rows of items with variable height. If you were to use floats, then you'd also have to come up with some way to clear all of the second row from the first. Here's an example of that ugly behavior.
But, using the magic of inline-block, here's a version that works. With only two additional CSS rules, it even works in IE6 and 7!
I usually use inline-block for inline elements that I want to be able to give height and width to. This is helpful when using sprites (especially for rounded corner buttons using the sliding door method). I don't use it for everything though and I'm more likely to actually use a float when needed than to break a block level element to using inline-block.
Because floats introduce issues in IE in terms of horizontal floats need an explicit width assigned in order to stay on the same horizontal level. With inline-block ( with fixes ) you can avoid assigning explicit widths to the floated items but maintain the blocky inline behaviour that you desire.
You also don't have to clear the items afterwards but I guess that compensates for the inline-block fixes you need to do.
I've got three columns inside of a div that is the full page width. The two on either side are 25% width and the one in the center is 50% width. This layout is working fine except in IE6 where at certain page widths it bumps the right column to the next line. Is there a fix for this? Maybe an alternate way to layout a page like this?
Edit: I'm using a cross browser inline-block hack that works great in FF, IE, S, Chrome. I'm pretty sure this quirk has to do with the way IE calculates widths on fluid content, and happens due to miscalculation (rounding maybe?). I've put up an example here. Try slowly adjusting the window width in IE6 (maybe later versions too) and watch as the green DIV gets bumped down at certain widths.
Thanks,
Brendan
It's a rounding problem in IE6's box model. Generally, you can't have a combination equal 100%. Try making your values sum to 99% of total width, and it should work fine. This solution has always worked for me.
It sounds like a piece of content in that column might have a defined width which is more than what the 25% of page width it is given. Can you provide CSS examples?
EDIT: IE6 does not support inline-block which could also be the issue.
EDIT 2: I looked at it on a 1680x1050 screen in IE6 in a virtual machine. When I drag the width slowly over time from about 800px to 1600px, it randomly moves the right column around. I suspect it's an issue with the hack that you're trying to use. Your code is so simple that I think you should consider researching an alternate hack instead. I've also never seen the *<property>: <value> hack. What's the * do, all compliant browsers?
Two divs, floated left, of unknown width. One of them has more content than fits the page, so it moves below the first (except in IE):
http://corexii.com/floatproblem/float.html
Add display:inline-table; and the big one wraps its content (consistently across browsers):
http://corexii.com/floatproblem/table.html
But introduce a doctype (not just strict, ANY doctype) and it doesn't anymore in Firefox:
http://corexii.com/floatproblem/doctype.html
How do I get the right div to wrap its content while using a doctype at the same time, reliably across browsers?
How do I get the right div to wrap its
content while using a doctype at the
same time, reliably across browsers?
Without defining widths, you cannot. I'd recommend percentage widths in this case, but it's up to you.
The default width for a div is 100% of its container (in this case the page).
The first div will end up it's actual size unless you size the page to be smaller that its inherent width.
Expecting consistency accross browsers without a full and valid doctype is simply an exercise in futility.
CSS can't quite do everything that table based layouts can. For one, dynamic width layouts are much more complicated. Table-less layouts are still preferable for 98% of cases, but if you really need this kind of dynamic width layout you might have to use a table.
Inconsistent widths, if not carefully proportioned, are not very good from a aesthetic standpoint so you may be fixing the wrong problem.
You could start by including a BODY element.
Traingamer has given you an explanation of Firefox's behavior and what needs to be done to get your desired result. You might listen to him instead of going off on a tangent about CSS being impossible to create layouts with.
Don't blame CSS for problems that you are introducing by not adhering to correct web specifications.
Say I have textboxes, dropdownlists and submit buttons. They are all inline-elements. Which means that "officially" margin, padding, width and height properties should be ignored (in practice not really). If I were to go the right way to set the height to a button I would write something like display:block and then define the height. But there are considerations that a block level element would expand itself unexpectedly so I'd better set its width to some fixed value. The problem is that I don't know its width since it can be dynamically defined upon the text of the button.
Another scenario: I wish to create a menu via <ul> and <li>. I want to have it horizontally aligned, with some items grouped to the left, and with a few stretched to the right. Both <ul> and <li> are block-level elements. Since I wish my menu to take all available horizontal space, then to play with the items height and to have menu items pushed to both sides, the block-mode is fine to me. I'll just use float:left and float:right to achieve the task. But again use should kinda set a width to menu elements, since they are block elements. I do not know their widths because the text of the items can vary. But it seems that everything is rendered just fine as it is.
I have not noticed any issues with both inline elements forced to render as block elements without being floated or width set, or with the list item example. It works just fine in IE7, FF3, Opera 9 and Safari whatever the current version is. The question remains: should I worry about these inline-to-block elements or real block elements floated but without the width set or just leave everything as it is? Am I missing something or is it just one more of those things you simply should not expect to get right?
Say I have textboxes, dropdownlists
and submit buttons. They are all
inline-elements. Which means that
"officially" margin, padding, width
and height properties should be
ignored (in practice not really). If I
were to go the right way to set the
height to a button I would write
something like display:block and then
define the height. But there are
considerations that a block level
element would expand itself
unexpectedly so I'd better set its
width to some fixed value. The problem
is that I don't know its width since
it can be dynamically defined upon the
text of the button.
Unless you're referring to Internet Explorer's box model quirks, you shouldn't be worried about anything expanding or contracting unexpectedly. As long as you take care of normalizing for browser variation, you will be fine. If you have an unexpected and unwanted side-effect along the way to design glory, you debug it, as that is programmer error you contend with. CSS can be quirky, but that is not an appropriate excuse 95% of the time for most major browsers. The other 5% we don't talk about.
This is how I understand your problem:
You want a menu of floated <li> so that you have a horizontal menu that spans the width of the viewport (what your user sees 'in the browser window') to be consistently the full width of the viewport.
It sounds like you are thinking in terms of a fixed width design, when really what sounds like it would suit your purposes is a fluid-width design. This means you create a design that is 'elastic' and expands and contracts relative to the size of the user's browser window. If you created your design anticipating pixel widths being set on each element, you can probably find an elegant way to maintain a fluid-width header and navigation, but have a fixed-width main content area. You can find a happy medium without a full redesign. This walkthrough will likely be what you're looking for. A good explanation of the terms fixed-width and fluid-width can be found here if you're unfamiliar with the jargon and want a closer look at these ideas.
One more for the road:
Setting a width on all floated elements is not only recommended, but is a part of the CSS2 standard as per W3C.
Angelina
You're getting yourself a bit over stressed I think :)
Check out these links, especially 9.4, 9.5 and 10.3. And ctrl-f "inline-block"
If we take the "Official" line that you mention then life is easy as we don't need to worry about widths, heights and on for these elements.
Don't think pixel perfect, don't worry about the minutia of presentation, follow the standards, allow the browser & its users to define styles...
(if only it was really that straight-forward in the "un-Offical" real-world)
Ok, I suppose my question was not understood correctly.
What will happen if i do not set width for floated boxes? I can't set it, I don;t know it. because it depends on the content. Will all boxes just shrink to their content width? This is how it's working in practice. And i'm satisfied with it. Is there any official confirmation that this behaviour should be expected?
Added:
I foudn something interesting here: http://www.webmasterworld.com/css/3811603.htm
I suggest checking the recommendations for a more technical explanantion for the differences, but simply put, the behaviour of floats changed between css2(1998) and css2.1(a couple months of 2005, and then 2007). Per css2 it was mandatory to set a width on floats, while the "shrink-wrapping" you see in ff3 is css2.1. That means pre-Jul/2007 browsers are conforming to the recommendation relevant to their time of manufacture when they stretch div#container the full viewport width. (Which doesn't explain Opera, but it always has done its own thing.)
If so, then i'm contended. As I mentioned, it works in current IE7, FF3, Opera 9 and Safari.
Any more comments?
(assuming if i understand you problem)
In most cases you don't need to set width on list items.
But (yes, there is a but here) if you have a link with display:block (let say you want to use sliding door) you have to do a little trick:
the html:
<ul class="menu">
<li>Link</li>
<li>Link</li>
<li>Link</li>
</ul>
And CSS:
.menu li {
float:left
}
.menu li a {
display:block;
}
/* ===================== */
/* = and the IE6 trick = */
/* ===================== */
* html .menu li a {
width:1%;
white-space:nowrap;
}
If you don't do like this, then the LINK will be stretched to all parent. The LINK not the LIST Element ;) Doing this way you set a "min-width" to IE6 and you won't have any other problems.