This isn’t 1999 any more. I don’t even remember designing with transparent tables (but I DO remember what a discovery for me this technique was). Yeah, positioning with transparent tables. It was even worse than CSS positioning. It was better to give this job to a WYSIWYG tool (but not many where able to do it properly). No wonder why Macromedia Flash took over the world back then. Not Adobe Flash, but Macromedia Flash. Version 3, to be more precise.
That said, I think understanding CSS positioning is useful for any developer these days. Even if is just for avoiding the trial-and-error method of setting positions of HTML elements until I get one that works.
Let’s dive in.
Two key concepts
- Boxes: a block of content with rectangular boundaries. It has a margin, a border, padding and at its core, the content itself.
- Normal flow: boxes in the normal flow belong to a formatting context. This can be block or inline formatting contexts, but not both simultaneously.
Block formatting context. Every object that belongs to this context is stacked on top of each other. They will follow the order of the HTML markup, one after the other. A block has some whitespace above and below it and tolerates no HTML elements next to it, except when ordered otherwise (by adding a float declaration to another element, for instance). It has the following characteristics:
- If no width is set, will expand to fill its parent container.
- Can have margins and padding.
- If no height is set, will expand naturally to fit its child elements (unless they are floated or positioned).
- By default will be placed below previous elements in the markup (unless there are floated or positioned elements surrounding it).
- Ignores the vertical-align property.
Inline formatting context. The element is displayed inside the current block on the same line. I will think of it as a box that acts like text.
- If found between two blocks, the element is called an ‘anonymous block’.
- Will not clear previous content to drop to the next line like block elements.
- Is subject to white-space.
- Will ignore top and bottom margin settings, but will apply left and right margins, and padding in all directions.
- Will ignore the width and height properties.
- If floated left or right, will automatically become a block-level element, subject to all block characteristics.
- Is subject to the vertical-align property.
The display property.
display: block; Places the box in the block formatting context.
display: inline; Places the box in the inline formatting context.
display: none; It takes the box away of the normal flow and hides it, as it didn’t exist.
display: inline-block; The box is placed inline, but behaves as a block. The practical use of this is to have an inline object with a custom width.
display: run-in; According to W3C, If a block box (that does not float and is not absolutely positioned) follows the run-in box, the run-in box becomes the first inline box of the block box. Otherwise, the run-in box becomes a block box. In practical terms, it means that I would make a box a run-in so it behaves as an inline element placed just before it (for example, to make an image the first letter of a text, the typical medieval practice of initials).
display: list-item; The box is displayed as a list-item, with a bullet in front of it. I don’t know why I would use this, honestly.
display: table / display: table-row / display: table-cell; The boxes will mimick the table, tr and td tags.
This is the default position value of an element, should I fail to apply any other value. Boxes can be stacked using this method, one on top of each other, but I won’t be able to position them using any kind of offset properties (top, left, bottom, right).
With relative, objects get placed by default as if they where static. However, they can now be offset. Not only that, but the offset is relative to their static position, and the flow doesn’t get changed. That is, the space they use in the document affecting the surrounding objects remains as if it were static. Also, relative elements create a new coordinate system for their children elements.
Unlike static and relative, anything that is positioned with absolute is independent from the normal flow (it won’t affect or be affected by any other element). Just as relative, it will create a new coordinate system for its children elements. And, I can set all four offsets (left/right and top/bottom), thus removing the need for width/height, as the element will stretch to comply with the four offsets.
This option shares all the rules of an absolutely positioned element, except that the viewport positions the fixed element, as opposed to any parent element. This way, a fixed element does not scroll with the document.
Just inherit the same value as its parent.
It’s worth noting that today, the use of floated elements for layout is getting more and more discouraged with the use of better alternatives, such as inline-block. However, it’s use is widespread, so it’s important to know about its usage.
The definition of the W3C states that “A float is a box that is shifted to the left or right on the current line. The most interesting characteristic of a float (or “floated” or “floating” box) is that content may flow along its side (or be prohibited from doing so by the “clear” property). Content flows down the right side of a left-floated box and down the left side of a right-floated box”. Floated elements are first placed according to the normal flow, then removed from the normal flow and sent to the right or left (depending on which value is applied) of the parent element. Floating objects get placed next to each other, given that there is enough room in the parent element, otherwise they jump to the next line of the normal flow.
As floated elements get removed from the normal flow, every new block added after floated elements acts as if the floated elements were not there. To fix this, clear was created. This property can be set to right, left or both, and it will respectively place the elements below any one with float:left, float:right, or any of these in the case of both. It could also be set to none and inherit, to remove the floating and inherit the parent’s value respectively.
Collapsing and Clearfix
One typical issue when using floats, is that parent elements don’t resize to fit their floated children. That makes sense, as they are removed from the normal flow. The solution to this is usually through a technique called Clearfix hack. A clearfix is a technique for an element to automatically clear after itself, thus preventing collapse.
Of course, this isn’t all there is to CSS positioning. But it summarizes the most important concepts for CSS-positioning survival, at least compared to a slightly more advanced method than randomly testing characters that I used to do in the past.
Some great resources: