Clothesline Layout & Responsive Design

As of the time of this writing there are some compatibility issues with older browsers and current broswers which support columns differently for which alternative CSS solutions can be produced primarily through media queries or vendor specific prefixes (-moz-, -webkit-).

Responsive clothesline layout at 320 pixels width displays one column.

Responsive clothesline layout at 320 pixels width displays all content in a single column.

With the adoption of CSS3 columns, max-width, min-width and media queries, it turns out clothesline layout is an excellent method for Responsive design and likely to to become a standard necessary skill for web designers to learn.

The goals of the clothesline layout in Responsive design are:

  • Create columns of content which fill the width of a fluid interface.
  • The number of columns vary depending on the width of the available screen space.
  • Content reflows when the number of columns changes.
  • Columns and content have limited fluidity controlled by min-width and max-width to preserve pleasing layout.

Clothesline layouts are intended to accommodate varying screen resolutions by creating swatch-like content containers which can stand alone as self-contained panels of information or cards.

Naturally, cards can be categorized in sections based on type and priority to suit HTML semantic markup, but to create a clothesline requires at least three containers:

Responsive clothesline layout displaying two columns at 480 pixel width.

Responsive clothesline layout displaying two columns at 480 px.

  1. Card container.
    • Set min-width to minimum necessary resolution (mobile first – at the time of this writing the minimum accommodation for Responsive design is 320px). In order to preserve spacing consistently with varying width margin, padding and borders are set on the cards instead of the containing elements.
    • Cards should not be floated elements because of layout issues.
  2. Column container.
    • The column container receives the CSS3 column properties which divides the space into columns and interior spacing (column-gap:).
  3. Section container.
    • Logical division of content which sets receives or inherits  max-width to control the width of the columns section.

Basic Sample Code

Responsive clothesline layout displaying three columns at 800 pixel width.

Responsive clothesline layout displaying three columns at 800px.

Please note the publish date of this page as changes to browsers and browser usage will change over time.

Jump to the bottom of the page for the full code for this example. You can also look at a live example of the basic code.

Body structure

We’ll start with a basic container structure for the body of the document:

<body>
  <div id="wrapper">
    <!-- Header --------------------------------------------------->
    <div id="header">header</div>
    <!-- Content --------------------------------------------------->
    <div id="content">
      <div id="columns">
        <!-- Content cards will go here. -->
      </div>
    </div>
    <!-- Footer --------------------------------------------------->
    <div id="footer">footer</div>
  </div>
</body>

Content Card Example

Any content can be put at the line 8 comment and will flow into the columns top-to-bottom, left-to-right. We’re going to place content cards which look like this:

<div class="card">
  <h4>Card Five</h4>
  <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.
     Proin adipiscing in nisl a ultrices. Nunc suscipit mauris
     sed lorem scelerisque vestibulum. Mauris aliquam leo orci,
     eu congue leo lacinia cursus. Proin convallis laoreet aliquam.</p>
</div>

The CSS

Let’s look at the whole stylesheet then break it down. Lines 1-12 are used only to setup the example page and are not necessary for the clothesline layout however the #wrapper max-width (line 6, highlighted) is essential to limit the fluidity of the overall interface and preserve good layout.

body {
  margin: 0;
}
#wrapper {
  margin: 0 auto;
  max-width: 960px;
}
#header, #content, #footer {
  background-color: #eee;
  min-height: 100px;
  border-bottom: thin solid green;
}

/* Columns -------------------------------------- */
#columns {
  -moz-column-gap: 5px;
  -moz-column-count: 4;
  -webkit-column-count: 4;
  -webkit-column-count: 4;
  column-count: 4;
  column-fill: auto;
  column-gap: 5px;

  padding-top: 5px;
}
@media screen and (min-width: 320px) {
  #columns {
    -moz-column-count: 1;
    -webkit-column-count: 1;
    column-count: 1;
  }
}
@media screen and (min-width: 480px) {
  #columns {
    -moz-column-count: 2;
    -webkit-column-count: 2;
    column-count: 2;
  }
}
@media screen and (min-width: 768px) {
  #columns {
    -moz-column-count: 3;
    -webkit-column-count: 3;
    column-count: 3;
  }
}
@media screen and (min-width: 960px) {
  #columns {
    -moz-column-count: 4;
    -webkit-column-count: 4;
    column-count: 4;
  }
}

