diff --git a/front/src/components/audio/artist/Card.vue b/front/src/components/audio/artist/Card.vue
index b06cdcd75b126c3d5b7f68abce5923caf0c18a2a..21c62cf34a5ea8063e4e076f9f58f1b5ec31af03 100644
--- a/front/src/components/audio/artist/Card.vue
+++ b/front/src/components/audio/artist/Card.vue
@@ -1,61 +1,38 @@
 <template>
-  <div class="ui card">
-    <div class="content">
-        <div class="header">
-          <router-link class="discrete link" :to="{name: 'library.artists.detail', params: {id: artist.id }}">
-            {{ artist.name }}
-          </router-link>
-        </div>
-        <div class="description">
-          <table class="ui compact very basic fixed single line unstackable table">
-            <tbody>
-              <tr v-for="album in albums">
-                <td>
-                  <img class="ui mini image" v-if="album.cover.original" v-lazy="$store.getters['instance/absoluteUrl'](album.cover.small_square_crop)">
-                  <img class="ui mini image" v-else src="../../../assets/audio/default-cover.png">
-                </td>
-                <td colspan="4">
-                  <router-link :title="album.title" class="discrete link" :to="{name: 'library.albums.detail', params: {id: album.id }}">
-                    <strong>{{ album.title }}</strong>
-                  </router-link><br />
-                  {{ album.tracks_count }} tracks
-                </td>
-                <td>
-                  <play-button class="right floated basic icon" :is-playable="album.is_playable" :discrete="true" :album="album"></play-button>
-                </td>
-              </tr>
-            </tbody>
-          </table>
-          <div class="center aligned segment" v-if="artist.albums.length > initialAlbums">
-            <em v-if="!showAllAlbums" @click="showAllAlbums = true" class="expand">
-              <translate translate-context="Content/Artist/Card.Link" :translate-params="{count: artist.albums.length - initialAlbums}" :translate-n="artist.albums.length - initialAlbums" translate-plural="Show %{ count } more albums">Show 1 more album</translate>
-            </em>
-            <em v-else @click="showAllAlbums = false" class="expand">
-              <translate translate-context="Content/*/Card.Link/Verb">Collapse</translate>
-            </em>
-          </div>
-        </div>
+  <div class="flat inline card">
+    <div :class="['ui', 'image', 'with-overlay', {'default-cover': !cover.original}]" v-lazy:background-image="imageUrl">
+      <play-button class="play-overlay" :icon-only="true" :is-playable="artist.is_playable" :button-classes="['ui', 'circular', 'large', 'orange', 'icon', 'button']" :artist="artist"></play-button>
     </div>
-    <div class="extra content">
-        <span>
-          <i class="sound icon"></i>
-            <translate translate-context="Content/Artist/Card" :translate-params="{count: artist.albums.length}" :translate-n="artist.albums.length" translate-plural="%{ count } albums">1 album</translate>
-        </span>
-        <play-button :is-playable="isPlayable" class="mini basic orange right floated" :artist="artist">
-          <translate translate-context="Content/Queue/Button.Label/Short, Verb">Play all</translate>
-        </play-button>
+    <div class="content">
+      <router-link :title="artist.name" :to="{name: 'library.artists.detail', params: {id: artist.id}}">
+        {{ artist.name|truncate(30) }}
+      </router-link>
+      <div>
+        <i class="small sound icon"></i>
+        <translate translate-context="Content/Artist/Card" :translate-params="{count: artist.albums.length}" :translate-n="artist.albums.length" translate-plural="%{ count } albums">1 album</translate>
       </div>
+      <tags-list label-classes="tiny" :truncate-size="20" :limit="2" :show-more="false" :tags="artist.tags"></tags-list>
+
+      <play-button
+        class="play-button basic icon"
+        :dropdown-only="true"
+        :is-playable="artist.is_playable"
+        :dropdown-icon-classes="['ellipsis', 'vertical', 'large', 'grey']"
+        :artist="artist"></play-button>
     </div>
