Blog

Layout in CSS

Achieving the layout you desire is probably the starting point of any webpage you might be working on While it can seem like an easy task, there are often a lot of different options available when it comes to how to achieve this. I find when looking at how some sites have been coded, there are quite a few common pitfalls made when it comes to basic CSS layout.

Vertical layout

Vertical layout is for all intents and purposes easy. You want a new section, you add a new element, the new element stacks below the old one, the order you place things in in your HTML is the order they will appear in vertically (from top to bottom) on the website.

Horizontal layout

Horizontal layout is a completely different kettle of fish. Strictly speaking there is no pure way of placing a group of elements side by side. Of course there are ways, but none are really perfect, all of them can feel a tad hacky at times. The main methods of I will be going through in this section will be float, inline-block and use of position: relative; and position: absolute. I would like to note at this point that the use of table, would also be able to achieve such horizontal layouts, but it is an outdated method and considered very bad practice.

Floats

float have always been available to use for displaying elements side by side, but this wasn't the intended purpose of float, and so there are some unusual side effects. float was designed to allow newspaper-like layout of text around image. If you floated an image left or right at the start of a block of text, then the text following it would flow around it, staying beside the image until that space was full, and then wrapping beneath it.

To use floats for layout you simply decide which way you want to them to float, left or right, and then each floated element will appear beside the previous one until there is no more space on that line. If you are attempting to create a grid using floats then you will need to be careful about how tall the elements are. If they are the same height, then there shouldn't be any problems. If, however, the elements are different heights then be aware that, without clearing, the first element that doesn't fit on a line will fall back to the highest point it can, which could well be the few px sticking out below from a slightly taller element in the previous row.

The main problem with floated elements is that they don't "have layout". What I mean by this is, although other elements will flow around it, and it will change their positioning, a floated element on it's own won't have a height that it takes up on the page. In a way, it's taken out of the flow of the DOM. If there was an element, with only one child element, and that child element was floated, then the parent element would have a computed height of 0 (assuming it hasn't got another number specified in the CSS).

Clearing Floats

Categorically, all floats need to be cleared. Clearing floats is what gives them layout again, and stops unwanted behavior from other elements flowing around them. Clearing floats can be quite simple, all you need is some kind of element following your last floated element, with the CSS property of clear: both; (left and right are also options, but both is a safer bet). While this is great if there is already an element about to do this, usually that isn't the case, it would be bad practice to add an element to the page just for the purposes of clearing a float, and so a couple of CSS only method have come about.

One is to simply use overflow: hidden; on the parent element, this forces the parent to respect the layout of the floated children. While this is clean and simple, it does have drawbacks, for starters it's limiting, and often it can cause more problems with the layout. I've seen overflow: hidden; applied to the body element before when floats were used for the main layout, and this stopped the user from being able to scroll on the page and see all of the content. It can also cut off visual effect such as box-shadow which rely on flowing outside of the usual space of an element.

Clearfix

There is a newer alternative to the clearing problem, the clearfix. To explain entirely how it works, you'll need a basic understanding of the :before and :after pseudo-elements and how you can use them with CSS-generated content. It uses the after element to place a hidden pseudo-element at the end of the element to which the class is applied. This hidden pseudo-element has the clear:both; CSS applied to is and so does the clearing without any extra elements being added to the page. In a nutshell, adding this class to the parent of elements you've floated will sort out the clearing for you. While this is a basic explanation, the implementation in terms of CSS is changing all the time as people come up with newer better ways to do things, the principal is the same, so just Google it when you need it for a project

Floating pitfalls

When it comes to floating, it can be a bit of a mine-field sometimes, and it's not hard to get things wrong, the whole thing's a bit of a hack from the beginning. But one fundamental I see people messing up again and again is this: Only float siblings, simple as that. For elements to float properly together they need to be direct siblings in the dom, it's no good floating the child of one element next to the child of another element, it's only going to cause problems.

The other thing is what to clear. The answer is always the direct parent. If you float an element, apply your clearfix to it's direct parent. It's doing no good on the one above that, if you inspect element on a webpage, nothing should have a height less than the height of it's children.

Inline-block

Now if all that business with floats seems like too much of a hack (which, while it depends on the situation, I'm of the opinion that it does) there is a newer alternative: display: inline-block. I've explained the basics of how inline-block works previously so I won't go into vast detail here, but what it does is allows multiple elements to display on the same line, have layout, and not break the flow of the page. What it also has is a massive downfall, which unfortunately (and it's after much research that I discover this) is by design.

Due to the nature of the inline display type, from which inline-block takes a lot of it's properties, whitespace before and after the element is counted. This means that if there is a row of inline-block elements, a small space will appear between them if there is any indentation or spacing around them in the markup. This will cause any pixel-perfect layouts using inline-block for a grid or similar to break. These can be tackled used a negative margin between elements, but this really is a hack, and the size of the space will vary with the font-size of the parent element.

HTML5 to the rescue

Forgive me for dropping a buzz-word, but this time I mean it. I think this is possibly my favourite of the new bits that HTML5 has brought. When using a list, under the HTML5 spec, the closing </li> tag can be omitted as the only thing that can be inside a <ul> or <ol> is an <li>. When the browser comes to the next <li> tag it simply adds in the closing <li> from the previous list item. This means that it adds it directly before the element, with no whitespace. This mean that when using an unordered list for, say, a product grind, with the closing tags omitted, the elements can be set, pixel-perfect into nice widths (eg: 25% for 4-across) and nothing will break.

Position relative and absolute

Generally speaking, if you're using position: relative; for layout, then you're doing something wrong. To my mind it should only be used it you just need to nudge something into place, but like the position it currently holds in the DOM; and even then I'd still be looking into using margins (negative one side, positive the other) as a first port of call. For me, position: relative; is only there for use with position: absolute. You make the parent relative (with no offset) so that when you're using position: absolute; top: 0; you can reset the starting point the the bounds of the element you want (usually some sort of wrapping div).

position: absolute; takes an element out of the flow of the DOM, and places it wherever it's offset specifies. The offset is made up of the top, right, bottom and left properties, though often, at least two of these are left as auto. These values are offset against the closest, non-statically positioned parent element. Or to phrase it differently, the closest parent that is position: relative; or also position: absolute. This positioning gives you complete, or absolute, control over where an element is positioned on the page, regardless of the other elements around it, which might be dynamically changed. It can be very useful for things like top nav elements which appear above previous elements in the dom, or for overlays, as these shouldn't disrupt the rest of the page layout

So there it is, all laid out

That's all the important bases covered with regards to layout in CSS. I find that once the basics of knowing what methods are available, and knowing what situation to use each one in, everything seem to just fall into place.