<div id="app">
  <form id="book-search" @submit.prevent="search">
    <label>
      <span>Search for a book</span>
      
      <input type="text" v-model:trim="searchTerm" placeholder="⌕">
    </label>
    
    <button type="submit">Search</button>
  </form>
  
  <ol class="search-results">
    <li class="search-result" v-for="book in searchResults.items">
      <img :src="'http://books.google.com/books/content?id=' + book.id + '&printsec=frontcover&img=1&zoom=1&source=gbs_api'" class="search-result--thumbnail">
      
      <ul class="search-result--info">
        <li class="search-result--title">{{ book.volumeInfo.title }}</li>
        
        <li v-if="book.volumeInfo.authors" class="search-result--authors">
          by {{ bookAuthors(book) }}
        </li>
        
        <li v-if="book.volumeInfo.publishedDate" class="search-result--published">
          <span>Published </span> {{ book.volumeInfo.publishedDate }}
        </li>
      </ul>
    </li>
  </ol>
  
  <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/106403/allthebooks%5B1%5D.jpg" id="all-the-books" v-if="searchResults.items">
</div>
$smallScreen: 550px;
$largeScreen: 1600px;

@function between($to, $from, $toWidth, $fromWidth) {
  $slope: ($to - $from) / ($toWidth - $fromWidth);
  $base: $from - $slope * $fromWidth;

  @return calc(#{$base} + #{100vw * $slope});
}

@mixin between($property, $to, $from, $toWidth: $smallScreen, $fromWidth: $largeScreen) {
  #{$property}: $to;

  @media (min-width: $toWidth) {
    #{$property}: between($to, $from, $smallScreen, $largeScreen);
  }

  @media (min-width: $fromWidth) {
    #{$property}: $from;
  }
}

:root {
  @include between(font-size, 15px, 24px);
}

*,*:before,*:after { box-sizing: inherit }

html  {
  box-sizing: border-box;
  height: 100%;
  display: flex;
}

body {
  margin: auto;
  background-color: #faf7f6;
  color: #805466;
}

#app {
  padding: 5%;
}

#book-search {
  display: flex;
  align-items: flex-end;
}

label span {
  display: block;
  font-size: .9rem;
  font-weight: bold;
}

input {
  padding: .2rem .5rem;
  border-radius: .25rem;
  border: 2px solid #f3edeb;
  margin-top: .25rem;
  margin-right: .25rem;
  box-shadow: 0 .4rem 1rem -.4rem #d4b1a5;
}

button {
  background: rebeccapurple;
  position: relative;
  color: white;
  border: none;
  padding: 0 .75rem;
  border-radius: .25rem;
  font-size: .6rem;
  line-height: 2.8;
  text-transform: uppercase;
  box-shadow: 0 .4rem 1rem -.4rem purple;
}

.search-results {
  padding-left: 0;
  
  li + li {
    margin-top: .5rem
  }
}

.search-result {
  background-color: white;
  position: relative;
  border: 2px solid #f3edeb;
  border-radius: .25rem;
  overflow: hidden;
  box-shadow: 0 1rem 1rem -.75rem #dfc8c0;
  display: flex;
  align-items: center;
}

.search-result--thumbnail {
  flex: none;
  width: 15%;
  width: 4rem;
  height: auto;
  align-self: flex-start;
}

.search-result--info {
  display: flex;
  height: 100%;
  flex-direction: column;
  justify-content: space-around;
  padding: .5rem;
  list-style: none;
}

.search-result--title {
  font-size: 1rem;
  font-weight: bold;
  color: #65002a;
}

.search-result--authors {
  font-size: .9rem
}

.search-result--published {
  font-size: .8rem;
}

#all-the-books {
  width: 100%;
}
View Compiled
new Vue({
  el: '#app',
  data() {
    return {
      searchTerm: '',
      searchResults: [],
    }
  },
  methods: {
    search() {
      axios.get(`https://www.googleapis.com/books/v1/volumes?q=` + this.searchTerm)
      .then(response => {
        this.searchResults = response.data
      })
      .catch(e => {
        console.log(e)
      })
    },
    
    bookAuthors(book) {
      let authors = book.volumeInfo.authors;
      
      if (authors.length < 3) {
        authors = authors.join(' and ')
      }
      
      else if (authors.length > 2) {
        let lastAuthor = ' and ' + authors.slice(-1);
        
        authors.pop()
        
        authors = authors.join(', ')

        authors += lastAuthor
      }
      
      return authors
    }
  }
});
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.4/vue.js
  2. https://cdnjs.cloudflare.com/ajax/libs/axios/0.17.1/axios.js