Why height: 0 can not work in css definition - javascript

In my project, I use vue.js 2, and i have an img component.
Here is code of it:
<template>
<div class="banner">
<img class="banner-img" :src="bannerImg"/>
</div>
</template>
<script>
export default {
name: 'DetailBanner',
props: {
sightName: String,
bannerImg: String,
gallaryImgs: Array
}
}
</script>
<style lang="stylus" scoped>
.banner
position: relative
overflow: hidden
height: 0
padding-bottom: 55%
.banner-img
width: 100%
The url of img is :
http://img1.qunarzz.com/sight/p0/201404/23/04b92c99462687fa1ba45c1b5ba4ad77.jpg_600x330_bf9c4904.jpg
Here i don't want to display this img, so i set height:0 in CSS.
But unlucky, It fails. I have tested for removing height: 0, and it shows all the same.
why height: 0 can not work, who can help me?

You could take advantage of Vue.js and use v-if to show/hide your image as follow :
<template>
<div class="banner" v-if="showImg">
<img class="banner-img" :src="bannerImg"/>
</div>
</template>
<script>
export default {
name: 'DetailBanner',
props: {
sightName: String,
bannerImg: String,
gallaryImgs: Array
},
data(){
return{
showImg:false
}
}
}
</script>
you could put showImg in your props, by this way you could change the image state using only Vue.js and avoid struggling with CSS

Related

Vue multiselect template slot clear does not work

i copied the code from async part of the documentation, because that's the 'X' to remove value i want.
here is my general component that i use in other vue components
<template>
<div>
<multiselect
v-model="items"
:options="filteredList"
:multiple="multiple"
:close-on-select="multiple ? false : true"
:show-labels="false"
:placeholder="placeholder"
track-by="id"
:label="label"
#input="inputChanged"
:internal-search="false"
#search-change="searchItems"
>
<template slot="clear" slot-scope="props">
<div class="multiselect__clear" v-if="items.length" #mousedown.prevent.stop="clearAll(props.search)"></div>
</template>
</multiselect>
</div>
</template>
<script>
export default {
model: {
prop: 'parentItems',
event: 'change',
},
props: ['multiple', 'list', 'placeholder', 'label', 'parentItems'],
data() {
return {
items: this.parentItems,
filteredList: this.list,
}
},
methods: {
searchItems(query) {
let q = latinize(query.toLowerCase().replace(/\s/g,''))
this.filteredList = this.list.filter(li => latinize(li[this.label].toLowerCase().replace(/\s/g,'')).includes(q))
},
inputChanged() {
this.$emit('change', this.items);
},
clearAll() {
this.items = this.multiple ? [] : null
},
},
}
</script>
everything works as desired, except the X to clear selection is never displayed.
i found the clear element in console, it has width of 255 and height of 0. i tried to put X between the div tags, like this
<template slot="clear" slot-scope="props">
<div class="multiselect__clear" v-if="items.length"
#mousedown.prevent.stop="clearAll(props.search)"
>
X
</div>
</template>
but it would display above the select input field. also changing the height attribute in dev console just made clear space above input field.
what am i missing?
vue-multiselect does nothing special with the clear slot other than render it before the input tags. It leaves the styling and behavior/implementation entirely up to the end user.
In addition, the example from the docs you linked poorly implements the slot, as the provided slot has no contents, so the div won't be visible or clickable, making it effectively useless. Not to mention, it uses the obsolete (pre-2.6) slot syntax of Vue, which would cause warnings on the browser console if using the development build of Vue.
Solution
The clear slot should look like this:
<multiselect v-model="value"
:options="options"
multiple
taggable
#tag="addTag">
<template v-slot:clear>
<button v-if="value.length" class="multiselect__clear" #click="clearSelectedTags">
Ⓧ Clear selection
</button>
</template>
</multiselect>
demo
Thanks to tony19 I went and inspected the part of documentation I mentioned in the question.
I found out that they use different code for the example, so to attain desired effect, I need to add following code to my css.
.multiselect__clear {
position: absolute;
right: 41px;
height: 40px;
width: 40px;
display: block;
cursor: pointer;
/*z-index: 2;*/
}
.multiselect__clear:after, .multiselect__clear:before {
content: "";
display: block;
position: absolute;
width: 3px;
height: 16px;
background: #aaa;
top: 12px;
right: 4px;
cursor: pointer;
}
.multiselect__clear:before {
transform: rotate(45deg);
}
.multiselect__clear:after {
transform: rotate(-45deg);
}

Apply css in dynamic injected html

I am doing something like StackOverflow editor. Fetch markdown text, transfer it to HTML, and inject it into the preview area. But when I tried to apply CSS to the injected HTML elements, it was ignored. In browser inspection, I can not find the stylesheet I write for the elements. I guess this is about the order of CSS rendering. Any suggestion will be appreciated.
<template>
<div>
<div class="item">
<label for="content">Contents</label>
<textarea name="content" id="content" v-model="mdtext"></textarea>
</div>
<div id="preview"></div>
</div>
</template>
<script>
import marked from 'marked'
export default {
data () {
return {
mdtext: ''
}
},
watch: {
mdtext: function () {
document.getElementById('preview').innerHTML = marked(this.mdtext)
}
}
}
</script>
<style scoped>
...
#preview p{
width: 100%;
word-break: break-all;
word-wrap: break-word;
}
...
</style>
You're using scoped css, which makes Vue add that data-v- attribute to the p as well. However, the generated <p> doesn't not have that same data-v- attribute, which is why it's not working.
You can easily fix it by using the deep selector:
<style scoped>
#preview >>> p {
}
</style>
Reference: https://vue-loader.vuejs.org/guide/scoped-css.html#deep-selectors

