Mini-tutorial on responsive layouts, part 1

Dec 29 2017

This is part one of the mini-tutorial. It covers the box model and introduces the concept of positioning, together with three essential CSS properties: display, float and position. Read part two here.


Effectively using CSS and HTML to build responsive layouts seems to be a painful topic for everybody. Part of the problem is CSS itself. It's not perfect, it has no error messages, it's hard to debug and different browsers interpret it differently. Another part of the problem, the one we do have some control over, is people not understanding the basic principles of CSS. What we see from a lot of the new (and some experienced) developers is they tend to copy and paste styles without getting into details, until the result starts looking okay-ish. This approach is very time consuming, produces a lot of garbage code and breaks as soon as something small has to be changed. Below you will find a compilation of best practices and some general principles that will help you understand CSS and layouts better.

Box model and display property

Theory first.

Any DOM element by default is a rectangular box. It has size dimensions (width and height) and spacing on the sides: padding and margin. The difference between margin and padding is that margin is space outside the box (beetween the box and its neighbours), and padding is space inside the box (between its borders and the content). Sometimes dimensions and spacing of an element can be set explicitly, and sometimes not, depending on the element display type.

There are two essential types of DOM elements that we need to understand: inline and block.

Inline

Examples of inline HTML elements are span, img, input, label. Inline elements:

  • fit into the line without breaking it (hence the term inline)
  • ignore explicitly set padding-top, padding-bottom, width and height properties

Block

Examples of blocks are div, p, table, headers (h1, h2, etc.) Block elements:

  • inherit 100% of their parent width by default
  • break line (take the entire line to themselves even if they can fit into the previous one)

See the entire list of HTML inline and block elements here.

Inline-block

CSS allows to create elements that are inline without the bad side-effects of inline elements (you can set their dimensions and paddings), which is pretty convenient when you're working with graphic elements rather than just text. There are no HTML elements that are inline-blocks by default, but you can create one using the display property.

Display property

In fact, one would argue that inline-block is among the most used display values. The other two are none and flex.

display: none; disables element rendering. display: flex; affects internal behaviour of the box (in relation to its children) rather than external. Flexbox layouts will be discussed later.

Floating elements

Somewhat in parallel with the display property, there exists a whole world of floating elements, or elements with the float property. Depending on the value of the float property (essentially, can be either left or right) the element will "float" to a side of the parent as if it was carried there by a river current, just to be stopped by a dam (parent's border). Several elements floating to the same side will line up - when you need to display multiple block elements in a row, sometimes floating them is the best you can do. Floating two elements in different directions might be useful too.

There are a couple of gotchas:

  • float changes the display value of the element (usually it becomes a block, for more details see this doc)
  • browsers have a hard time identifying where to stop floating elements even when it seems pretty clear to you. The solution is clear property

As an example of the latter, consider this code:

<head>
  <style>
    .float {
      float: left;
      ...
    }
    ...
  </style>
</head>
<body>
  <div class='float'>floating div 1</div>
  <div class='float'>floating div 2</div>
  <div class='float'>floating div 3</div>
  <div>non-floating div</div>
</body>

Since the last div is a block by default, one would expect it to break the line of floats. However, the result will be this:

broken layout

To fix it, let's add clear: both; property to the last div:

good layout

Positioning

Another important and often misunderstood concept is element positioning, or how an element fits into a bigger picture. By default, all elements are positioned following a normal flow defined by the context (it's called static positioning). But sometimes an element has to be moved around a little, and then there are two things to consider:

  1. what's the element's point of reference, or relative to which other element it has to be positioned
  2. to what distance and in which direction the element should be moved

Actually, there's one more thing that one has to consider before everything else: why the element has to be positioned. I feel obliged to include this, because positioning methods other than static are so often abused. If something can be achieved without using position: relative; or position: absolute;, there's no reason to use the position property at all; so, don't.


There are four position strategies (or "methods"), represented by four values of the position property. Read more on them in the MDN docs; here we'll go over the reasons to use each of those.

  • position: fixed; is used if the element should have a permanent place relative to the viewport, and there's a scroll on the document body. If there's no scroll on the body, use position: absolute; instead.
  • position: sticky; also has a very specific usage. Here's an example: 'A common use for sticky positioning is for the headings in an alphabetized list. The "B" heading will appear just below the items that begin with "A" until they are scrolled offscreen. Rather than sliding offscreen with the rest of the content, the "B" heading will then remain fixed to the top of the viewport until all the "B" items have scrolled offscreen, at which point it will be covered up by the "C" heading, and so on' (MDN on position: sticky;).
  • position: absolute; is used for elements that don't fit the natural two-dimensional grid and don't influence their neighbors. Examples of absolutely positioned elements are modal windows, on-hover popups or even tiny things like this:

amazon logo

In this Amazon logo example, "Try Prime" is a link positioned "inside" a div together with the logo picture. It obviously overlaps with the image element, but doesn't affect its position. It's "glued" to the corner of the logo, always relative to the logo div's position. Terminology here is a bit confusing - absolutely positioned elements are always positioned relative to some other element (read more on the containing block below).

  • Using position: relative; is justified in three cases:   * When element placement has to be adjusted relative to its natural position (its normal flow position) - properties left, right, top and bottom can be used together with position: relative; to move the element around without affecting other elements that are positioned statically (note that, as opposed to absolute positioning, the space created for this element by the normal flow will not be collapsed nor filled by other elements).   * When the element has to become a containing block (a "point of reference") for one or more of the absolutely positioned descendants, without changing its own position in the normal flow;   * when a new stacking context has to be created for the element's children (read more on the stacking context in the Z-index paragraph).

You can read on the containing blocks in the MDN docs to understand more about points of reference for elements with different position values. Here we'll focus just on the absolutely positioned elements:

If the position property is absolute, the containing block is formed by the edge of the padding box of the nearest ancestor element that has a position value other than static (fixed, absolute, relative, or sticky).

This is part one of the mini-tutorial. In part two we will continue this discussion on positioning, touching on the subjects of negative margins, z-index, stacking context and flexbox.

Masha K.
Software Developer
Back to Blog