Let's build a Random Quote Machine in Elm - Part 1
Tags: elm, beginners, tutorial, webdev
Published: 2019-07-29 11:07:13

---
title: Let's build a Random Quote Machine in Elm - Part 1
published: true
description: 
tags: elm, beginners, tutorial, webdev
cover_image: https://thepracticaldev.s3.amazonaws.com/i/9grt8qdh0f1nky2b1h7r.png
series: Build a Random Quote Machine in Elm
---

In this series I will teach you how to build the [Random Quote Machine](https://github.com/dwayne/elm-random-quote-machine/) web app in Elm.

View the [demo](https://dwayne.github.io/elm-random-quote-machine/) to see what we're trying to achieve.

We'll start from scratch and in 3 short posts we'll cover all the steps needed to complete the app.

Here's what we'll do:

1. We'll structure the app using HTML.
2. We'll style the app using CSS.
3. We'll port the HTML to its equivalent in Elm.
4. We'll refactor the Elm code.
5. We'll make the "New quote" button work.
6. We'll fetch quotations from a remote source.

You'll gain experience working with [randomness](https://guide.elm-lang.org/effects/random.html), [JSON decoders](https://guide.elm-lang.org/effects/json.html), [HTTP](https://guide.elm-lang.org/effects/http.html) and [flags](https://guide.elm-lang.org/interop/flags.html).

Let's get started.

## Structure the app using HTML

Create a new directory named `random-quote-machine` and in it create an
`index.html` file.

```sh
$ mkdir random-quote-machine
$ cd random-quote-machine
$ touch index.html
```

Open `index.html` in your favourite editor and write the following:

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Random Quote Machine</title>

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
  </head>
  <body>
    <!-- Background -->
    <div>
      <!-- Wraps the quotation box and attribution -->
      <div>
        <!-- Quotation box -->
        <div>
          <!-- Quote and author -->
          <blockquote>
            <!-- Quote -->
            <p>
              <span><i class="fa fa-quote-left"></i></span>I am not a product of my circumstances. I am a product of my decisions.
            </p>
            <!-- Author -->
            <footer>
              &mdash; <cite>Stephen Covey</cite>
            </footer>
          </blockquote>

          <!-- Actions -->
          <div>
            <!-- Tweet it -->
            <div>
              <a href="https://twitter.com/intent/tweet?hashtags=quotes&text=%22I%20am%20not%20a%20product%20of%20my%20circumstances.%20I%20am%20a%20product%20of%20my%20decisions.%22%20%E2%80%94%20Stephen%20Covey" target="_blank"><i class="fa fa-twitter"></i></a>
            </div>
            <!-- Post it to Tumblr -->
            <div>
              <a href="https://www.tumblr.com/widgets/share/tool?posttype=quote&tags=quotes&content=I%20am%20not%20a%20product%20of%20my%20circumstances.%20I%20am%20a%20product%20of%20my%20decisions.&caption=Stephen%20Covey&canonicalUrl=https%3A%2F%2Fwww.tumblr.com%2Fdocs%2Fen%2Fshare_button" target="_blank"><i class="fa fa-tumblr"></i></a>
            </div>
            <!-- Get a new random quote -->
            <div>
              <button type="button" autofocus>New quote</button>
            </div>
          </div>
        </div>

        <!-- Attribution -->
        <footer>
          by <a href="https://github.com/dwayne/" target="_blank">dwayne</a>
        </footer>
      </div>
    </div>
  </body>
</html>
```

When you view the HTML in a browser you'll see the following:

![A screenshot of the app after step 1 is completed.](https://thepracticaldev.s3.amazonaws.com/i/d5c9exb57ythoaybco6y.png)

For more details, go [here](https://github.com/dwayne/elm-random-quote-machine/blob/tutorial/tutorial/step-01.md).

## Style the app using CSS

Create a new directory named `assets` and in it create a `styles.css` file.

```sh
$ mkdir assets
$ touch assets/styles.css
```

Open `index.html` and add a link to the stylesheet just after the Font Awesome link.

```html
<link rel="stylesheet" href="assets/styles.css">
```

### Style the body

```css
@import url("https://fonts.googleapis.com/css?family=Raleway:400,500");

/* General */

body {
  margin: 0;
  height: 100vh;

  font-family: Raleway, sans-serif;
  font-weight: 400;
}
```

### Style the background

```html
<!-- Background -->
<div class="background">
  <!-- Wraps the quotation box and attribution -->
  <div>
    <!-- ... -->
  </div>
</div>
```

```css
/* Background */

.background {
  height: 100vh;

  display: flex;
  align-items: center;
  justify-content: center;

  background-color: #333;
}
```

### Style the quotation box

```html
<!-- Quotation box -->
<div class="quote-box">
  <!-- Quote and author -->
  <blockquote class="quote-box__blockquote">
    <!-- Quote -->
    <p class="quote-box__quote-wrapper">
      <span class="quote-left"><i class="fa fa-quote-left"></i></span>...
    </p>
    <!-- Author -->
    <footer class="quote-box__author-wrapper">
      &#8212; <cite class="author">...</cite>
    </footer>
  </blockquote>

  <!-- Actions -->
  <div class="quote-box__actions">
    <!-- Tweet it -->
    <div>
      <a href="..." target="_blank" class="icon-button"><i class="fa fa-twitter"></i></a>
    </div>
    <!-- Post to Tumblr -->
    <div>
      <a href="..." target="_blank" class="icon-button"><i class="fa fa-tumblr"></i></a>
    </div>
    <!-- Get a new quote -->
    <div>
      <button type="button" autofocus class="button">New quote</button>
    </div>
  </div>
</div>
```

```css
/* Quote box */

.quote-box {
  width: 450px;
  padding: 40px 50px;

  border-radius: 3px;

  color: #333;
  background-color: #fff;
}

.quote-box__blockquote {
  margin: 0 0 30px 0;
}

.quote-box__quote-wrapper {
  margin-top: 0;

  text-align: center;
  font-size: 1.8rem;
}

.quote-box__quote-wrapper .quote-left {
  margin-right: 12px;
}

.quote-box__author-wrapper {
  text-align: right;
}

.quote-box__author-wrapper .author {
  font-style: italic;
}

.quote-box__actions {
  display: flex;
}

.quote-box__actions .button {
  height: 30px;

  padding-left: 15px;
  padding-right: 15px;

  border: 0;
  border-radius: 3px;

  cursor: pointer;

  color: #fff;
  background-color: #333;
}

.quote-box__actions .icon-button {
  display: flex;
  align-items: center;
  justify-content: center;

  width: 40px;
  height: 30px;

  border-radius: 3px;

  text-decoration: none;

  color: #fff;
  background-color: #333;
}

.quote-box__actions .button:hover,
.quote-box__actions .icon-button:hover {
  opacity: 0.9;
}

.quote-box__actions > div:first-child {
  margin-right: 10px;
}

.quote-box__actions > div:last-child {
  margin-left: auto;
}
```

### Style the attribution

```html
<!-- Attribution -->
<footer class="attribution">
  by <a href="https://github.com/dwayne/" target="_blank" class="attribution__link">dwayne</a>
</footer>
```

```css
/* Attribution */

.attribution {
  margin-top: 15px;

  text-align: center;
  font-size: 0.8rem;

  color: #fff;
}

.attribution__link {
  text-decoration: none;
  font-weight: 500;

  color: #fff;
}
```

Here's how the app looks now:

![A screenshot of the app after step 2 is completed.](https://thepracticaldev.s3.amazonaws.com/i/6gd3j0xl2krjwf8iwzps.png)

**Tip:** *I've found that the earlier I get the majority of the HTML and CSS stuff out the way the easier it is to figure out how to structure the Elm code and to layer on the features. This isn't Elm specific though. That's how I do it in React and that's how I did it in Angular.*

For more details, go [here](https://github.com/dwayne/elm-random-quote-machine/blob/tutorial/tutorial/step-02.md).

Tomorrow we'll port the HTML to Elm and do a little refactoring to organize the code and make it easier to add features in the later steps.