/* Cards -------------------------------------- */
.card {
  display: inline-block;
  column-break-inside: avoid;
  -webkit-column-break-inside: avoid;
  -moz-column-break-inside: avoid;

  margin-bottom: 5px;
  padding: .5em;
  border: thin solid #ddd;
  border-radius: 5px;
  box-shadow: 0 0 2px #ccc;
}
.card img {
  width: 100%;
}
Default Columns Styling

The first CSS block for the columns section is the default setting which divides the #columns container into columns with column-count. The method of flowing content within the columns sections is handled with column-fill. The space between columns is handled with column-gap. Additional (unessential) padding-top is added to create some space between the tops of the columns and the top edge of the #columns container.

At the time of this writing Firefox(v23) requires the vendor prefixed -moz-column-gap.

#columns {
  -moz-column-gap: 5px;
  column-count: 4;
  column-fill: auto;
  column-gap: 5px;

  padding-top: 5px;
}
Media Query Overrides

After the default columns style we have a series of media queries which only apply the style contained within them if the media query returns true. It is essential that media queries follow the default style in the code to override the defaults.

Responsive clothesline layout displaying four columns at 960 pixel width.

Responsive clothesline layout displaying four columns at 960px.

Each media query (@media) gets specified information from the browser. In this case the queries are triggered when the media is a “screen” and finds the width of the screen or browser. If the screen or browser meets the specified criteria (min-width) the enclosed CSS is applied.

The first query checks whether the screen or browser width is at least 320px (our minimum width for the user interface). If so, the number of columns is changed from the previously set default (4 columns) to one. Each successive query checks for the next larger width we want to accommodate and will override the previous style if true. So if the screen or browser width is at least 320px the number of columns is set to one, but if the next media query is true (width is at least 480px) the number or columns is then set to two overriding the initial column number setting. If false, the columns number remains at one.

The final media query tests for a min-width of 960px which is the max-width of the #wrapper: 960px is the largest screen width we will accommodate and any screen width larger than that will result in a fixed width interface of 960px centered on the screen based on the #wrapper style previously set.


@media screen and (min-width: 320px) {
  #columns {
    -moz-column-count: 1;
    -webkit-column-count: 1;
    column-count: 1;
  }
}
@media screen and (min-width: 480px) {
  #columns {
    -moz-column-count: 2;
    -webkit-column-count: 2;
    column-count: 2;
  }
}
@media screen and (min-width: 768px) {
  #columns {
    -moz-column-count: 3;
    -webkit-column-count: 3;
    column-count: 3;
  }
}
@media screen and (min-width: 960px) {
  #columns {
    -moz-column-count: 4;
    -webkit-column-count: 4;
    column-count: 4;
  }
}
Content Cards

As previously stated the content within the columns can be any content but in this case we are using blocks of content called cards. Each card is a self-contained block of information common to index pages.

Several problems can arise with columns including the width of column child elements affecting the width of the columns. For this example, and typically, we want the columns in a section to have even widths. We also want to avoid child element content from being split between columns. We are using <div> for the cards which are block-level elements which will take up 100% of the available width but also push a column width so you end up with only one column in all circumstances. We want the cards to take up all available width to keep them fluid, but we want to avoid the columns expanding. To prevent column child elements from being split between columns we use “column-break-inside: avoid;” and “display: inline-block;” on the cards.

The second half of the .card definition is styling and spacing for the appearance of the cards. Last, we will set images appearing inside the cards to 100% so they will adjust larger or smaller to the card width. This makes the images inside the cards Responsive.

.card {
  display: inline-block;
  column-break-inside: avoid;
  -webkit-column-break-inside: avoid;
  -moz-column-break-inside: avoid;

  margin-bottom: 5px;
  padding: .5em;
  border: thin solid #ddd;
  border-radius: 5px;
  box-shadow: 0 0 2px #ccc;
}
.card img {
  width: 100%;
}

Full Code

Copy and paste the code into a single HTML document. To test you can change the width of your browser. The code has not been extensively tested on different devices or a variety of browsers.

