I'm new in VueJS and I get confused to change background image from Vue props value.
I've created simple table from 'vue3-easy-data-table'.
BaseTable.vue:
<template>
<EasyDataTable>
...
</EasyDataTable>
</template>
<script setup lang="ts">
changeImg: {
type: String,
}
})
</script>
<style>
.vue3-easy-data-table__message {
background-image: url("`${v-bind("changeImg")}`");
/* background-image: var(--image-url); */
/* background-image: url('#/assets/img/noDataMultiplierOnCity.svg'); */
}
</style>
View.vue:
<template>
<BaseTable
:changeImg= "image"
/>
</template>
<script lang="ts" setup>
const image : string = "'#/assets/img/noDataMultiplierOnCity.svg'"
</script>
I've tried solution from this link https://stackoverflow.com/questions/42872002/in-vue-js-component-how-to-use-props-in-css but no gain.
Already tried as in the comments in the code, in this case I can just style the component in style tag cause the class is from 'vue3-easy-data-table' (maybe have another way to apply style to it?)
I want to make the background image from BaseTable so it can be reused in other file.
I hope I understood you right and this example will help you
template:
<div :style="styleExample" />
script:
let styleExample = { 'width': props.examplePro }
One way to solve this is to use an inline reactive style. For example you could give your script a method that convers the prop into a style, one that holds the image and any other defining features:
<template>
<EasyDataTable :style="backgroundStyles(image)">
...
</EasyDataTable>
</template>
<script setup>
changeImg: {
type: String,
}
})
const backgroundStyles = (img) => {
return {
'background-image': `url(${img})`,
'background-size': 'cover'
}
}
</script>
code:
App.vue
<script setup>
import { ref } from 'vue'
import BaseTable from './BaseTable.vue'
import BaseTable2 from './BaseTable2.vue'
const msg = ref('Hello World!')
const imageUrl = ref("https://cdn.mos.cms.futurecdn.net/SWx64q2g3wax53Xz5H4QjS-970-80.jpg.webp");
</script>
<template>
<h1>{{ msg }}</h1>
<input v-model="msg">
<BaseTable :image="imageUrl"/>
<hr>
<BaseTable2 :image="imageUrl"/>
</template>
BaseTable.vue
<template>
<div class="bkgrnd" :style="backgroundStyles(image)">
<h2>
Base Table
</h2>
<ul v-for="index in 8" :key="index">
<li>Index: {{ index }}</li>
</ul>
</div>
</template>
<script setup>
const props = defineProps(['image'])
const backgroundStyles = (img) => {
return {
'background-image': `url(${img})`,
'background-size': 'cover'
}
}
</script>
<style scoped>
.bkgrnd {
color: white;
font-style: bold;
}
</style>
Solution using the prop in the CSS
Another way to do this can be to avoid inline styles and instead display the background image in the <style> CSS code. To do this, I would use a computed property to create a URL from the prop, something like:
const computedUrl = computed(() => {
return `url(${props.image})`;
});
Code example,
BaseTable2.vue
<template>
<div class="bkgrnd">
<h2>
Base Table 2
</h2>
<ul v-for="index in 8" :key="index">
<li>Index: {{ index }}</li>
</ul>
</div>
</template>
<script setup>
import { computed } from 'vue';
const props = defineProps(['image'])
const computedUrl = computed(() => {
return `url(${props.image})`;
});
</script>
<style scoped>
.bkgrnd {
color: white;
font-style: bold;
background-image: v-bind(computedUrl);
}
</style>
Both examples can be found at the Vue SFC Playground
I have next.js with tailwind CSS installed. I configured everything accordingly to the instructions. All codes are below.
_app.js
import '../styles/index.css';
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
export default MyApp
tailwind.config.js
module.exports = {
content: [],
theme: {
extend: {},
},
plugins: [],
}
postcss.config.js
module.exports = {
plugins: ["tailwindcss"],
}
index.js
import Head from 'next/head'
import Image from 'next/image'
import styles from '../styles/Home.module.css'
export default function Home() {
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
</div>
)
}
index.css
#import 'tailwindcss/base';
#import 'tailwindcss/components';
#import 'tailwindcss/utilities';
When I look up on index.css for any changes from browser (I use chrome) it stays the same. I'm not sure what's wrong.
Firstly make sure that You installed tailwindcss with next.js properly.
Here you have reference to docs
Then Just use it, example index.js page.
import Head from "next/head";
export default function Home() {
return (
<div>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<div className="flex items-center justify-center h-screen flex-col gap-5">
<h1 className="text-3xl text-red-500 font-semibold">Tailwind CSS</h1>
</div>
</div>
);
}
Output:
on tailwind.config.js make sure that in content include the extensions
/** #type {import('tailwindcss').Config} */
module.exports = {
content: [
"./pages/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
My v-select components should have a fixed width (60px), they fit in a table cell, and I want to prevent them from changing the width after value selected.
They change the width and drop-down arrow moves to the right after selection, so if there a way to decrease the size of an icon or its padding/margin it might be helpful.
Don't really know how to get props of this arrow and how this calls.
Here is the reproducible
https://codesandbox.io/s/competent-dew-eixq2?file=/src/components/Playground.vue
EDIT: Add snippet
<!DOCTYPE html>
<html>
<head>
<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.0.1/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<style>
.select {
max-width: 60px;
max-height: 60px;
font-size: 11px;
}
.col {
max-width: 60px;
max-height: 60px;
}
</style>
</head>
<body>
<div id="app">
<v-app>
<v-row>
<div class="col" v-for="col in cols" :key="col">
<v-select class="select" :items="variants" item-value="name" item-text="name" label="" dense outlined hide-details single-line v-model="selected">
</v-select>
</div>
</v-row>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.10/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.0.1/dist/vuetify.js"></script>
<script>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: {
selected: "",
cols: [1, 2, 3, 4, 5],
variants: [{
id: 0,
name: ""
},
{
id: 1,
name: "1:0"
},
{
id: 2,
name: "0:1"
},
{
id: 3,
name: "1:0 B"
},
{
id: 4,
name: "0:1 B"
},
{
id: 6,
name: "1:0 R"
},
{
id: 7,
name: "0:1 R"
},
{
id: 8,
name: "1:0 F"
},
{
id: 9,
name: "0:1 F"
},
],
},
})
</script>
</body>
</html>
The basic problem is that v-select has some styling (specifically padding and margin) that does not work very well at small widths.
This is the innerHTML of the rendered v-select, with the styles that need reducing
<div class="select...">
<div class="v-input__control">
<div role="button" class="v-input__slot"> <!-- padding-right: 12px; -->
<div class="v-select__slot">
<div class="v-select__selections">
<div class="v-select__selection--comma"> <!-- margin-right: 4px; -->
1:0 B
</div>
</div>
<div class="v-input__append-inner"> <!-- padding-left: 4px; -->
<div class="v-input__icon v-input__icon--append"> <!-- width: 24px; min-width: 24px;-->
<i aria-hidden="true" class="v-icon..."></i>
</div>
</div>
</div>
</div>
</div>
</div>
Aside from those innerHTML changes, you want a fixed width of 60px per column so change
<style>
.select {
max-width: 60px;
...
}
to
<style>
.select {
width: 60px;
...
}
Adjusting Vuetify inner styles
Looking at the Vuetify issues around styling, there's suggestions of using un-scoped style blocks, or deep-scoped style blocks, but neither worked for me. Vuetify have said they are working on a revamp of the way styles are applied to overcome the issues.
Fortunately Vue itself has tools to do it in javascript.
These are the key steps
add a reference to the v-select so that it's accessible in javascript
add a change handler to the v-select so that elements can be re-styled when the user selects something
define the style adjustments in an object so you can easily tweak them
add a method to apply the styles
call the method in mounted() and the v-select #change handler
use Vue.nextTick() to allow Vuetify to style first, then our custom styles are applied
Here's the adjusted code snippet. I put in some severely minimal padding and margins, and maximized the space for the selected value (to avoid text wrapping). You may want to play with the styles as I'm not sure I understood all of the requirements.
<!DOCTYPE html>
<html>
<head>
<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.0.1/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
<style>
.select {
width: 60px;
max-height: 60px;
font-size: 11px;
}
.col {
max-width: 60px;
max-height: 60px;
}
</style>
</head>
<body>
<div id="app">
<v-app>
<v-row>
<div class="col" v-for="col in cols" :key="col">
<v-select ref="select" #change="applyCustomStyles"
class="select" :items="variants" item-value="name" item-text="name" label="" dense outlined hide-details single-line v-model="selected">
</v-select>
</div>
</v-row>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.10/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.0.1/dist/vuetify.js"></script>
<script>
const customStyles = {
".v-input__slot": {
padding: "0 0 0 4px",
},
".v-select__selections": {
width: "27px",
},
".v-select__selection--comma": {
margin: "7px 0 7px 0",
},
".v-input__append-inner": {
"padding-left": "0",
},
".v-input__icon": {
width: "14px",
"min-width": "14px",
},
};
new Vue({
el: '#app',
vuetify: new Vuetify(),
mounted() {
this.applyCustomStyles();
},
methods: {
applyCustomStyles() {
Vue.nextTick(() => {
this.$refs.select.forEach((vSelect) => {
Object.entries(customStyles).forEach(([selector, styles]) => {
Object.entries(styles).forEach(([style, value]) => {
vSelect.$el.querySelector(selector).style[style] = value;
});
});
});
});
},
},
data: {
selected: "",
cols: [1, 2, 3, 4, 5],
variants: [{
id: 0,
name: ""
},
{
id: 1,
name: "1:0"
},
{
id: 2,
name: "0:1"
},
{
id: 3,
name: "1:0 B"
},
{
id: 4,
name: "0:1 B"
},
{
id: 6,
name: "1:0 R"
},
{
id: 7,
name: "0:1 R"
},
{
id: 8,
name: "1:0 F"
},
{
id: 9,
name: "0:1 F"
},
],
},
})
</script>
</body>
</html>
Why not a <style> block?
There are suggestions of using an un-scoped style block to override the Vuetify styles.
For example,
<style>
.select .v-input__slot {
padding-right: 4px
}
...
</style>
The problem is the Vuetify styles are getting applied after those declared on the component.
You can do it by applying greater specificity than Vuetify uses, e.g.
<style>
.select.v-text-field.v-text-field--enclosed:not(.v-text-field--rounded)>.v-input__control>.v-input__slot {
padding-right: 4px
}
</style>
gives you this
so you can hunt out all the existing places where a change is necessary and copy the Vuetify selector.
The problems might occur when a new version of Vuetify is used, or the shape of the component is changed. To me, the javascript solution looks more manageable.
1. If you don't care about the appended icon, you can remove it with the use of append-icon prop (pass empty value):
<v-select
class="select"
...
append-icon=""
></v-select>
2. You can override the slot for the icon with your own content:
<v-select
class="select"
...
>
<template #append>
<div class="my-custom-icon">...</div>
</template>
</v-select>
Then add style to your my-custom-icon class to make it appear in one place:
.my-custom-icon {
position: absolute;
left: ...;
right: ...;
}
3. Make use of overflow: hidden property:
<style> // don't add "scoped" attribute, otherwise the style won't be applied
.select .v-input__control {
overflow: hidden;
}
</style>
Hello I have facing same problem but as I am using custom made select from vuetify v-select i can not overwrite CSS because it will change drop-down in whole project and this will be the case for all devloper working on projects
So simple solution will be make container div and give it min-width max width and width as you see fit it will solve your size change issue with table cell
It worked for me as i set my drop-down min width to max-width of container so it will be same same width
Ex
<div :class='container'>
<v-select />
</div>
<style>
. container {
max-width: 9rem // in my case it's the min width for my default selected option
}
</style>
I have a <b-form-select></b-form-select> in Bootstrap Vue and would like to change color of arrows. I tried a lot but arrows still stay black. How can I change the color of them?
You have to change the background of your .custom-select
Arrow color changed:
new Vue({
el: "#app",
data() {
return {
selected: null,
options: [{
value: null,
text: 'Please select an option'
},
{
value: 'a',
text: 'This is First option'
},
{
value: 'b',
text: 'Selected Option'
},
{
value: {
C: '3PO'
},
text: 'This is an option with object value'
},
{
value: 'd',
text: 'This one is disabled',
disabled: true
}
]
}
}
})
/* I changed the fill of the SVG to red */
.custom-select {
background: #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='red' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right .75rem center/8px 10px !important;
<!-- Load required Bootstrap and BootstrapVue CSS -->
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.css" />
<!-- Load polyfills to support older browsers -->
<script src="//polyfill.io/v3/polyfill.min.js?features=es2015%2CIntersectionObserver" crossorigin="anonymous"></script>
<!-- Load Vue followed by BootstrapVue -->
<script src="//unpkg.com/vue#latest/dist/vue.min.js"></script>
<script src="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.js"></script>
<!-- Load the following for BootstrapVueIcons support -->
<script src="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue-icons.min.js"></script>
<div id="app">
<b-container>
<b-row>
<b-col>
<div class="mt-3">Selected: <strong>{{ selected }}</strong></div>
<b-form-select v-model="selected" :options="options"></b-form-select>
</b-col>
</b-row>
</b-container>
</div>
This is the CSS solution.
With SASS you can do this without overwriting - just include your modifications, and that overwrite the default value: https://bootstrap-vue.js.org/docs/reference/theming/
Try this with a classname in your css style of
<b-form-select></b-form-select>
Demo: https://jsfiddle.net/bardalesj/uwnp8efr/147/
In my website, I am using fancybox 2.1.5. when I open an image and close it I return to the top of the page unintentionally. The problem can be seen in the following minimal example
<!DOCTYPE html>
<head>
<style media="screen" type="text/css">
body {
height: 100%;
}
html {
height: 100%;
}
</style>
<link rel="stylesheet" type="text/css" href="css/jquery.fancybox.css?v=2.1.5" media="screen" />
</head>
<body>
<a href=#>
<img src="http://placehold.it/1000x600">
</a>
<a class="fancybox" href="img/Gallery/500x600.gif">
<img src="http://placehold.it/500x600">
</a>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.fancybox.js?v=2.1.5"></script>
<script>
$(document).ready(function() {
$('.fancybox').fancybox();
});
</script>
</body>
</html>
You will see that if you open and close the second image you will find yourself at the top of the page.
It appears that if I delete the initial style in the head
<style media="screen" type="text/css">
body {
height: 100%;
}
html {
height: 100%;
}
</style>
The problem disappears. if I erase only the body style or the html style the problem also disappears. In order for the problem to appear both body and html heights must be to 100%
Unfortunately I don't understand why this is happening. Can someone please explain?
Note: I have found solutions and hacks to this problem but I would like to understand why this is happening
Update: seems not to work if you trigger the Fancybox while on a URL that points to a tag with an ID (e.g., "https://example.com/#currentsection"). When you exit the Fancybox, it doesn't go to the top of the page, but does scroll to the top of the tag with the ID, even if you've set the autoFocus and placeFocusBack options to false. Strangely, it still works if your URL is pointed at #top.
Original answer
I found that when using Fancybox in Next.js, binding or configuring Fancybox with autoFocus set to false fixed this. It then seems that placeFocusBack property (default: true) will apply. Set it up like so:
npm install --save #fancyapps/ui
components/fancybox-wrapper.js:
// Fancybox UI wrapper for lightbox
// Thanks to https://fancyapps.com/docs/ui/fancybox/react
import React, { useEffect } from "react";
import { Fancybox as NativeFancybox } from "#fancyapps/ui/dist/fancybox.esm.js";
function Fancybox(props) {
const delegate = props.delegate || "[data-fancybox]";
useEffect(() => {
const opts = props.options || {};
NativeFancybox.bind(delegate, opts);
return () => {
NativeFancybox.destroy();
};
}, []);
return <>{props.children}</>;
}
export default Fancybox;
pages/_app.js:
import Fancybox from "../components/fancybox-wrapper";
import "#fancyapps/ui/dist/fancybox.css";
import { SSRProvider } from "#react-aria/ssr";
function MyApp({ Component, pageProps }) {
return (
<SSRProvider>
<Fancybox options={{ infinite: false, autoFocus: false }}>
<Component {...pageProps} />
</Fancybox>
</SSRProvider>
);
}
export default MyApp;
You can use native helper of fancy box to fix returning to top of page problem.
$('.fancybox').fancybox({
padding: 0,
helpers: {
overlay: {
locked: false
}
}
});
reference : http://davekiss.com/prevent-fancybox-from-jumping-to-the-top-of-the-page/