How to pass styles to child component and use it as scoped style in Vue?

I have a parent component:
<template>
<ChildComponent :styles="styles" />
</template>
<script>
export default {
data: () => ({
styles: `
p {
color: red
}
`
})
}
</script>
And this is the child component:
<template>
<p>Hello World</p>
</template>
<script>
export default {
props: {
styles: {
type: String,
required: true
}
}
}
</script>
<style scoped>
</style>
Now I want to use those styles provided by the parent component in child as scoped styles. Like for example:
<!-- ChildComponent.vue -->
<style scoped>
p {
color: red
}
</style>
Is there any way to do so?
If you want to target the child elements with scoped styling you have to use the deep selector.
Which can be done with
a >>> b { color : red; }
/deep/ a b { color : red; }
a::v-deep b { color : red; }
Here is the full explanation: https://vue-loader.vuejs.org/guide/scoped-css.html#child-component-root-elements
If you wanna add the style in your child component, based on the parent component which is calling it, you can pass an attribute as a prop and use it as a class into the child component. Following your example:
Parent component:
<template>
<ChildComponent styles="parent-style" />
</template>
Child component:
<template>
<section :class="styles">
<p>Hello World</p>
</section>
</template>
<script>
export default {
props: {
styles: {
type: String,
required: true
}
}
}
</script>
<style lang="scss" scoped>
.parent-style {
p {
color: red;
}
}
</style>
Please note that it does not answer scoped CSS.
I am using CSS modules, still might help or just to improve following approach.
Send class names to child component from parent, such as:
Parent Template
<template>
<header :class="$style.Header">
<!-- send class names to **Child-Component** using `v-bind` through the className attribute -->
<HeaderLogo :className="$style.Header__logo" />
</header>
</template>
Child-Template
<template>
<div :class="className">Blah</div>
</template>
CSS Module
<style lang="scss" module>
.Header {
white-space: nowrap;
&__logo {
width: 100%;
}
}
</style>

Binding a Component property in Vue

Good day everyone! I'm currently learning vue and I'm following a youtube tutorial on building an image carousel from scratch. Here's the code for the Image Carousel parent component:
<template>
<div class = "slides">
<div class = "slides-inner">
<div v-for= "slide in slides">
<Slide v-bind:slide= "slide"></Slide>
</div>
</div>
</div>
<script>
import Slide from './Slide';
export default{
data(){
return{
slides:[
{ src:'src/assets/slide1.jpg' },
{ src:'src/assets/slide2.jpg' },
{ src:'src/assets/slide3.jpg' },
{ src:'src/assets/slide4.jpg' },
{ src:'src/assets/slide5.jpg' }
]
}
},
components: {
Slide
}
}
</script>
<style scoped>
.slides {
align-items: center;
background-color: #666;
color: #999;
display: flex;
font-size: 1.5rem;
justify-content: center;
min-height: 10rem;
}
</style>
and here's the code for the individual image slides:
<template>
<div class="slide">
{{slide.src}}
</div>
</template>
<script>
export default {
data(){
return{}
},
props: {
slide: ['slide']
}
}
</script>
<style scoped>
</style>
The v-bind on the v-for loop on the parent Image Carousel component is supposed to bind the slide.src property to the current slide being looped so that it will display the image in the browser but what I'm getting is a blank browser screen and an error that says the right value of the operator at v-bind is not an object although the tutorial I'm following works exactly as it should with this same code so I'm wondering what I'm doing wrong.
In your slide component, it should be
export default {
data(){
return{}
},
props: {
slide: Object
}
}
You can check valid props type in Vue document
Please also see the Vue Style Guide as prop definitions should be as detailed as possible. An Essential Requirement by the creators of Vue. See Vue Style Guide.

Dynamic image is not loaded via :src

I am working on a simple Vue app, using vue-cli and webpack for that purpose.
So basicly i have 2 components, a parent and a child component ~
like this:
<template>
<div class="triPeaks__wrapper">
<div class="triPeaks">
<tri-tower class="tower"></tri-tower>
<tri-tower class="tower"></tri-tower>
<tri-tower class="tower"></tri-tower>
</div>
<div class="triPeaks__line">
<tower-line :towerLine="towerLineCards" />
</div>
<tri-pack />
</div>
</template>
the towerLineCards is the important thing there, it is a prop that is passed to the tower-line component, it is basicly a array with 10 elements, it is a array with 10 numbers that are shuffled, so it can be something like that:
[1,5,2,6,8,9,16,25,40,32]
this array is create via beforeMount on the lifecycle.
On the child component:
<template>
<div class="towerLine-wrapper">
<div class="towerLine">
<img v-for="index in 10" :key="index" class="towerLine__image" :src="getImage(index)" alt="">
</div>
</div>
</template>
<script>
export default {
props: {
towerLine: {
type: Array,
required: true
}
},
method: {
getImage (index) {
return '#/assets/images/cards/1.png'
}
}
}
</script>
<style lang="scss">
.towerLine {
display: flex;
position: relative;
top: -90px;
left: -40px;
&__image {
width: 80px;
height: 100px;
&:not(:first-child) {
margin-left: 3px;
}
}
}
</style>
the issue is with the :src image that i am returning via the getImage(), this way it is not working. If i change to just src it works just fine, i did this way just to test, because the number in the path should be dynamic when i got this to work.
What is wrong with this approach? any help?
Thanks
Firstly, you should use a computed property instead of a method for getImage().
And to solve the other problem, you could add require(YOUR_IMAGE_PATH) when you call your specific image or put it inside /static/your_image.png instead of #/assets/images/cards/1.png.

Categories