29 July 2009

position:absolute vs. floats and containers

If you, like me, have run into the problem of defining a container for floated or absolutely positioned elements, this summary post might be helpful.

Absolutely positioned elements are positioned relative to a parent element which is a "containing block" a.k.a "offset container" a.k.a "layer". To make an element an offset container, simply use

- position:absolute, or
- position:relative, or
- position:fixed.
- position:static will not result in an offset container!

Coordinates of clicks are also returned according to offset containers. See this page as a source.

With floats one usually runs into the problem that they stick out of their parent elements, that is, the parent element is not stretched as far as the floats go. To solve this problem, the parent element needs to create a new "block formatting context". This happens if

- the parent element is floated
- its overflow is NOT visible (Note: May not work in IE6)
- its display property is a less common variant (table-cell, inline-block, etc.)
- its position is absolute or fixed (relative or static will NOT work)

See this post or Matt Ryall's article for more.

23 July 2009

Border-collapse bug in Firefox

You might be surprised if you try to draw another border around a table if border-collapse:collapse is set on the table itself, as Firefox happens to merge the border of the table with that of the element outside it. Here is a simple markup:

<div style="border:1px solid blue;width:20px;">
<table style="border:1px solid red;border-collapse:collapse">

And the result in FF 3.5 magnified:

The overlap is one pixel only, but it is enough to hide a 1px-wide border. The borders are drawn as expected in other browsers. The solution can be to use border-collapse:separate.

Images in DIVs and a small vertical space

It is trivial, yet I've forgotten. By default, images are inline elements, and are placed on the baseline. If one puts a DIV around it, it will include a small space below the baseline to accommodate letters extending below it. Here is a real-life example:

This cannot be fixed with a vertical-align on the IMG. Either set line-height in the DIV to zero, or the IMG should be rendered as a block element.

6 July 2009

Strange full width bug in Firefox 2

Fiefox (unlike IE6, Opera, Safari and Chrome) behaves strangely when trying to figure out the width of certain embedded elements.

By default, a DIV or a LI, as block elements, should take up 100% of the available horizontal space. However, in a certain combination of elements, Firefox 2 seems to get the size wrong. The simplest case I could find was the following:


border:1px solid red;
min-width:20%; max-width:30%; /* USE width:25%; */
border:1px solid black;
overflow:auto; /* USE visible */
border-bottom: 1px dashed black;


<div id="big">
<div id="small">
<div class="element">text</div>
<div class="element">longer-text</div>
<ul class="element"><li>list</li></ul>

What happens is that the elements classed as "element" will not take up the whole width of div.small. What is even more interesting is that all three of them have the very same width -- the width of the widest among them.

The phenomenon disappears if:

- one uses a normal "width" property on div#small (even if it is a percentage)
- if div#small's "overflow" is "visible" instead of "auto" or "hidden"
- div#small is not floated.

I have not tested this on newer versions of Firefox.

5 July 2009

Float container height (clearing)

It seems to have been a common problem to force containers to be at least as tall as floated elements that are contained in it. Alex Walker wrote an excellent article about some solutions as well as about very simple one.

The simple solution is to give overflow:auto; (or none) to the container. It seems to work in most browsers I have tested. NOTE: This seems to be related to the so-called block formatting contexts, which are explained here by Matt Ryall. The very same technique allows repairing blocks adjacent to floated elements.

I less elegant solution is to insert <br style="clear:all" /> just before the closing tag of the container. This, however, pollutes the markup.

Another solution seems to be to float the container as well.

I hope this post will make it easier to find this excellent article for whomever might need it.