+  </div>
 </template>
 
 <script>
 import backend from '@/audio/backend'
 import PlayButton from '@/components/audio/PlayButton'
+import TagsList from "@/components/tags/List"
 
 export default {
   props: ['artist'],
   components: {
-    PlayButton
+    PlayButton,
+    TagsList
   },
   data () {
     return {
@@ -65,16 +42,23 @@ export default {
     }
   },
   computed: {
-    albums () {
-      if (this.showAllAlbums) {
-        return this.artist.albums
+
+    imageUrl () {
+      let url = '../../../assets/audio/default-cover.png'
+      let cover = this.cover
+      if (cover.original) {
+        url = this.$store.getters['instance/absoluteUrl'](cover.medium_square_crop)
+      } else {
+        return null
       }
-      return this.artist.albums.slice(0, this.initialAlbums)
+      return url
     },
-    isPlayable () {
-      return this.artist.albums.filter((a) => {
-        return a.is_playable
-      }).length > 0
+    cover () {
+      return this.artist.albums.map((a) => {
+        return a.cover
+      }).filter((c) => {
+        return !!c
+      })[0] || {}
     }
   }
 }
@@ -82,4 +66,27 @@ export default {
 
 <!-- Add "scoped" attribute to limit CSS to this component only -->
 <style scoped>
+.default-cover {
+  background-image: url("../../../assets/audio/default-cover.png") !important;
+}
+
+.play-button {
+  position: absolute;
+  right: 0;
+  bottom: 40%;
+}
+
+.with-overlay {
+  background-size: cover !important;
+  background-position: center !important;
+  height: 8em;
+  width: 8em;
+  display: flex !important;
+  justify-content: center !important;
+  align-items: center !important;
+}
+.flat.card .with-overlay.image {
+  border-radius: 50% !important;
+  margin: 0 auto;
+}
 </style>
diff --git a/front/src/components/audio/artist/Widget.vue b/front/src/components/audio/artist/Widget.vue
index 1b88feae76121b868b103139a6eb3dbb9ddf047c..603b96fbc8dd9f7855bb206760f3f123b9357116 100644
--- a/front/src/components/audio/artist/Widget.vue
+++ b/front/src/components/audio/artist/Widget.vue
@@ -1,6 +1,6 @@
 <template>
   <div class="wrapper">
-    <h3 class="ui header">
+    <h3 v-if="header" class="ui header">
       <slot name="title"></slot>
       <span class="ui tiny circular label">{{ count }}</span>
     </h3>
@@ -12,28 +12,7 @@
       <div v-if="isLoading" class="ui inverted active dimmer">
         <div class="ui loader"></div>
       </div>
-      <div class="flat inline card" v-for="object in objects" :key="object.id">
-        <div :class="['ui', 'image', 'with-overlay', {'default-cover': !getCover(object).original}]" v-lazy:background-image="getImageUrl(object)">
-          <play-button class="play-overlay" :icon-only="true" :is-playable="object.is_playable" :button-classes="['ui', 'circular', 'large', 'orange', 'icon', 'button']" :artist="object"></play-button>
-        </div>
-        <div class="content">
-          <router-link :title="object.name" :to="{name: 'library.artists.detail', params: {id: object.id}}">
-            {{ object.name|truncate(30) }}
-          </router-link>
-          <div>
-            <i class="small sound icon"></i>
-            <translate translate-context="Content/Artist/Card" :translate-params="{count: object.albums.length}" :translate-n="object.albums.length" translate-plural="%{ count } albums">1 album</translate>
-          </div>
-          <tags-list label-classes="tiny" :truncate-size="20" :limit="2" :show-more="false" :tags="object.tags"></tags-list>
-
-          <play-button
-            class="play-button basic icon"
-            :dropdown-only="true"
-            :is-playable="object.is_playable"
-            :dropdown-icon-classes="['ellipsis', 'vertical', 'large', 'grey']"
-            :artist="object"></play-button>
-        </div>
-      </div>
+      <artist-card :artist="artist" v-for="artist in objects" :key="artist.id"></artist-card>
     </div>
     <div v-if="!isLoading && objects.length === 0">No results matching your query.</div>
   </div>
@@ -42,17 +21,16 @@
 <script>
 import _ from '@/lodash'
 import axios from 'axios'
-import PlayButton from '@/components/audio/PlayButton'
-import TagsList from "@/components/tags/List"
+import ArtistCard from "@/components/audio/artist/Card"
 
 export default {
   props: {
     filters: {type: Object, required: true},
     controls: {type: Boolean, default: true},
+    header: {type: Boolean, default: true},
   },
   components: {
-    PlayButton,
-    TagsList
+    ArtistCard,
   },
   data () {
     return {
@@ -96,23 +74,6 @@ export default {
         this.offset = Math.max(this.offset - this.limit, 0)
       }
     },
-    getImageUrl (object) {
-      let url = '../../../assets/audio/default-cover.png'
-      let cover = this.getCover(object)
-      if (cover.original) {
-        url = this.$store.getters['instance/absoluteUrl'](cover.medium_square_crop)
-      } else {
-        return null
-      }
-      return url
-    },
-    getCover (object) {
-      return object.albums.map((a) => {
-        return a.cover
-      }).filter((c) => {
-        return !!c
-      })[0] || {}
-    }
   },
   watch: {
     offset () {
@@ -127,21 +88,12 @@ export default {
 <style scoped lang="scss">
 @import "../../../style/vendor/media";
 
-.default-cover {
-  background-image: url("../../../assets/audio/default-cover.png") !important;
-}
-
 .wrapper {
   width: 100%;
 }
 .ui.cards {
   justify-content: flex-start;
 }
-.play-button {
-  position: absolute;
-  right: 0;
-  bottom: 0;
-}
 
 .ui.three.cards .card {
   width: 100%;
@@ -151,19 +103,6 @@ export default {
     width: 25em;
   }
 }
-.with-overlay {
-  background-size: cover !important;
-  background-position: center !important;
-  height: 8em;
-  width: 8em;
-  display: flex !important;
-  justify-content: center !important;
-  align-items: center !important;
-}
-.flat.card .with-overlay.image {
-  border-radius: 50% !important;
-  margin: 0 auto;
-}
 </style>
 <style>
 .ui.cards .ui.button {
diff --git a/front/src/components/library/Artists.vue b/front/src/components/library/Artists.vue
index f16a6740f8954c7381cf53ef656b18d37e8952c2..c1a13aed9975207d6271a272f57c27ce1688fa54 100644
--- a/front/src/components/library/Artists.vue
+++ b/front/src/components/library/Artists.vue
@@ -35,27 +35,18 @@
             <label><translate translate-context="Content/Search/Dropdown.Label/Noun">Results per page</translate></label>
             <select class="ui dropdown" v-model="paginateBy">
               <option :value="parseInt(12)">12</option>
-              <option :value="parseInt(25)">25</option>
+              <option :value="parseInt(30)">30</option>
               <option :value="parseInt(50)">50</option>
             </select>
           </div>
         </div>
       </div>
       <div class="ui hidden divider"></div>
-      <div
-        v-if="result"
-        v-masonry
-        transition-duration="0"
-        item-selector=".card"
-        percent-position="true"
-        stagger="0">
-        <div v-if="result.results.length > 0" class="ui cards">
-          <artist-card
-            v-masonry-tile
-            v-for="artist in result.results"
-            :key="artist.id"
-            :artist="artist"></artist-card>
+      <div v-if="result && result.results.length > 0" class="ui three cards">
+        <div v-if="isLoading" class="ui inverted active dimmer">
+          <div class="ui loader"></div>
         </div>
+        <artist-card :artist="artist" v-for="artist in result.results" :key="artist.id"></artist-card>
       </div>
       <div class="ui center aligned basic segment">
         <pagination
@@ -108,7 +99,7 @@ export default {
       page: parseInt(this.defaultPage),
       query: this.defaultQuery,
       tags: this.defaultTags.filter((t) => { return t.length > 0 }) || [],
-      paginateBy: parseInt(this.defaultPaginateBy || 12),
+      paginateBy: parseInt(this.defaultPaginateBy || 30),
       orderingDirection: defaultOrdering.direction || "+",
       ordering: defaultOrdering.field,
       orderingOptions: [["creation_date", "creation_date"], ["name", "name"]]
@@ -205,5 +196,22 @@ export default {
 </script>
 
 <!-- Add "scoped" attribute to limit CSS to this component only -->
-<style scoped>
+<style scoped lang="scss">
+@import "../../style/vendor/media";
+
+.wrapper {
+  width: 100%;
+}
+.ui.cards {
+  justify-content: flex-start;
+}
+
+.ui.three.cards .card {
+  width: 100%;
+}
+@include media(">tablet") {
+  .ui.three.cards .card {
+    width: 25em;
+  }
+}
 </style>
diff --git a/front/src/style/themes/_dark.scss b/front/src/style/themes/_dark.scss
index f612914ca87ad3e14876d8026ec95757ffb2e380..fbf3ca99dc69ead2dc3c29444ff6af1a2b1e8f0d 100644
--- a/front/src/style/themes/_dark.scss
+++ b/front/src/style/themes/_dark.scss
@@ -8,40 +8,56 @@ $discrete-text-color: rgba(223, 235, 240, 0.904);
 $border-color: rgb(63, 88, 102);
 $light-shadow-color: rgba(223, 235, 240, 0.15);
 $shadow-color: rgba(63, 102, 97, 0.95);
-$box-shadow: 0px 1px 3px 0px rgba(63, 88, 102, 0.95), 0px 0px 0px 1px rgba(63, 88, 102, 0.98);
+$box-shadow: 0px 1px 3px 0px rgba(63, 88, 102, 0.95),
+  0px 0px 0px 1px rgba(63, 88, 102, 0.98);
 $link-color: rgb(255, 144, 0);
 
 .theme-dark {
   background-color: $background-color;
   .ui.labeled.input {
-    input, .label {
+    input,
+    .label {
       background-color: $input-background-color;
       &::placeholder {
         color: $light-background-color;
-
       }
-
     }
   }
   .ui.statistics .statistic {
-    > .label, > .value {
+    > .label,
+    > .value {
       color: $text-color;
     }
   }
-  .ui.link.list.list .active.item, .ui.link.list.list .active.item a:not(.ui) {
+  .ui.link.list.list .active.item,
+  .ui.link.list.list .active.item a:not(.ui) {
     color: inherit;
   }
-  .ui.form textarea, .ui.form select, .ui.selection.dropdown, .ui.dropdown.selected, .ui.dropdown .menu .selected.item, .ui.form input:not([type]), .ui.form input[type="date"], .ui.form input[type="datetime-local"], .ui.form input[type="email"], .ui.form input[type="number"], .ui.form input[type="password"], .ui.form input[type="search"], .ui.form input[type="tel"], .ui.form input[type="time"], .ui.form input[type="text"], .ui.form input[type="file"], .ui.form input[type="url"] {
+  .ui.form textarea,
+  .ui.form select,
+  .ui.selection.dropdown,
+  .ui.dropdown.selected,
+  .ui.dropdown .menu .selected.item,
+  .ui.form input:not([type]),
+  .ui.form input[type="date"],
+  .ui.form input[type="datetime-local"],
+  .ui.form input[type="email"],
+  .ui.form input[type="number"],
+  .ui.form input[type="password"],
+  .ui.form input[type="search"],
+  .ui.form input[type="tel"],
+  .ui.form input[type="time"],
+  .ui.form input[type="text"],
+  .ui.form input[type="file"],
+  .ui.form input[type="url"] {
     background-color: $input-background-color;
     &::placeholder {
       color: $light-background-color;
-
     }
   }
   .ui.dropdown .menu .item:hover {
     background-color: $light-background-color;
     color: $text-color;
-
   }
   .main.pusher > .ui.secondary.menu {
     background-color: $background-color;
@@ -54,7 +70,9 @@ $link-color: rgb(255, 144, 0);
     }
   }
   .ui.modal {
-    > .header, > .content, > .actions {
+    > .header,
+    > .content,
+    > .actions {
       background-color: $background-color;
     }
     > .header {
@@ -65,29 +83,36 @@ $link-color: rgb(255, 144, 0);
       border-top: 1px solid $border-color;
     }
   }
-  main, .main, footer, .modal {
-
+  main,
+  .main,
+  footer,
+  .modal {
     .ui.menu {
       background-color: $light-background-color;
       .item {
-
         color: $text-color;
       }
     }
-    .ui.secondary.menu .dropdown.item:hover, .ui.secondary.menu .link.item:hover, .ui.secondary.menu a.item:hover {
+    .ui.secondary.menu .dropdown.item:hover,
+    .ui.secondary.menu .link.item:hover,
+    .ui.secondary.menu a.item:hover {
       background: $background-color;
       color: $text-color;
     }
-    .header, .ui.form .field > label, .sub.header {
+    .header,
+    .ui.form .field > label,
+    .sub.header {
       color: $text-color;
     }
     .ui.attached.header {
       background-color: transparent;
     }
-    .ui.toggle.checkbox input:checked ~ .box, .ui.toggle.checkbox input:checked ~ label {
+    .ui.toggle.checkbox input:checked ~ .box,
+    .ui.toggle.checkbox input:checked ~ label {
       color: $text-color !important;
     }
-    .ui.toggle.checkbox .box::before, .ui.toggle.checkbox label::before {
+    .ui.toggle.checkbox .box::before,
+    .ui.toggle.checkbox label::before {
       background-color: $light-background-color;
     }
     a:not(.ui):not(.discrete) {
@@ -96,8 +121,12 @@ $link-color: rgb(255, 144, 0);
     .ui.segment:not(.basic) {
       background-color: $light-background-color;
     }
-    .ui.list, .ui.dropdown {
-      .item, div.item, a.item, .button.item {
+    .ui.list,
+    .ui.dropdown {
+      .item,
+      div.item,
+      a.item,
+      .button.item {
         background-color: $background-color;
         color: $discrete-text-color;
       }
@@ -113,10 +142,13 @@ $link-color: rgb(255, 144, 0);
         color: $discrete-text-color;
       }
     }
-    label, .toggle label {
+    label,
+    .toggle label {
       color: $text-color !important;
     }
-    &, .main.pusher, .ui.vertical.segment {
+    &,
+    .main.pusher,
+    .ui.vertical.segment {
       color: $text-color;
       background-color: $background-color;
     }
@@ -125,21 +157,28 @@ $link-color: rgb(255, 144, 0);
       color: $discrete-text-color;
     }
 
-    .ui.table thead th, .ui.table {
+    .ui.table thead th,
+    .ui.table {
       color: $text-color;
     }
     .ui.divider:not(.vertical):not(.horizontal) {
       border-top: 1px solid $border-color;
       border-bottom: 1px solid $border-color;
     }
-    .ui.cards > .card, .ui.card {
+    .ui.cards > .card,
+    .ui.card {
       color: $text-color;
       background-color: $background-color;
-      box-shadow: $box-shadow;
-      .content, .header, .description {
+      &:not(.flat) {
+        box-shadow: $box-shadow;
+      }
+      .content,
+      .header,
+      .description {
         color: $text-color;
       }
-      .extra, .meta {
+      .extra,
+      .meta {
         color: $discrete-text-color;
       }
     }
@@ -150,31 +189,40 @@ $link-color: rgb(255, 144, 0);
     }
 
     // buttons
-    [class='ui button ui button'], [class='ui button'], [class='ui icon button'], [class='ui fluid button'], [class='ui cancel button'] {
+    [class="ui button ui button"],
+    [class="ui button"],
+    [class="ui icon button"],
+    [class="ui fluid button"],
+    [class="ui cancel button"] {
       background-color: $light-background-color;
       color: $text-color;
       &:hover {
         background-color: $button-hover-color;
-
       }
     }
-    .ui.buttons > .ui.button:not(.basic):not(.inverted), .ui.buttons:not(.basic):not(.inverted) > .button {
+    .ui.buttons > .ui.button:not(.basic):not(.inverted),
+    .ui.buttons:not(.basic):not(.inverted) > .button {
       box-shadow: 0px 0px 0px 1px $light-shadow-color inset;
-
     }
-    .ui.basic.buttons:not(:hover):not(.green):not(.orange):not(.yellow):not(.red) .button, .ui.basic.button {
+    .ui.basic.buttons:not(:hover):not(.green):not(.orange):not(.yellow):not(.red)
+      .button,
+    .ui.basic.button {
       box-shadow: 0px 0px 0px 1px $text-color inset;
       &:not(:hover):not(.green):not(.orange):not(.yellow):not(.red) {
         color: $text-color !important;
       }
     }
-    .ui.basic.buttons .button, .ui.basic.button {
+    .ui.basic.buttons .button,
+    .ui.basic.button {
       &:hover {
         color: $text-color !important;
       }
-
     }
-    .ui.basic.buttons:not(.green):not(.orange):not(.yellow):not(.red) .button:hover, .ui.basic.button:not(.green):not(.orange):not(.yellow):not(.red):hover, .ui.basic.button:not(.green):not(.orange):not(.yellow):not(.red):active, .ui.basic.button:not(.green):not(.orange):not(.yellow):not(.red):focus {
+    .ui.basic.buttons:not(.green):not(.orange):not(.yellow):not(.red)
+      .button:hover,
+    .ui.basic.button:not(.green):not(.orange):not(.yellow):not(.red):hover,
+    .ui.basic.button:not(.green):not(.orange):not(.yellow):not(.red):active,
+    .ui.basic.button:not(.green):not(.orange):not(.yellow):not(.red):focus {
       color: $background-color !important;
     }
     // loading /dimmers
@@ -185,7 +233,8 @@ $link-color: rgb(255, 144, 0);
       background-color: $loading-background-color;
     }
     // table
-    .ui.basic.table tbody tr, .ui.table tr td {
+    .ui.basic.table tbody tr,
+    .ui.table tr td {
       border-bottom: 1px solid $border-color;
     }
     .ui.table thead th {
@@ -193,13 +242,15 @@ $link-color: rgb(255, 144, 0);
     }
     .ui.table {
       &:not(.basic) {
-        &, thead th {
+        &,
+        thead th {
           background-color: $light-background-color;
         }
       }
     }
   }
-  .ui.link.list.list a.item:hover, .ui.link.list.list .item a:not(.ui):not(.button):hover {
+  .ui.link.list.list a.item:hover,
+  .ui.link.list.list .item a:not(.ui):not(.button):hover {
     color: $link-color;
   }
   [data-tooltip]::after {
@@ -208,13 +259,13 @@ $link-color: rgb(255, 144, 0);
   }
   .ui.progress > .label {
     color: $text-color;
-
   }
   i.grey.icon {
     color: $text-color !important;
   }
   input {
-    &::selection, &::-moz-selection {
+    &::selection,
+    &::-moz-selection {
       background: $background-color;
       color: $text-color;
     }