Creating a Classic Car Rental App with Engine Sound Demo
Published: 2021-03-01 16:25:04

Here is a little experiment using HTML5 audio to create an app mockup for an imaginary classic car rental service.

### Basic markup
```html
<div class="container">
  <div class="app">
    <img src="../codepen/mustang/app.png">
    <div class="wrapper">
      <div class="button-outer">
        <div class="glare"></div>
        <div class="shape-1">
          <div class="shape-2">
            <div class="shape-3">
              <button id="startEngine" class="btn">
                <span class="light"></span>
                <span class="sm">Engine</span>
                <span>Start</span>
                <span>Stop</span>
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
<audio id="engine" src="../codepen/mustang/start.mp3"></audio>
```

### Add styles
```css
  .wrapper {
    text-align: center;
    position: absolute;
    bottom: 50px;
    height: 290px;
    left: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    padding-top: 100px;
    transition: transform 1s;
    transform: translateX(-50%);
  }
  .button-outer {
    background: linear-gradient(135deg, #4c4c4e 0%, #414141 34%, #6a6a6a 55%, #212121 100%);
    width: 290px;
    height: 290px;
    margin-left: 5px;
    margin-top: 5px;
    border-radius: 50%;
    box-shadow: 1px 1px 4px rgba(138, 135, 135, 0.68) inset;
    overflow: hidden;
    position: relative;
    transform: translateZ(3px);
    transform-style: preserve-3d;
  }
  .shape-1 {
    width: 260px;
    height: 260px;
    background-color: #1e1e1e;
    position: absolute;
    top: 15px;
    left: 15px;
    border-radius: 50%;
    box-shadow: 3px 3px 1px 1px #505050 inset, 1px -1px 1px 1px #e6e6e6 inset;
  }
  .shape-2 {
    width: 240px;
    height: 240px;
    border-radius: 50%;
    margin-left: 10px;
    margin-top: 10px;
    background-color: #101010;
    border: 1px solid rgba(94, 94, 94, .7);
    box-shadow: -2px -2px 1px rgba(168, 168, 168, 0.8) inset;
    transform: translateZ(5px);
  }
  .shape-3 {
    width: 230px;
    height: 230px;
    margin-top: 5px;
    margin-left: 5px;
    background-color: #252525;
    border-radius: 50%;
    border: 1px solid #1c1c1c;
    box-sizing: border-box;
    box-shadow: -2px 3px 1px #5f5f5f inset;
  }
  .glare {
    width: 220px;
    height: 250px;
    border-radius: 50%;
    background-color: #fff;
    margin-left: 35px;
    transform: translateY(-50px);
    box-shadow: 0 0 50px 37px #fff;
  }
  .btn {
    -webkit-tap-highlight-color: transparent;
    background: #666;
    border-radius: 50%;
    width: 225px;
    height: 225px;
    margin-left: 2px;
    margin-top: 2px;
    border: 0;
    transition: all 0.1s;
    cursor: pointer;
    box-shadow: 0 0 10px 3px #000 inset, 0 -50px 100px rgba(0, 0, 0, 0.8) inset, 0 30px 60px rgba(0, 0, 0, 0.8) inset;
    box-sizing: border-box;
  }
  .btn:active {
    box-shadow: 0 0 12px 5px #000 inset, 0 -60px 100px rgba(0, 0, 0, 0.8) inset, 0 50px 60px rgba(0, 0, 0, 0.8) inset;
    padding-top: 13px;
    background-position-y: 6px;
  }
  .btn:focus {
    outline: none;
  }
  span {
    font-family: sans-serif;
    text-transform: uppercase;
    font-weight: bold;
    font-size: 30px;
    color: #212121;
    transition: all 0.6s;
    display: block;
  }
  .playing span {
    color: #C5DEA1;
    text-shadow: 0 0 15px #8CA579, 0 0 2px #fff;
  }
  span.sm {
    font-size: 20px;
  }
  .light {
    width: 35px;
    height: 15px;
    margin: 0 auto;
    background-color: #212121;
    margin-bottom: 25px;
    border-radius: 7px;
    border: 1px solid #1b1b1b;
    transition: all 0.6s;
  }
  .playing .light {
    background-color: #f9ea1a;
    border: 1px solid #923C14;
    box-shadow: 0 0 11px 3px #C94A29 inset, 0 0 32px 6px #C77713, 0 0 100px #fff
  }
```

### Bringing it to life
```javascript
let audioElem = document.getElementById("engine");
let startEngine = document.getElementById("startEngine");

startEngine.addEventListener("click", handlePlayButton, false);
playAudio();

async function playAudio() {
  try {
    await audioElem.play();
    startEngine.classList.add("playing");
  } catch(err) {
    startEngine.classList.remove("playing");
  }
}

function handlePlayButton() {
  if (audioElem.paused) {
    playAudio();
  } else {
    audioElem.pause();
    startEngine.classList.remove("playing");
  }
}
```

### Final result
{% codepen https://codepen.io/flexdigital/pen/bGBMbKg %}

### About the author

Simon is a <a href="https://www.flexdigital.uk/">freelance web designer</a>.

#### Credits
Button concept: https://codepen.io/taltmann42
Image credit: https://unsplash.com/photos/BwBxVVdlpYE