CSS Grid meets the real world – a login form

Once CSS Grid Layout ships in browsers we will be able to use it as an enhancement to existing layout methods long before we can consider using it as our main layout tool. I’m starting to work on some examples that demonstrate this kind of usage – and they also help to explain how some parts of grid will work as they hit the real world.

In this example I have created a login form. The final form looks like the image below.

Form using CSS Grid Layout

You can take a look at the CodePen, depending on the browser you are using and whether you have enabled Grid Layout, you will see one of the three versions.

Step 1: Really old browsers

As we want to make sure this works for all of our users, I start out by building the form with minimal layout. To centre the box I use the time-honoured method of setting auto margins left and right, I’m just setting padding on the body in this case to push the box away from the top of the screen. You could use display: table or similar if you wanted to.

 body {
  padding-top: 20%;
}
h1,
.login,
.account,
.contact{
  width:80%;
  margin: 0 auto;
}

There is some other CSS that will be used in all versions for styling the form fields, adding background and borders and so on. We get something that looks like this.

Basic version of the form

Step 2: Our flexible friends

Flexbox has great browser support and can give us our horizontal and vertical centering. My next step is to check for browsers with flexbox support using a CSS feature query. If the browser supports flexbox I use display:flex on the body – set it to a height of 100 vh units – and then use the alignment properties that are in flexbox to align and justify the box.

@supports (display: flex) {
  body {
    padding:0;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
  }
  h1, .login, .account, .contact {
    margin: 0;
    width: 80%;
  }
}

I need to do some minimal overwriting of the values set for the non-flexbox version. I could go further with this to do more alignment of the internals of the form, but I’m going to pretend that I’m building this at a point where we have widespread grid support (mostly to cut down the amount of code you need to wade through).

Login form with flexbox

Step 3: invoke the grids!

I’ve now got something, with very little work that looks pretty good. However Grid Layout can add some finishing touches here.

One again I am using a feature query to check for grid support. I can then add CSS specifically for those grid supporting browsers.

@supports (display: grid) {
}

Aligning the form

If you create a grid with column and row tracks that do not add up to the size of the grid container, you can use alignment properties to align the tracks within that container.

The align-content property controls the block axis, aligning the grid rows. I set align-content to centre and all the tracks line up at the centre up of the grid.

The justify-content property controls the inline axis, aligning the grid columns. I set justify-content to centre and all the tracks move to the centre of the grid. These properties are part of the Box Alignment Level 3 module, the module that takes all the nice alignment properties that are part of flexbox and makes them available to other CSS layout techniques.

body {
    display: grid;
    align-content: center;
    justify-content: center;
 }

Aligning the content of grid areas

At the bottom of my form is some help text, I’m using the align-self property with a value of end to align the text to the bottom of that row.

.account {
      align-self: end;
}

Nested grids

Inside my form are my form elements, with labels and fields. As these are nested inside the grid and not direct children of the grid container, I need to create a new grid on the div elements that wrap the form fields. If we had subgrid support in any browsers, this would be a good use case for that, but I digress.

My nested grids create a flexible three column grid in each row and also align those items to centre so the labels neatly line up with the fields.

.login > div {
  display: grid;
  grid-template-columns: 1fr 2fr;
   align-items: center;
}
.login > div.actions {
  grid-template-columns: 1fr 1fr 1fr;
}

I could have chosen to use flexbox for this part of the grid, it would be a valid choice. There is a key difference between grid and flexbox however. When we use grid we decide our grid sizing then put things into it, this makes it very easy to align things in both directions. Where flexbox shines is in being able to look at the content, and distribute space according to the size of the content. By adding a width to items that is used by flex-basis we could get this grid like behaviour for these items, in an ideal world it seems more grid-like however, and we do more of the layout on the container rather than needing to add properties to the items.

This decision making process is something we’ll find we can do more and more as we move to layout methods actually designed for the tasks we put them to. It will be nice once we can actually make these decisions for real – using the right layout tool for the job, rather than the one that has the fewest compromises.

Find out more about some of the techniques used here:

– Jen Simmons has written a great article on Feature Queries
– Lots of small example of pieces of grid layout over at Grid by Example
– more about the difference between grid and flexbox

Leave a Reply