Is there any easy way to determine what factors are contributing to the size of an HTML element? - html

For example I have a situation where I have something like this (contrived) example:
<div id="outer" style="margin: auto>
<div id="inner1" style="float: left">content</div>
<div id="inner2" style="float: left">content</div>
<div id="inner3" style="float: left">content</div>
<br style="clear: both"/>
</div>
where there are no widths set on any elements, and what I want is #inner1, #inner2 and #inner3 to appear next to each other horizontally inside #outer but what is happening is that #inner1 and #inner2 are appearing next to each other and then #inner3 is wrapping on to the next line.
In the actual page where this is happening there is a lot more going on, but I have inspected all of the elements very carefully with Firebug and do not understand why the #inner3 element is not appearing on the same line as #inner1 and #inner2 and causing #outer to get wider.
So, my question is: Is there any way to determine why the browser is sizing #outer the way it is, or why it is choosing to wrap #inner3 even though there is plenty of room to put it on the previous "line"? Baring specific solutions to this problem, what tips or techniques do you hardcore HTML/CSS/Web UI guys have for a poor back end developer who has found himself working on the front end?

It would be nice to have a tool that could tell you exactly what all your layout problems are, but in this case the browser rendered the page exactly how it should have -- the combined width of the floats exceeded the width of the containing block, so the last one drops to a new line (this is slightly different than the IE6 expanding box/float drop problem which is typically caused by content inside the float, not the floats themselves). So in this case, there was nothing wrong with your page.
Debugging this is simply a matter of walking through your HTML in Firebug and figuring out which children of a block is exceeding the block's width. Firebug provides plenty of information for this purpose, although sometimes I need to use a calculator. I think what you described about being able to see which elements constrain other elements would simply be too complex and overwhelming, especially for elements that are removed from normal flow (such as floats or positioned elements).
Also, a deeper understanding of how CSS layout helps a lot as well. It can get pretty complicated.
For example, it is generally recommended to assign explicit widths to floated elements -- the W3C CSS2 spec states that floats need to have an explicit width, and does not provide instructions of what to do without it. I think most modern browsers use the "shrink to fit" method, and will constrain themselves to the width of the content. However, this is not guaranteed in older browsers, and in something like a 3-column layout, you'll be at the mercy of at the width of content inside the floats.
Also, if you're striving for IE6 compatibility, there are a number of float related bugs that could also cause similar problems.

Try the Web Developer Plugin for Firefox. Specifically, the Information -> Display Block Size and Outline -> Outline Block Level Elements options. This will allow to see the borders of your elements, and their size as Firefox sees them.

In Firebug's CSS tab, you can see what style rules apply to a selected elements in the cascading order. This may or may not help you in your problem.
My guess would be that something about the content of #inner3 is causing it to wrap below the first line, and the #outer is just getting sized to accommodate the smaller needed space.

So I found the answer in my specific case -- there was a div much further up in the DOM that had specific left/right margins set which compressed it and everything in it.
But the heart of the question is really how can you easily debug this sort of issue? What would be perfect in this case for example would be something in Firebug that, when hovering over an element's size in the layout panel would display a tool tip that says something like "width constrained by outer element X; height constrained by style Z on element Q" or "width contributed to by inner elements A, B and C".
I wish I had the time to write something like this, although I suspect it would be difficult (if not impossible) to get that information out of Firefox's rendering engine.

Related

Unwanted space in 2 column layout

I'm trying to design a 2 column layout for getting a feel for HTML again.
I want to avoid using floats because I want to keep the natural document flow. Every other question on Stack Overflow I browsed through incorporate floats or worse tables. I tried layouting it with flex as well but I couldn't figure out how to make both the columns stay the same size on the other pages with different amounts of content in the first column.
Here's what I got so far: http://jsfiddle.net/wykenakw/
I figured out through trial and error that I can use a negative margin to line up the sidebar to the main content but it feels awkward, quirky and hacky. I inspected every element inside my columns but I couldn't find any potential child elements with margins that could cause this 4px gap. It's driving me nuts.
Am I missing something? Am I doing something wrong?
float is ideal because it will essentially cut out the "white space" for you. You can try and use: white-space-collapse:discard on parent elements (in this case #wrapper), but I rarely have success using it.
White space is just a "natural" occurrence created by the browser rendering. In order to avoid this (without using float), you need to simply remove the white space between your elements. This isn't ideal because of the flow and indentation of the elements, but without using float it's what has to be done.
Additionally, in my opinion there is nothing wrong with using float as a "natural document flow". You can always clear the elements.
So instead of:
</main>
<aside id="col_2">
You'd have:
</main><aside id="col_2">
Hope this helps!
http://jsfiddle.net/wykenakw/1/
Change your <main> into a <div> or use css to turn it into a block element:
main {
display: block;
}
As mentioned in the other answer actual spaces between the two elements is causing the unwanted whitespace. However spaces between two block elements is always ignored.

Box sizing: Divs appear to follow different rules from other elements

This question is related to an issue I got recently creating a textarea to fit a containing div. The issue itself has now come to a resolution, though I'm still interested in an answer to this question: How can one get a textarea's sizing (or really, most other elements) to match that of a div? For a decent example, take a look at my JSFiddle.
http://jsfiddle.net/sqW73/1/
The first "pyramid" only defines the width at its outermost. The others shrink their content appropriately based on the amount of padding they've been given.
I understand that the box-sizing: border-box property would be the quickest way to accomplish what I'm looking for: width means the size of the content plus the size of the padding. However, my impression is that border-box is just meant to be a "quick-fix" for pages that were relying upon what people saw as IE6's broken box model. If content-box is supposed to be a reliable default, then what is the expected manner in which people should be sizing things like textboxes? Is there a separate unit type from % that someone could use to essentially give it the div's default state?
I'm a bit pressed for time at the moment, but hopefully what I've given outlines the question in enough detail...?

float:left; vs display:inline; vs display:inline-block; vs display:table-cell;

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.

CSS floats with unknown widths don't wrap whitespace with doctype

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.

Floated block-level element: is it necessary to set the width, if yes, how?

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.