I have this very simple chat app here:
It contains of a Header and then v-main. Inside v-main I first have a v-container containing a v-card. This v-card element has the Name as an title, then a v-list containing the messages, and finally, divided by an v-divider a simple v-form. The end of v-app also contains a v-footer.
Treeview:
v-app
v-app-bar
v-main
v-container
v-card
v-card-title
v-divider
v-list
v-divider
v-form
v-footer
Current code inside v-main->v-container:
The v-containersimply has the fluid property on it.
<template>
<v-card>
<!-- Card Title -->
<v-card-title>
{{ messageInfo.sender }}
</v-card-title>
<v-divider></v-divider>
<!-- Messages -->
<v-list
class="overflow-y-auto"
v-for="msg in $store.state.messages"
:key="msg.id"
>
<v-list-item>
<Message :message="msg" :isSender="isSender(msg)" />
</v-list-item>
</v-list>
<v-divider></v-divider>
<!-- Send Messages -->
<v-form v-model="valid" ref="form">
<v-container>
<v-row justify="center">
<v-col :cols="10">
<v-text-field
v-model="messageInfo.message"
:rules="messageRules"
:counter="maximumLength"
required
rounded
flat
background-color="primary"
color="tertiary"
#keydown.enter="validateAndSend"
></v-text-field>
</v-col>
<v-col :cols="1">
<v-btn
:disabled="!valid"
color="tertiary"
#click="validateAndSend"
icon
large
fab
>
<v-icon>mdi-message</v-icon>
</v-btn>
</v-col>
</v-row>
</v-container>
</v-form>
</v-card>
</template>
Question:
Can I maximize the height of the v-list-element, so that my v-form will always end right above the start of the v-footer, regardless of the contents of v-list? I don't have the height of v-list set yet (I think this is the problem, but unsure which height to choose).
I don't want there to be a huge gap between my "content" and the footer.
Also, when there are more messages than in the image, the v-list will simply list them (won't cut off), which then of course pushes down the v-form and the v-footer.
I am very unsure how to do this and couldn't really find anything on google or the vuetify website.
It is not important that the messages are wrapped in a v-list-component. I just need a way to scroll through messages, if necessary.
Additional information:
I am very new to vuetify and I am using nuxt.js (don't think that's important though).
Height of card:
This layout create scroll card for screen height. You need to set property fill-height for v-container.
Then you need to style card by position: absolute
<v-container fluid fill-height>
<v-card class="card">
...
</v-card>
</v-container>
Styles:
.card {
position: absolute !important;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: 14px;
}
Stretching list in card:
Now you need to stretch v-list. I moved v-for from v-list to v-list-item. Then I just added
d-flex and flex-column on v-card. Last step is stretch the list by mt-auto
<template>
<v-card class="card d-flex flex-column">
<!-- Card Title -->
<v-card-title>
{{ messageInfo.sender }}
</v-card-title>
<v-divider></v-divider>
<!-- Messages -->
<v-list class="overflow-y-auto mt-auto">
<v-list-item v-for="msg in messages" :key="msg.id">
<Message :message="msg" :isSender="isSender(msg)" />
</v-list-item>
</v-list>
<v-divider></v-divider>
<!-- Send Messages -->
<v-form ref="form">
<v-container>
<v-row justify="center">
<v-col :cols="10">
<v-text-field
v-model="messageInfo.message"
required
rounded
flat
background-color="primary"
color="tertiary"
/>
</v-col>
<v-col :cols="1">
<v-btn>
<v-icon>mdi-message</v-icon>
</v-btn>
</v-col>
</v-row>
</v-container>
</v-form>
</v-card>
</template>
Scrolling list from bottom to top (pure css):
You also need to reverse scroll for list. You can easily do it by pure css with transform: rotateX(180deg)
Template:
<v-list class="overflow-y-auto mt-auto scroll-container">
<v-list-item class="scroll-container-item" v-for="msg in messages" :key="msg.id">
...
</v-list-item>
</v-list>
Styles:
.scroll-container {
transform: rotateX(180deg);
-webkit-transform: rotateX(180deg); /* Safari and Chrome */
-ms-transform: rotateX(180deg); /* IE 9+ */
-o-transform: rotateX(180deg); /* Opera */
}
.scroll-container-item {
-webkit-transform: rotateX(180deg); /* Safari and Chrome */
-ms-transform: rotateX(180deg); /* IE 9+ */
-o-transform: rotateX(180deg); /* Opera */
}
Related
I am trying to use Vuetify components to achieve an effect on some v-img thumbnails and I am failing to do so. My images are setup as follows:
<v-row class="fill-height pa-5"
align-content="center"
justify="center">
<v-col class="text-subtitle-1 text-center"
cols="12"
sm="3">
<v-card>
<v-img :src="item.docs.doc1"
aspect-ratio=".77"></v-img>
</v-card>
</v-col>
<v-col class="text-subtitle-1 text-center"
cols="12"
sm="3">
<v-card>
<v-img :src="item.docs.doc2"
aspect-ratio=".77"></v-img>
</v-card>
</v-col>
<v-col class="text-subtitle-1 text-center"
cols="12"
sm="3">
<v-card>
<v-img :src="item.docs.doc3"
aspect-ratio=".77"></v-img>
</v-card>
</v-col>
<v-col class="text-subtitle-1 text-center"
cols="12"
sm="3">
<v-card>
<v-img :src="item.docs.doc4"
aspect-ratio=".77"></v-img>
</v-card>
</v-col>
</v-row>
I have these aligned horizontally in a row with columns and I am trying to have it so that when i over over each v-img they dim separately and a white solid v-button will appear in the center which I will assign a link/text too. What is the best way to do this as the hover component seems to lack dimming properties.
I don't think you are going to get this straight out the box but you don't need to do much more to get the result you want.
Out-the-box...
Use the Hover component to trigger an event and use the slot (boolean) value to toggle CSS class(es).
Template
<v-hover v-slot="{ hover }">
<v-card :class="{ 'on-hover': hover }">
// ...
</v-card>
</v-hover>
Custom...
Then add some scoped styles. The following is just a quick example but you can style however you like.
Styles
.v-image {
transition: filter .4s ease-in-out;
}
.v-card:hover .v-image {
filter: brightness(25%);
}
Example: https://codepen.io/alexpetergill/pen/NWBadjV
Docs: https://vuetifyjs.com/en/components/hover/
API: https://vuetifyjs.com/en/api/v-hover/#slots
I have a header, sub-header, icon and button on my v-card. My goal is to place my create button the right, but I can't seem to do that.
<template>
<v-row class="pl-5">
<v-card class="pl-5" elevation="0">
<v-card-title>
<v-icon left x-large color="primary">{{ icon }}</v-icon>
<span class="font-weight-bold">{{ title }}</span>
</v-card-title>
<v-card-subtitle> Subheader </v-card-subtitle>
<v-spacer></v-spacer>
<router-link v-if="type == 'index'" :to="`/${name.toLowerCase().replace(' ', '-')}/create`">
<v-btn outlined class="blue--text mt-5 mr-8">
<span>Create</span>
</v-btn>
</router-link>
</v-card>
</v-row>
</template>
<script>
export default {
props: {
icon: String,
name: String,
title: String,
subtitle: String,
type: String
},
components: {}
}
</script>
<style scoped></style>
If I move my <router-link> in <v-card-subtitle>
I get this
If I move my <router-link> in <v-card-title>
I get this
Can someone give me a push here ?
Fiddle
https://jsfiddle.net/bheng/h2u870dv/
If I do this:
<v-row class="pl-5">
<v-card-title>
<span class="material-icons">
favorite_border
</span>
<p class="font-weight-bold">TITLE</p>
<p class="caption">ST</p>
</v-card-title>
<v-spacer></v-spacer>
<v-btn>Create</v-btn>
</v-row>
I get
Button seems to locate at the place I wanted it to be, but the title and subtitle misalign very badly. I'm stuck now.
You can add div or v-col in v-row and use css to align items the way you want:
new Vue({
el: '#app',
vuetify: new Vuetify(),
data() {
return {
icon: 'favorite_border',
name: 'link',
title: 'TITLE',
subtitle: 'https://fonts.google.com/icons?selected=Material+Icons',
type: 'index'
}
}
})
.myclass {
width: 100%;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: flex-start;
}
<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#6.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Material+Icons" rel="stylesheet">
<div id="app">
<v-app>
<v-main>
<v-container>
<v-row class="pl-5">
<div class="myclass">
<v-card class="pl-5 mycard" elevation="0">
<v-card-title>
<v-icon left x-large color="primary">{{ icon }}</v-icon>
<span class="font-weight-bold">{{ title }}</span>
</v-card-title>
<v-card-subtitle> Subheader </v-card-subtitle>
<v-spacer></v-spacer>
</v-card>
<a v-if="type == 'index'" :href="`/${name.toLowerCase().replace(' ', '-')}/create`">
<v-btn outlined class="blue--text mt-5 mr-8">
<span>Create</span>
</v-btn>
</a>
</div>
</v-row>
</v-container>
</v-main>
</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>
Your problem is that you're placing your button inside the v-card you declared to set the style of the title. And this card is just a square box since you haven't specified any width. If you set the elevation="1" you can see this clearly.
Just place your button outside the v-card and the v-spacer will work. Alternatively, you could also set the v-card width to 100%. Btw, you can also use the to prop in your v-btn, so there's no need to have a v-router-link.
Check this codesandbox I made: https://codesandbox.io/s/stack-71444864-v-spacer-example-0tx24n?file=/src/components/Example.vue
<v-row class="pl-5">
<v-card class="pl-5" elevation="0">
<v-card-title>
<v-icon left x-large color="primary"> mdi-home </v-icon>
<span class="font-weight-bold">Testing</span>
</v-card-title>
<v-card-subtitle class="pb-0"> Subheader </v-card-subtitle>
</v-card>
<v-spacer></v-spacer>
<v-btn to="/about" outlined class="blue--text mt-5 mr-8">
<span>Create</span>
</v-btn>
</v-row>
Update: v-cols and custom CSS with breakpoints conditionals
I saw you were interested to learn how to make this design using vuetify's grid. The advantage to use v-cols and breakpoint conditionals is that you'll have more control of your design over different viewports. Like on a mobile view. This is how I'd do it.
I start by splitting the grid in 2 columns, one for the title and one for the button, in cols view (previously known as xs (extra small)) I set the size of them to 12 columns and on sm (small) and up I set the size to 6 columns each. This way they are shown half and half.
The title column has no changes, on the buttom column I use the classes d-flex justify-end to move the button all to the right and align-center to center the button vertically at the middle of the v-row.
Then I use the breakpoint conditionals to activate the block property of the button and to apply paddings to the whole v-row, depending on the current viewport.
<v-row :class="$vuetify.breakpoint.smAndUp ? 'px-4' : ''">
<v-col cols="12" sm="6">
<v-card elevation="0">
<v-card-title>
<v-icon left x-large color="primary"> mdi-home </v-icon>
<span class="font-weight-bold">Testing</span>
</v-card-title>
<v-card-subtitle class="pb-0"> Subheader </v-card-subtitle>
</v-card>
</v-col>
<v-col cols="12" sm="6" class="d-flex justify-end align-center">
<v-btn to="/about" :block="$vuetify.breakpoint.xsOnly ? true : false" outlined class="blue--text">
<span>Create</span>
</v-btn>
</v-col>
</v-row>
I am having issues aligning things correctly inside my Vue app using Vuetify.
<v-card class="mx-auto">
<v-row>
<v-col
v-for="(item, i) in items"
:key="i"
align-end
justify-end
>
<v-btn class="btn">
<v-icon>{{ item.icon }}</v-icon>
<span class="ml-2">{{ item.text }}</span>
</v-btn>
</v-col>
</v-row>
...
I simply want to align it to the right.
The properties you've put on <v-col> don't exist (i.e. align-end and justify-end). They are properties on the <v-row> component (which is a flex container). You need to use classes instead.
Make sure to consult the API->props section on the Vuetify component page when choosing component properties.
Try
<v-col class="d-flex justify-end">
<v-btn>Button</v-btn>
</v-col>
Note that the alignment is dependent upon the width of v-col. If v-col is only as wide as the button, you'll need to set the width by using the cols="x" property.
Add direction: rtl to your v-btn, Here is codepen:
<template>
<v-btn class="btn rtl">
...
</v-btn>
</template>
<style>
.rtl { direction: rtl; }
</style>
I am trying to align button in my cards. I have a layout which contains 3 cards in a row. But, the problem is, when i add text in the card the position of the button changes in the specific card.
I have tried passing different props and tried using different classes. But it did not work for me
This is the code:
CardRenderer.vue:
<v-container grid-list-sm>
<v-layout wrap>
<v-flex xs12 sm4 v-for="(item, index) in renderData" v-bind:key="index">
<v-card hover height="100%" >
<v-img
class="white"
height="200px"
:src="item.icon"
>
<v-container >
<v-layout fill-height>
<v-flex xs12 align-end flexbox >
<!-- <span class="headline black--text">{{ item.name }}</span> -->
</v-flex>
</v-layout>
</v-container>
</v-img>
<v-card-title>
<div>
<p class="headline black--text">{{ item.name }}</p>
<!-- <span class="grey--text">Number 10</span><br> -->
<!-- <span>Whitehaven Beach</span><br> -->
<span>{{ item.description }}</span>
</div>
</v-card-title>
<v-card-actions>
<!-- <v-btn flat color="orange">Share</v-btn> -->
<v-btn :href="'/dashboard/'+item.name" color="primary">More!</v-btn>
</v-card-actions>
</v-card>
</v-flex>
</v-layout>
</v-container>
This is how my layout looks right now.. Look at the button. I want them to be aligned irrespective of the text provided in the card.
Thanks
You can add classes d-flex flex-column on your v-card and add <v-spacer></v-spacer> before the card actions.
<v-card class="d-flex flex-column">
<v-card-title>
...
</v-card-title>
<v-spacer></v-spacer>
<v-card-actions>
...
</v-card-actions>
</v-card>
Just add an outer class to the card:
<v-card hover height="100%" class="card-outter">
and add card-actions class to v-card-actions
<v-card-actions class="card-actions">
css :
.card-outter {
padding-bottom: 50px;
}
.card-actions {
position: absolute;
bottom: 0;
}
Live example on codesandbox:
https://codesandbox.io/s/vue-template-jsodz?fontsize=14
Add a margin to the bottom of your card, and then position the buttons absolutely from the bottom (with a bit of a margin too).
I know this is old, but I had the same issue. Turs out the absolute position is available through props so you don't have to use inline styling or classes.
<v-card-actions>
<v-btn
absolute
bottom
left
>More!</v-btn>
</v-card-actions>
However, this did mess up the position on my tooltips - fyi.
I had the same problem with only one dialog, so I don't need absolute positioning - just to keep the buttons at the bottom of the card.
'Stead of messing with styles and positioning and stuff, simply insert an extra <v-card-text></v-card-text>, and Vue automatically adds the padding needed to push the buttons down.
Not the best practice, but it's quick and works all right, specially when you're using Vue's automatic styling and don't want to start applying random css.
<v-dialog v-model="dlgShow" max-width="290">
<v-card min-height="220"> //this causes the problems
<v-card-title>Confirmation required</v-card-title>
<v-card-text>Are you sure you want to delete this?</v-card-text>
<v-card-text></v-card-text> //and here's the fix
<v-card-actions>
<v-spacer></v-spacer>
<v-btn #click="dlgShow = false">No, cancel</v-btn>
<v-btn color="primary" #click="myFunc">Yes, delete</v-btn>
<v-spacer></v-spacer>
</v-card-actions>
</v-card>
</v-dialog>
https://codepen.io/Adellii/pen/VBEQbo?&editors=101
The current code moves the buttons to the bottom when user clicks on yes in the radio button.How do I get the buttons fixed in the bottom?
<div id="app">
<v-app id="inspire">
<v-layout>
<v-flex xs12 sm6 offset-sm3>
<v-card height="280">
<v-radio-group v-model="content">
<v-radio label="Yes" value="yes" name="yes"></v-radio>
<v-radio label="No" value="no" name="no"></v-radio>
</v-radio-group>
<div class="x" v-show="content === 'yes'">
<v-text-field label="Regular" placeholder="Placeholder"></v-text-field>
<v-text-field label="Regular" placeholder="Placeholder"></v-text-field>
</div>
<v-card-actions>
<v-btn flat color="orange">Share</v-btn>
<v-btn flat color="orange">Explore</v-btn>
</v-card-actions>
</v-card>
</v-flex>
</v-layout>
</v-app>
</div>
Apparently there are no v-card component props to achieve this.
So just add some css:
.flexcard {
display: flex;
flex-direction: column;
}
<v-card class="flexcard">
Codepen
Note that this works in your provided example for placing buttons at the bottom. In case your CSS is different in your project I'm not sure what you would like to do with other elements inside card. So you might need to add something like <v-spacer></v-spacer> or class="grow" or class="shrink" to some elements inside v-card to fit your style.
Example with bigger v-card height