Getting Started With CSS Layout

Getting Started With CSS Layout

Getting Started With CSS Layout

Rachel Andrew

2018-05-25T12:00:19+02:00
2018-05-25T13:49:32+00:00

Over the past couple of years, CSS Layout has dramatically changed as well as the way we develop the front end of our sites. We now have a real choice in terms of the layout methods we use in CSS to develop our sites, which means we often need to make a choice as to which approach to take. In this article, I will run through the various layout methods that you have available to you by explaining the basics of how they are used and what they are used for.

This guide is for you if you are fairly new to CSS and wondering what the best way to approach layout is, but also if you are an experienced developer from elsewhere in the stack who wants to make sure your understanding of layout today is up to date. I have not tried to fully document each layout method here, as that would have created a book and not an article. Instead, I am giving an overview of what is available to you, with plenty of links to find out more.

Normal Flow

If you take an HTML webpage which has no CSS applied to change the layout, the elements will display in normal flow. In normal flow, boxes are displayed one after another based on the Writing Mode of the document. This means that if you have a horizontal writing mode, one in which sentences run left to right or right to left, normal flow will display the boxes of block level elements one after the other vertically down the page.

If you are in a vertical writing mode, then sentences run vertically so normal flow would lay the blocks out horizontally.

Shows how the Block Axis is horizontal in a vertical writing mode and vertical in a horizontal writing mode
Block and Inline Directions change with Writing Mode

Normal flow is where you begin with any layout: when you create a CSS Layout, you are taking the blocks and causing them to do something other than normal flow.

Structure Your Document To Take Advantage Of Normal Flow

You can take advantage of normal flow by ensuring your document starts out in a well-structured manner. Imagine if — instead of this concept of normal flow — the browser piled all your boxes up in the corner on top of each other until you created a layout. That would mean you would have to place every single thing on the page. Instead, the browser displays our content in an immediately readable way.

If your CSS fails to load, the user can still read the content, and users who don’t get CSS at all (e.g. someone using a screen reader) will have the content delivered to them in the order it is in the document. This makes it important from an accessibility point of view that your HTML document starts life in a good order; however, it will also make your life easier as a web developer. If your content is in the order a user would expect to read it, you won’t need to make massive changes to layout to get it into the right place. With newer layout methods you may be surprised how little you have to do.

Therefore, before thinking about layout, think about document structure and the order you would want your content to be read in from the top of the document to the bottom.

Moving Away From Normal Flow

Once we have a well-structured document, we need to decide how to take that and turn it into our desired layout. This will involve moving away from normal flow, for parts of our document. We have a whole set of layout methods to use. The first method we will take a look at is float, as floats are an excellent demonstration of what it is to take an element out of normal flow.

Floats

Floats are used to shift a box to the left or right, allowing content to display wrapped around it.

In order to float an item, use the CSS property float and a value of left or right. The default value of float is none.

.item {
    float: left;
}

It is worth noting that when you float an item and text wraps around it, that what happens is the line boxes of that content are shortened. If you float an item and the following box containing your text has a background color applied, you can see that this background color will then run underneath the floated item.

A block floated left, background color on the text to the right on it runs under the block
The background color on the content runs under the float

As you are shortening the line boxes in order to make space between the float and the wrapping text, you must set a margin on the floated item. A margin on the text would just move the text in from the edge of the container. For an image floated left, you would add a margin to the right and bottom assuming that you want the image flush with the top and left of the container.

See the Pen Smashing Guide to Layout: float by Rachel Andrew (@rachelandrew) on CodePen.

Clearing Floats

Once you have floated an element, all of the following elements will wrap around that floated element until they wrap underneath and normal flow continues. If you want to prevent that, you need to clear the float.

On the element that you want to begin displaying after the float, add the property clear with a value of left to indicate clearing an item floated left, right to clear an item floated right, or both to clear any floats.

.clear {
    clear: both;
}