<!DOCTYPE html>
<html>
  <head>
    <title>Responsive Clothesline</title>
    <style type="text/css" media="all">
      body {
        margin: 0;
      }
      #wrapper {
        margin: 0 auto;
        max-width: 960px;
      }
      #header, #content, #footer {
        background-color: #eee;
        min-height: 100px;
        border-bottom: thin solid green;
      }

      /* Columns
      --------------------------------------*/
      #columns {
        -moz-column-gap: 5px;
        -moz-column-count: 4;
        -webkit-column-count: 4;
        -webkit-column-count: 4;
        column-count: 4;
        column-fill: auto;
        column-gap: 5px;
        padding-top: 5px;
      }

      @media screen and (min-width: 320px) {
        #columns {
          -moz-column-count: 1;
          -webkit-column-count: 1;
          column-count: 1;
        }
      }
      @media screen and (min-width: 480px) {
        #columns {
          -moz-column-count: 2;
          -webkit-column-count: 2;
          column-count: 2;
        }
      }
      @media screen and (min-width: 768px) {
        #columns {
          -moz-column-count: 3;
          -webkit-column-count: 3;
          column-count: 3;
        }
      }
      @media screen and (min-width: 960px) {
        #columns {
          -moz-column-count: 4;
          -webkit-column-count: 4;
          column-count: 4;
        }
      }

      /* Cards
      --------------------------------------*/
      .card {
        display: inline-block;
        column-break-inside: avoid;
        -webkit-column-break-inside: avoid;
        -moz-column-break-inside: avoid;

        margin-bottom: 5px;
        padding: .5em;
        border: thin solid #ddd;
        border-radius: 5px;
        box-shadow: 0 0 2px #ccc;
       }
       .card img {
         width: 100%;
       }
    </style>
  </head>
  <body>
    <div id="wrapper">
      <!-- Header
      --------------------------------------------------->
      <div id="header">header</div>
      <!-- Content
      --------------------------------------------------->
      <div id="content">
        <div id="columns">
          <div class="card">
            <h4>Card One</h4>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin adipiscing in nisl a ultrices. Nunc suscipit mauris sed lorem scelerisque vestibulum. Mauris aliquam leo orci, eu congue leo lacinia cursus. Proin convallis laoreet aliquam.</p>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin adipiscing in nisl a ultrices. Nunc suscipit mauris sed lorem scelerisque vestibulum. Mauris aliquam leo orci, eu congue leo lacinia cursus. Proin convallis laoreet aliquam.</p>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin adipiscing in nisl a ultrices. Nunc suscipit mauris sed lorem scelerisque vestibulum. Mauris aliquam leo orci, eu congue leo lacinia cursus. Proin convallis laoreet aliquam.</p>
          </div>
          <div class="card">
            <h4>Card Two</h4>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin adipiscing in nisl a ultrices. Nunc suscipit mauris sed lorem scelerisque vestibulum. Mauris aliquam leo orci, eu congue leo lacinia cursus. Proin convallis laoreet aliquam.</p>
          </div>
          <div class="card">
            <h4>Card Three</h4>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin adipiscing in nisl a ultrices. Nunc suscipit mauris sed lorem scelerisque vestibulum. Mauris aliquam leo orci, eu congue leo lacinia cursus. Proin convallis laoreet aliquam.</p>
          </div>
          <div class="card">
            <h4>Card Four</h4>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin adipiscing in nisl a ultrices. Nunc suscipit mauris sed lorem scelerisque vestibulum. Mauris aliquam leo orci, eu congue leo lacinia cursus. Proin convallis laoreet aliquam.</p>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin adipiscing in nisl a ultrices. Nunc suscipit mauris sed lorem scelerisque vestibulum. Mauris aliquam leo orci, eu congue leo lacinia cursus. Proin convallis laoreet aliquam.</p>
          </div>
          <div class="card">
            <h4>Card Five</h4>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin adipiscing in nisl a ultrices. Nunc suscipit mauris sed lorem scelerisque vestibulum. Mauris aliquam leo orci, eu congue leo lacinia cursus. Proin convallis laoreet aliquam.</p>
          </div>
        </div>
      </div>
      <!-- Footer
      --------------------------------------------------->
      <div id="footer">footer</div>
    </div>
  </body>
</html>

One Comment (+add yours?)

  1. Trackback: » Clotheslines in the Responsive Web Soul of a Carp

Leave a Reply

Your email address will not be published. Required fields are marked *