Scoped style in vue.js isn't scoped at all - javascript

Good afternoon,
I'm having a difficulty scoping imported CSS file within bounds of my HTMLEditor vue component.
Here's the component:
<template>
<div class="htmleditor">
<div class="htmleditor-input">
<h3>Header</h3>
<p>Paragraph of text</p>
</div>
<div class="htmleditor-output">
</div>
</div>
</template>
<script>
export default
{
data: () =>
({
html: ''
}),
}
</script>
<style scoped src="~/css/default.min.css">
.htmleditor
{
display: flex;
}
.htmleditor-input
{
border: 1px solid green;
}
.htmleditor-output
{
border: 1px solid yellow;
}
</style>
The issue I'm having is, if I do it this way - it says
Module not found: Error: Can't resolve '~/css/default.min.css'
If I try putting #import '~/css/default.min.css' inside .htmleditor in CSS, all I get is a non-scoped style.

I found the fix.
If you are getting the same error - know that nodejs' vue compiler requires somewhat 'absolute' paths to files.
You can't use '~/' nor '/' nor '.' as the first thing in your path, you have to navigate directly - which in my case (Laravel) meant putting: '../../../../css/default.min.css'.

Related

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

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.

CSS doesn't apply to a component

I have a react component that is wrapped up in div:
AccountLogin.jsx:
import './AccountLogin.css';
export default observer(() => (
<div className="content">
Something here
</div>
));
AccountLogin.css:
.content {
color: blue;
background-color: blue;
margin: 500px;
}
But the css doesn't apply to my rendered component AccountLogin.
Any ideas why that could happen?
Looking at rfx-stack source, I can see that files suffixed with .global.css are imported in global scope where as others are imported as css-modules.
So you can either rename your file to AccountLogin.global.css or use the imported class name:
import styles from './AccountLogin.css';
Within component:
<div className={styles.content}>...</div>

Vue.js conditional module styles

I want to separate the styles in a Vue.js component in modules.
Each style module will have far more than just a class, and new classes will be added regularly. So, it will be hard to change the entire component's template. So, I'm looking for a more practical solution.
I came with the idea of, using a v-if in the styles, but not exactly sure how it should be implemented or if such thing is possible after all.
It will be way more practical, if just depending on the name sent with props, the entire styles changes.
<template>
<div class="color-text">
Text in the color of the class with just the name
</div>
</template>
<script>
export default {
name: 'comp',
props: ['name']
}
</script>
<!-- General styles -->
<style scoped>
div{
float: right;
}
</style>
<!-- red styles -->
<style module v-if="name === 'red'">
.color-text{
color: red;
}
</style>
<!-- blue styles -->
<style module v-if="name === 'blue'">
.color-text{
color: blue;
}
</style>
<!-- green styles -->
<style module v-if="name === 'green'">
.color-text{
color: green;
}
</style>
If I was tackling this I'd use a transitive class value. and not worry about props at all.
<template>
<div class="color-text">
Text in the color of the class with just the name
</div>
</template>
<script>
export default {
name: 'comp'
}
</script>
<!-- General styles -->
<style scoped>
div{
float: right;
}
.red .color-text{
color: red;
}
.blue .color-text{
color: blue;
}
.green .color-text{
color: green;
}
</style>
then you can use the class property to pass in your color type
<div id="app">
<comp class="red"></comp>
<comp class="green"></comp>
<comp class="blue"></comp>
</div>
I've put together an example jsfiddle though it may need some tweaking when it comes to scoped styles and how webpack handles the injection

VueJS error compiling template

I just made my first project with VueJS and Vue-loader.
So I made my first component to show a simple message, it works fine when I make one message, but I get an error when I make multiple messages:
(Emitted value instead of an instance of Error)
Error compiling template:
<message>This is a small message!</message>
<message>Another one</message>
- Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.
This is my code. I'm very new to this and I can't figure out what's wrong.
App.vue
<template>
<message>This is a small message!</message>
<message>Another one</message>
</template>
<script>
import Message from './Components/Message.vue';
export default {
name: 'app',
components: {
Message,
},
data () {
return {
}
}
}
</script>
Message.Vue
<template>
<div class="box">
<p>
<slot></slot>
</p>
</div>
</template>
<script>
export default {
}
</script>
<style>
.box { background-color: #e3e3e3; padding: 10px; border: 1px solid #c5c5c5; margin-bottom: 1em;}
</style>
I hope somebody can help!
The error is pretty self-explanatory. You should have only one root element in each component. So just pack everything in a div.
<template>
<div>
<message>This is a small message!</message>
<message>Another one</message>
</div>
</template>

Categories