The above method works if you want an element to start after a float. It won’t help if you find yourself in a situation where you have a floated item inside a box, with some text alongside. If the text is shorter than the floated item, the box will be drawn underneath the content and ignore the float. As we have already learned, floats shorten the line boxes, the rest of the layout continues in normal flow.

The floated box is poking out of the bottom of the container
The box around the text does not clear the float

To prevent this situation we need to clear something inside the box. We could add an empty element and set that to clear all. This involves sticking empty divs into our document which isn’t ideal and may not be possible if your page is generated by a CMS. So instead, the typical clearing floats method is what is known as a clear fix hack. This method works by adding CSS Generated Content, and setting that to clear both.

See the Pen Smashing Guide to Layout: clearfix by Rachel Andrew (@rachelandrew) on CodePen.

The Block Formatting Context

Another way to clear floats inside a box is to invoke a Block Formatting Context (BFC) on the container. A Block Formatting Context contains everything inside it, which would include floated items which can no longer poke out the bottom of the box. There are a few ways to force a BFC, the most common when clearing floats is to set the overflow property to have a value other than the default visible.

.container {
    overflow: auto;
}

Using overflow in this way will generally work, however, in certain situations you could end up with clipped shadows or unwanted scrollbars on the item. It also can look a little confusing in your stylesheet: Did you set overflow because you wanted scrollbars or just to gain this clearing ability?

To make intent clearer and prevent the creation of a BFC causing unwanted side effects, you can use flow-root as a value of the display property. The only thing that display: flow-root does is to create a BFC, thus clearing your floats with no other problems caused.

.container {
    display: flow-root;
}

Legacy Usage Of Floats

Until the arrival of newer layout methods floats were used to create column layouts, this technique worked by giving a set of items a width and setting them to float up next to one another. Careful management of the percentage size of these floated boxes could create a grid effect.

I would not suggest starting a new design now and using this method. However, it will remain in existing sites for many years to come. Therefore, if you come across a design where almost everything seems to be floated, this is the technique in use.

Resources And Further Reading On Floats And Clearing Floats

Positioning

To remove an element from normal flow or shift it around from its place in normal flow, you can use the position property in CSS. When in normal flow, elements have a position of static. The items display one after the other in the Block dimension and if you scroll the page they scroll with it.

When changing the value of position you will typically be also using offset values to move the box around from a particular reference point. The reference point used depends on the value of position you are using.

Relative Positioning

If an item has position: relative then the reference point is the place it would normally be in normal flow. You can then use offset values for the properties top, left, bottom and right to move the box from where it would normally be displayed.

.item {
    position: relative;
    bottom: 50px;
}

Note that other items on the page do not respond to the new position of your element. The place it was positioned in normal flow is reserved, therefore you need to manage any overlaps yourself.

See the Pen Smashing Guide to Layout: relative positioning by Rachel Andrew (@rachelandrew) on CodePen.

Absolute Positioning

Set position: absolute on an item and it will be removed completely from normal flow. The space that was left for it will be removed. The item will then be positioned relative to its containing block which, unless it is nested inside another positioned element, will be the viewport.

Therefore, the first thing that will happen if you set position: absolute on an item is that it typically ends up stuck to the top and left of the viewport. You can then use offset values for the properties top, left, bottom and right to move the box from that position to where you want it to be.

.item {
    position: absolute;
    top: 20px;
    right: 20px;
}

Often you don’t want the box positioned according to the viewport, but in reference to a containing element, it is inside. In which case you need to give that containing element a position value other than the default static.

As setting position: relative does not remove the item from normal flow, this is the usual choice. Give the parent element that you wish to set your offsets from position: relative and then offset the absolutely positioned block from the boundaries of that element.

See the Pen Smashing Guide to Layout: absolute positioning by Rachel Andrew (@rachelandrew) on CodePen.

Fixed Positioning

