How to Style the Easy-to-Style Widgets

A specific styling example

Let's look at a concrete example of how to style an HTML form. We will build a fancy-looking "postcard" contact form.

If you want to follow along with this example, make a local copy of our postcard-start.html file, and follow the below instructions.


The HTML

The HTML is only slightly more involved than the example we used in the first article of this guide; it just has a few extra IDs and a heading.

<form>
  <h1>to: Mozilla</h1>

  <div id="from">
    <label for="name">from:</label>
    <input type="text" id="name" name="user_name" />
  </div>

  <div id="reply">
    <label for="mail">reply:</label>
    <input type="email" id="mail" name="user_email" />
  </div>

  <div id="message">
    <label for="msg">Your message:</label>
    <textarea id="msg" name="user_message"></textarea>
  </div>

  <div class="button">
    <button type="submit">Send your message</button>
  </div>
</form>

Add the above code into the body of your HTML.


Organizing your assets

This is where the fun begins! Before we start coding, we need three additional assets:

  1. The postcard background - download this image and save it in the same directory as your working HTML file.
  2. A typewriter font: The "Mom's Typewriter" font from dafont.com - download the TTF file into the same directory as above.
  3. A hand-drawn font: The "Journal" font from dafont.com - download the TTF file into the same directory as above.

Your fonts need some more processing before you start:

  1. Go to the fontsquirrel.com Webfont Generator.
  2. Using the form, upload both your font files and generate a webfont kit. Download the kit to your computer.
  3. Unzip the provided zip file.
  4. Inside the unzipped contents you will find some font files (at the time of writing, two .woff files and two .woff2 files; they might vary in the future.) Copy these files into a directory called fonts, in the same directory as before. We are using two different files for each font to maximize browser compatibility.

The CSS

Now we can dig into the CSS for the example. Add all the code blocks shown below inside the <style> element, one after another.


Overall layout

First, we prepare by defining our @font-face rules, and all the basic styles set on the <body> and <form> elements. If the fontsquirrel output was different from what we described above, you can find the correct @font-face blocks inside your downloaded webfont kit, in the stylesheet.css file (you'll need to replace the below @font-face blocks with them, and update the paths to the font files):

@font-face {
  font-family: "handwriting";
  src:
    url("fonts/journal-webfont.woff2") format("woff2"),
    url("fonts/journal-webfont.woff") format("woff");
  font-weight: normal;
  font-style: normal;
}

@font-face {
  font-family: "typewriter";
  src:
    url("fonts/momot___-webfont.woff2") format("woff2"),
    url("fonts/momot___-webfont.woff") format("woff");
  font-weight: normal;
  font-style: normal;
}

body {
  font: 1.3rem sans-serif;
  padding: 0.5em;
  margin: 0;
  background: #222;
}

form {
  position: relative;
  width: 740px;
  height: 498px;
  margin: 0 auto;
  padding: 1em;
  box-sizing: border-box;
  background: #fff url(background.jpg);

  /* we create our grid */
  display: grid;
  grid-gap: 20px;
  grid-template-columns: repeat(2, 1fr);
  grid-template-rows: 10em 1em 1em 1em;
}

Notice that we've used some CSS Grid and Flexbox to lay out the form. Using this we can easily position our elements, including the title and all the form elements:

h1 {
  font:
    1em "typewriter",
    monospace;
  align-self: end;
}

#message {
  grid-row: 1 / 5;
}

#from,
#reply {
  display: flex;
}


Labels and controls

Now we can start working on the form elements themselves. First, let's ensure that the <label>s are given the right font:

label {
  font:
    0.8em "typewriter",
    sans-serif;
}

The text fields require some common rules. In other words, we remove their borders and backgrounds, and redefine their padding and margin:

input,
textarea {
  font:
    1.4em/1.5em "handwriting",
    cursive,
    sans-serif;
  border: none;
  padding: 0 10px;
  margin: 0;
  width: 80%;
  background: none;
}

When one of these fields gains focus, we highlight them with a light grey, transparent, background (it is always important to have focus style, for usability and keyboard accessibility):

input:focus,
textarea:focus {
  background: rgba(0, 0, 0, 0.1);
  border-radius: 5px;
}

Now that our text fields are complete, we need to adjust the display of the single and multiple-line text fields to match, since they won't typically look the same using the defaults.


Tweaking the textareas

<textarea> elements default to being rendered as an inline-block element. The two important things here are the resize and overflow properties. While our design is a fixed-size design, and we could use the resize property to prevent users from resizing our multi-line text field, it is best to not prevent users from resizing a textarea if they so choose. The overflow property is used to make the field render more consistently across browsers. Some browsers default to the value auto, while some default to the value scroll. In our case, it's better to be sure everyone will use auto:

textarea {
  display: block;

  padding: 10px;
  margin: 10px 0 0 -10px;
  width: 100%;
  height: 90%;

  border-right: 1px solid;

  /* resize  : none; */
  overflow: auto;
}


Styling the submit button

The <button> element is really convenient to style with CSS; you can do whatever you want, even using pseudo-elements:

button {
  padding: 5px;
  font: bold 0.6em sans-serif;
  border: 2px solid #333;
  border-radius: 5px;
  background: none;
  cursor: pointer;
  transform: rotate(-1.5deg);
}

button:after {
  content: " >>>";
}

button:hover,
button:focus {
  outline: none;
  background: #000;
  color: #fff;
}


The final result

And voilĂ ! Your form should now look like this:

The final result

Note: If your example does not work quite as you expected and you want to check it against our version, you can find it on GitHub - see it running live (also see the source code).