A 50/50 Layout

2018-10-06 20:55

A layout that I find myself implementing frequently is the following:

+-------+-------+
| TITLE |       |
+-------+  IMG  |
| T     |       |
|  E    |  IMG  |
|   X   |       |
|    T  |  IMG  |
|     ! |       |
+-------+-------+

Nothing special, assuming that TITLE and TEXT! are housed within the same container:

<article>
  <section>
    <h1>TITLE</h1>
    <p>TEXT!</p>
  </section>
  <section>
    IMG
    IMG
    IMG
  </section>
</article>

A tricky issue arises when the layout needs to mutate to the following on mobile:

+-------+
| TITLE |
+-------+
|       |
|  IMG  |
|       |
|  IMG  |
|       |
|  IMG  |
|       |
+-------+
| T     |
|  E    |
|   X   |
|    T  |
|     ! |
+-------+

This mobile layout would be easy to do with flex/grid using order, but that means we can’t wrap TITLE and TEXT! in a container, since elements must be parallel for ordering to work. Ideally then, our HTML looks a bit like:

<article>
  <section>
    <h1>TITLE</h1>
  </section>
  <section>
    <p>TEXT!</p>
  </section>
  <section>
    IMG
    IMG
    IMG
  </section>
</article>

So how do we achieve the desktop layout with the above HTML? I opt for css-columns. The following css will give us the 50/50 layout on desktop, and the correctly ordered layout on mobile:

article {
  display: flex;
}

article > section {
  break-inside: avoid;
}

article > section:nth-child(1) { order: 1 }
article > section:nth-child(2) { order: 3 }
article > section:nth-child(3) { order: 2 }

@media (min-width: 1025px) {
  article {
    display: block;
    columns: 2;
  }
}

Disclaimer: This is a slightly specific solution, it more or less assumes there will always be those 3 children present. But, it works well in those instances.