web: experiment with grid

Web page design inspired by a classic Bauhaus poster by Herbert Bayer. The result is a design responsive to both screen width and height.

I’m experimenting with css grids to create interesting page designs. This layout is inspired by a classic graphic design poster from 1926, for an exhibition for Kandinsky’s 60th birthday.

I wanted to recreate the layout and consider the way elements should interact at different screen widths or heights. Check out the html at http://sullivanlehdesigns.com/play-examples/kandinsky-grid.html

Building the grid

The first step is to plan out the grid settings. The image was rotated so the elements are horizontal/vertical to make it easier to build. I decided to build 3 columns, with first and last equal size, and 4 rows.

grid lines on poster
Planning the grid columns and rows

Because css grid uses the same grid-gap for both columns and rows, the columns are do not butt against each in the html version. Negative margins could have been set to make up for it but the additional white space is fine.

showing the grid, again
Final css grid has the same gap measurement between columns and rows.

The middle column is set to a minimum of 5% of the screen width and a maximum of 50%. The text that lines up in that section is dynamically  sized so it isn’t important to be a specific width.

For the rows, it was important the first 2 be the exact same height. Using an fr measurement wasn’t giving me a consistent height but with viewport height they are guaranteed to match.

Because I wanted white space between the edges of the browser window and the page background, there is a wrapper div and a layout div. The layout div has the paper color background and is rotated for screens wider than 600px.

.wrapper {
 margin:0 auto;
 height:100vh;
 text-transform:uppercase;
 letter-spacing:.1em;
 padding:1rem;
 }
.layout {
  background-color:#fcf4e6;
  padding:5vh 5vw;
  }
 @media (min-width:500px){
 .layout {
  display:grid;
  grid-template-columns: 1fr minmax(5%, 50%) 1fr;
  grid-template-rows:8vh 8vh 1fr .5fr 1fr;
  grid-gap:1rem;
  } 
 }
 @media (min-width:600px){
 .wrapper {
  padding:5vh 5vw;
  }
 .layout {
  margin:auto;
  width:70vw;
  transform: rotate(-6deg);
  }
 }

This project is a re-imaging of the design specifically for digital viewing so I was considering how elements relate to each other and the screen size, and how changing the size would effect them. For instance, the photo section has a red bar and an image placed a little bit away from it:

red bar, paper, then photo
the photo is offset from the red bar a little

This effect could be created a lot of ways. For small screens I decided there would not be a gap between the line and the photo. But for large screens, the background of the div is red, and the image a border the same color as the page background. The html is simple:

<div class="bio-image">
 <img src="kandinsky-portrait.jpg" alt="portrait" />
</div>

And the css is, too:

.bio-image {
 grid-column:1/2;
 grid-row:1/span 2;
 }
 .bio-image img {
 border-left:8px solid red;
 height: 100%;
 }
@media (min-width:500px){
 .bio-image {
  background-color:red;
  }
 .bio-image img {
  float:right;
  }
@media (min-width:1200px){
 .bio-image img {
  float:right;
  border-left:8px solid #fcf4e6;
  width: 90%;
  height: 100%;
  object-fit: cover;
  }
}

This way the image and red bar change size dynamically without sacrificing too much of the photo detail.

Elements keep their relationship to the grid most of the time. For the large red number, it could either become a smaller font size on narrow screens to avoid hitting the table. But I like having a large red element on the bottom left for balance, so it simply moves to a different gridline:

large red number stays large
The number moves to the left grid line, so it doesn’t run into the table.

The most frustrating part was that css can’t force justify text to the width of the container. But it seemed a good time to experiment with type based on viewport widths, so both “Kandinsky” and “Jubilaums-Ausstellung” are set that way.

.title {
 font-size: 10vw;
 line-height: 1;
 grid-column: 1/4;
 grid-row: 3/4;
 }
.what {
 background-color: red;
 padding: .5em;
 font-size: 2.8vw;
 line-height: 1.1;
 grid-column: 2/4;
 grid-row: 4/5;
 align-self: start;
 }

Working on an experimental project also means total control of content. Making the h4 white-space: nowrap; ensures that text will always be one line, aligned with the bottom of the photo.

A sprinkle of flexbox

Two sections use flexbox: the top right areas with text and another red bar each.

Basic html:

<div class="company">
  <div class="red-line"></div>
  <div class="content">
    <h3>Anhaltischer Kunstverein</h3>
    <p>Johannisstr. 13</p>
  </div>
</div>

Because css grid only applies to direct children of the element that uses display:grid (it might with an additional setting), I used flexbox to have these divs force their items to line up with the top and bottom of the grid lines.

.company {
 grid-column: 3/4;
 display: flex;
 flex-direction: column;
 justify-content: space-between;
 border-left: 2vw solid #fcf4e6;
}

They didn’t need grid because they only use columns, not both rows and columns; another way of saying 1d vs 2d.

End thoughts

There are things I’d do differently. There should be 4 columns so the top right box doesn’t have awkward border settings. The red bars in the upper right should use hr instead of div. The type and photo could be refined for better fit. But I’m pretty proud at this first attempt at playing with css grids and flexbox.