Simple Form

There might not appear to be anything out of the ordinary about this form. But take a closer look, and you’ll see how clean the HTML is—no column wrappers, and not a single div or other semantically meaningless element to be found. Grid affords us this, turning the button and each label and field into its own grid item that we can position as we please. (Because they are direct children of the grid container, which is the form itself.) I thought this was a good candidate for using grid-template-areas , as it simplified defining the grid and arranging its items. You could achieve the same layout by using Grid’s line-based positioning instead.

As an aside, if you ever layout a form with Grid, be aware that Chrome doesn't support <fieldset> as a Grid container.

The Finished Example Layout

The Code

HTML
<form class="form">
  <label for="name" class="label-name">Name</label>
  <input type="text" id="name" name="name" maxlength="40" class="field field-name" />

  <label for="email" class="label-email">Email Address</label>
  <input type="email" id="email" name="email" maxlength="40" class="field field-email" />

  <label for="message" class="label-message">Message</label>
  <textarea id="message" name="message" cols="30" rows="5" maxlength="400" class="field field-message"></textarea>

  <input type="submit" value="Send Message" class="button" />
</form>

CSS
/* Grid
-------------------------------------- */
/* Define the default grid (it's all in one column) */
.form {
  display: grid;
  grid-row-gap: 5px;
}

/* Switch to two columns in wider viewports */
@media (min-width: 29.375rem) {
  .form {
    grid-column-gap: 25px;
    grid-template-areas: 
      "label-name  label-email"
      "field-name  field-email"
      "label-msg   ."
      "field-msg   field-msg"
      "button      .";
  }
}

/* The values below correspond to the values shown in grid-template-areas above, placing the items on the grid accordingly. Note that the grid-area value does NOT have to match the class name. For example, .field-message has field-msg as its grid-area. */
@media (min-width: 29.375rem) {
  .label-name {
    grid-area: label-name;
  }
  .label-email {
    grid-area: label-email;
  }
  .label-message {
    grid-area: label-msg;
  }
  .field-name {
    grid-area: field-name;
  }
  .field-email {
    grid-area: field-email;
  }
  .field-message {
    grid-area: field-msg;
  }
  .button {
    grid-area: button;
  }
}

/* Generic styles for demo purposes
-------------------------------------- */
.form {
  background-color: #eee;
  font-family: Helvetica, Arial, sans-serif;
  max-width: 600px;
  padding: 25px;
}

.field {
  border: 1px solid #ccc;
  font-family: inherit;
  font-size: 1rem;
  padding: 10px;
}

@media (max-width: 29.3125rem) {
  .label-email {
    margin-top: 20px;
  }
}

.label-message {
  margin-top: 20px;
}

.button {
  appearance: none;
  background-color: orange;
  border: none;
  font-size: .9375rem;
  margin-top: 20px;
  padding: 10px;
  /* without this, the button would be as 
  wide as its column (and the Name field) */
  justify-self: start;
}