JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@1.5.12/dist/vuetify.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vuetify@1.5.12/dist/vuetify.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons">
<div id="app">
<v-app id="inspire">
<v-layout>
<v-flex xs12 sm6 offset-sm3>
<v-container grid-list-sm fluid>
<v-layout row wrap>
<v-flex v-for="n in images" xs4 d-flex>
<v-card flat tile class="d-flex">
<v-img
:src="n.error ? noImageSrc : n.src"
@error="n.error = true"
aspect-ratio="1"
class="grey lighten-2"
>
<template v-slot:placeholder>
<v-layout fill-height align-center justify-center ma-0>
<v-progress-circular
indeterminate
color="grey lighten-5"
></v-progress-circular>
</v-layout>
</template>
</v-img>
</v-card>
</v-flex>
</v-layout>
</v-container>
</v-flex>
</v-layout>
</v-app>
</div>
JavaScript
new Vue({
el: '#app',
data: () => ({
noImageSrc: 'https://via.placeholder.com/300x300',
images: Array.from({ length: 9 }, (n, i) => ({
error: false,
// каждая третья картинка - мусор
src: i % 3
? `https://placehold.co/300x300/${(Math.random() * 0x1000 | 0).toString(16).padStart(3, 0)}/FFF.png`
: 'https://bullshit.com/bullshit.jpg',
})),
}),
});