Vue.js grid / list view example

by Ying Chor Ding

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.27/vue.min.js"></script>
<section id="js-grid-list" class="grid-list" v-cloak>

	<div class="tool-bar">
		<!-- These link buttons use Vue.js to bind click events to change the "layout" variable and bind an active class -->
		<a class="list-icon" v-on:click="layout = 'list'" v-bind:class="{ 'active': layout == 'list'}" title="List"></a>
		<a class="grid-icon" v-on:click="layout = 'grid'" v-bind:class="{ 'active': layout == 'grid'}" title="Grid"></a>
	</div>

	<!-- Vue.js lets us choose which UL to show depending on the "layout" variable -->
	
	<ul v-if="layout === 'grid'" class="grid">
		<!-- A "grid" view with photos only -->
		<li v-for="blog in blog_posts">
			<a v-bind:href="blog.url" v-bind:style="{ backgroundImage: 'url(' + blog.image.large + ')' }" target="_blank"></a>
		</li>
	</ul>

	<ul v-if="layout === 'list'" class="list">
		<!-- A "list" view with small photos and blog titles -->
		<li v-for="blog in blog_posts">
			<a v-bind:href="blog.url" target="_blank">
				<img v-bind:src="blog.image.small">
				<p>{{blog.title}}</p>
			</a>
		</li>
	</ul>

</section>

CSS

[v-cloak] {
		/* Hide un-compiled mustache bindings until the Vue instance is ready */
		display: none;
}

* {
		box-sizing: border-box;
}

a,
a:visited,
a:hover {
	color: #389dc1;
	display: block;
	outline: none;
	text-decoration: none;
}

a:hover {
	text-decoration: none;
}

.grid-list {
	background-color: #fff;
	color: #5e5b64;
	font: 17px/1.3 "Open Sans", sans-serif;
	margin: 0 auto;
	max-width: 1024px;
	min-width: 300px;
	padding: 30px;
	text-align:center;
}

/* The tool bar */
.tool-bar {
	background-color: #ED1C24;
	background-image: url(...

JavaScript

var blog_list = new Vue({
	el: '#js-grid-list',
	data: {
		// The layout mode, possible values are "grid" or "list".
		layout: 'grid',

		// demo data
		blog_posts: [{
			title: 'Tapping into UGC with Offerpop',
			url: 'https://voltagead.com/tapping-ugc-offerpop/',
			image: {
				'large': 'https://2e64oz2sjk733hqp882l9xbo-wpengine.netdna-ssl.com/wp-content/uploads/2016/08/header-960x500-copy-960x500.jpg',
				'small': 'https://2e64oz2sjk733hqp882l9xbo-wpengine.netdna-ssl.com/wp-content/uploads/2016/08/header-960x500-copy-300x300.jpg'
			}
		}, {
			title: '5 websites that get design right',
			url: 'https://voltagead.com/5-websites-get-design-right/',
			image: {
				'large': 'https://2e64oz2sjk733hqp882l9xbo-wpengine.netdna-ssl.com/wp-content/uploads/2016/08/HERO-960x500.jpg',
				'small': 'https://2e64oz2sjk733hqp882l9xbo-wpengine.netdna-ssl.com/wp-content/uploads/2016/08/HERO-300x300.jpg'
			}
		}, {
			title: 'Mariachis, Hats, and Pies, Oh My!',
			url: 'https://voltagead.com/mariachis-hats-pies-oh/',
			image: {
				'large': 'https://2e64oz2sjk733hqp882l9xbo-wpengine.netdna-ssl.com/wp-content/uploads/2016/07/IMG_2629.2-960x582.jpg',
				'small': 'https://2e64oz2sjk733hqp882l9xbo-wpengine.netdna-ssl.com/wp-content/uploads/2016/07/IMG_2629.2-300x300.jpg'
			}
		}, {
			title: 'Big buzz. Big brands. Reebok does omnichannel.',
			url: 'https://voltagead.com/big-buzz-big-brands-reebok-omnichannel/',
			image: {
				'large': 'https://2e64oz2sjk733hqp882l9xbo-wpengine.netdna-ssl.com/wp-content/uploads/2016/07/reebok-hero2.jpg',
				'small': 'https://2e64oz2sjk733hqp882l9xbo-wpengine.netdna-ssl.com/wp-content/uploads/2016/07/reebok-hero2-300x300.jpg'
			}
		}, {
			title: 'Colorado Ad Day',
			url: 'https://voltagead.com/denver-ad-day/',
			image: {
				'large': 'https://2e64oz2sjk733hqp882l9xbo-wpengine.netdna-ssl.com/wp-content/uploads/2016/07/sample-blog-960x577.jpg',
				'small':...