Something with position: fixed will be positioned in most cases relative to the viewport, and removed from document flow so that no space is reserved for it. When the page is scrolled, the fixed element remains in position relative to the viewport as the rest of the content in normal flow scrolls as usual.

.item {
    position: fixed;
    top: 20px;
    left: 100px;
}

This can be helpful to enable a fixed navigation panel which stays on screen, e.g. while the content scrolls. As with other positioning values, you may cause overlaps when doing this so you should take care that all the content can be read and doesn’t end up behind a fixed item.

See the Pen Smashing Guide to Layout: Fixed positioning by Rachel Andrew (@rachelandrew) on CodePen.

To position a fixed item other than relative to the viewport, you need to have a containing element with one of the transformperspective, or filter properties set to something other than their default value of none. In this case, that element will become the containing block and your offsets with relate to that block rather than the viewport.

Sticky Positioning

Setting position: sticky on an element will cause the element to scroll with the document just as it would in normal flow, however, once it reaches a certain point in relation to the viewport (using the usual offsets) it “sticks” and starts to act like position: fixed. This is a newer value and is less well supported in browsers than other methods, however, it falls back to just scrolling with the page os is a value nicely used as an enhancement without causing problems if it is not supported.

.item {
    position: sticky;
    top: 0;
}

This is how to create the popular effect of a navigation bar scrolling with the content and then stopping at the top of the viewport to stay onscreen as you scroll the content.

See the Pen Smashing Guide to Layout: sticky positioning by Rachel Andrew (@rachelandrew) on CodePen.

Resources And Further Reading On Positioning

Flex Layout

Flexible Box Layout (Flexbox) is a layout method designed for one-dimensional layout. One-dimensional means that you wish to lay out your content in a row, or as a column. To turn your element into a flex layout, you use the display property with a value of flex.

.container {
    display: flex;
}

The direct children of that element become flex items, they will lay out as a row, aligned to the start edge in the inline direction.

See the Pen Smashing Guide to Layout: flex by Rachel Andrew (@rachelandrew) on CodePen.

The Axes Of Flexbox

In the above example, I described out items as being laid out aligned to the start edge of our row in the inline direction, rather than describing them as being aligned to the left. Our items are laid out in a row because the default value of the flex-direction property is row, this creates a row in the inline direction, the direction along which sentences run. As we are working in English, a left-to-right language, the start of a row is on the left and so our items start there. The value of flex-direction thus defines the main axis of Flexbox.

The cross axis, therefore, runs across the main axis at right angles. If your flex-direction is row and your items are displayed in the inline direction, your cross axis runs in the Block direction. If your flex-direction is column so the items are running in the Block direction then your cross axis is along the row.

If you get used to thinking in terms of main and cross axis when working with Flexbox, it will make many things easier.

Direction And Order

Flexbox gives you the ability to change the direction of items on the main axis by using a flex-direction value of row-reverse or column-reverse.

See the Pen Smashing Guide to Layout: flex-direction by Rachel Andrew (@rachelandrew) on CodePen.

You can also change the order of individual flex items with the order property. However, you should take great care when doing so as this can cause a problem for any user who is navigating using the keyboard rather than a mouse or touchscreen as the tab order of the document will follow the order the content is in the source. See the section below on Visual and Document Order for more details.

The Flex Properties

The flex properties are how to control the ratios of flex items along the main axis. The three properties are:

  • flex-grow
  • flex-shrink
  • flex-basis

These are usually used in their shorthand form of the flex property, the first value being flex-grow, the second flex-shrink and the third flex-basis.

.item {
    flex: 1 1 200px;
}

The value of flex-basis gives a size that the item will have before any growing or shrinking takes place. In the above example, that size is 200 pixels, so we would give each item 200 pixels of space. It is unlikely that our container will neatly divide by 200 pixels and so there will be space leftover or not enough space for all of the items if they each have 200 pixels. The flex-grow and flex-shrink properties allow us to control what happens to the items if there is too much or not enough space for them.


Source: Smashing Magazine