I have a page with 6 or more v-card.
Is there a way to fit them like a puzzle? I would like to remove white space between small v-card on first and second line.
Now is like this:
I have a page with 6 or more v-card.
Is there a way to fit them like a puzzle? I would like to remove white space between small v-card on first and second line.
Now is like this:
No way (Yet) to solve this by Vuetify API.
Related Github Feature Req:
[Feature Request] Masonry Layout #4091
Use Javascript plugin. For example masonry.js.
Codepen Demo: https://codepen.io/ezra_siton/pen/gOpZqKr
<!-- https://vuetifyjs.com/en/ -->
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
<div id="app">
<v-app>
<v-content>
<v-container>
<v-row class="masonry">
<v-col class="child" cols="12" sm="6">
<v-card class="pa-2" color="pink darken-1" dark>
<v-card-title>Card 1</v-card-title>
<v-card-text>
The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections form, Rackham. One of three columns
The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections form, Rackham.
</v-card-text>
</v-card>
</v-col>
<!-- card 2-->
<v-col class="child" cols="12" sm="6">
<v-card class="pa-2" color="orange darken-3" dark>
<v-card-title>Card 2</v-card-title>
<v-card-text>
One The standard chunk of Lorem Ipsum used since the 1500s is
</v-card-text>
</v-card>
</v-col>
<!-- card 3 -->
<v-col class="child" cols="12" sm="6">
<v-card class="pa-2" color="#385F73" dark >
<v-card-title>Card 3</v-card-title>
<v-card-text>
The chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections form, Rackham.
</v-card-text>
</v-card>
</v-col>
<!-- card 4 -->
<v-col class="child" cols="12" sm="6">
<v-card class="pa-2" color="blue darken-4" dark >
<v-card-title>Card 4</v-card-title>
<v-card-text>
The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections form, Rackham.
</v-card-text>
</v-card>
</v-col>
</v-row>
</v-container>
</v-content>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
<script src="https://unpkg.com/masonry-layout@4.2.2/dist/masonry.pkgd.min.js"></script>
<script>
new Vue({
el: '#app',
vuetify: new Vuetify(),
mounted: function () {
// Code that will run only after the
// entire view has been rendered
var msnry = new Masonry( '.masonry', {
// options
itemSelector: "[class*='col-']",
});
}
})
</script>
Step 1/3: CDN before body
Link directly to Masonry files on unpkg.
<script src="https://unpkg.com/masonry-layout@4.2.2/dist/masonry.pkgd.min.js"></script>
-or- Install with npm: npm install masonry-layout
and use import import Masonry from 'masonry-layout'
Step 2/3: HTML - Set container element
Masonry works on a container grid element with a group of child items.
Add a class (or id) to your flexbox grid (Set as container element).
masonry in this example (Use any name you want).
<v-row class="masonry">
<v-col class="child" cols="12" sm="6">
<v-card class="pa-2" outlined >
..rest of the code
Step 3/3: Initialize with vanilla js
new Masonry( elem, options )
3.1: Use .masonry as a container element argument.
3.2: Inside options object - set itemSelector to:
itemSelector: "[class*='col-']"
[class*='col-']: Wildcard selector (Select any class Contains col. For example: .col-6 -or- .col-md-2 ==> DRY // Clean solution)
I load the script inside vue mounted() lifecycle hook (After the components added to the DOM).
new Vue({
el: '#app',
vuetify: new Vuetify(),
mounted: function () {
// Code that will run only after the
// entire view has been rendered
var msnry = new Masonry( '.masonry', {
// options
itemSelector: "[class*='col-']",
});
}
})
One more option is to use flexbox/Grid and Custom CSS, in my opinion, this is too much code & ideas for such a simple task. Related article:
https://css-tricks.com/piecing-together-approaches-for-a-css-masonry-layout/
If you are using VueJs and Vuetify then try to use vue.js masonry. With vue-masony, all you need to do is v-row and v-col instead of div.
<v-row v-masonry transition-duration="0.3s" item-selector=".item">
<v-col v-masonry-tile class="item" cols="12" v-for="(content_obj, index) in class_contents" key="`content${index}`" sm="3" >
...
</v-col>
</v-row>
I found a simple solution (in this blog) with anything else than CSS. The same blog gives more examples of different grids and also some examples to make things prettier with JS.
The easiest way is to define a grid of columns the way you want. For example, I want on my proyect a 3 column grid about 400px each.
So we define a class masonry-with-columns, we put all the properties we want (margin, padding, column-gap, row-gap, etc)
.masonry-with-columns {
columns: 3 400px;
column-gap: 10px;
max-width: 100%;
}
Each child must have 2 properties
.masonry-with-columns div {
display: inline-block;
width: 100%;
}
inline-block: prevents objects from being cutwidth: 100%: When you do not put this property, at the time of loading it is displayed with a reduced width and then it expands, to avoid that, we must define a width<template>
<v-container
fill-height
fluid
>
<div class="masonry-with-columns">
<NoticeCard
v-for="(notice, idx) in notices"
:key="idx"
v-bind.sync="notice"
></NoticeCard>
</div>
</v-container>
</template>
import NoticeCard from '@/components/common/Notices/NoticeCard';
export default {
data() {
return {
notices: []
}
},
components:{
NoticeCard
},
methods: {
getNotices() {
axiosRequest.get('/get-cards').then((response) => {
if ( response.status === 200 )
this.notices = response.data[0];
}).catch(e => axiosResponseErrorHandler(this, e));
},
}
}
</script>
<style scoped>
.masonry-with-columns {
columns: 3 400px;
column-gap: 10px;
max-width: 100%;
}
.masonry-with-columns div {
display: inline-block;
width: 100%;
}
</style>
Comments