I want to insert into component inline css like
<div id="slide1" :style="item.css" v-html="item.html" />
Where my item.css contains string with many css definitions e.g.
#slide1 {} #slide1 p {} #slide1 h2 {} #media(...) { #slide {} } ....
What is the best approach to do this?
So what you are doing here is not loading styles, you are loading a full css set of rules. The style property of an HTML element will only let you add css properties, not blocks of rules like #slide1 {...}.
If you want to load the rules for a singular component remotely, you will want to do use a scoped style block for your component (assuming you are using single file components), like so:
<template>
...
</template>
<style scoped>
#import url("link-to-your-remote-styles");
</style>
What we're doing above is:
making sure that the styles loaded in this component will not bleed out of its scope by using the scoped attribute of the <style> tag;
loading the styles using the #import rule from CSS
Here's a link to a sandbox where I load tailwind just for the scope of one component.
Related
I'm relatively new to Angular, and I have a doubt about component stylesheets.
I have an Angular 12 app and created a component named my-component. The template of the component in question is something like this:
my-component.html
<div>
...some html...
<some-other-angular-component></some-other-angular-component>
...some other html...
</div>
some-other-angular-component is another component, either from the app itself or a third party library.
Now, what I want to do in my-component is apply some CSS rules to the contents of some-other-angular-component. I know that the HTML it generates contains classes that I can target, so I tried to add this to my component CSS:
my-component.scss
.some-other-angular-component-inner-class {
background-color: red;
}
However, this doesn't work, it appears that the component's CSS file only applies rules to the HTML defined directly in the component's template, not the HTML generated by sub-components.
Is there a way to make this work? I find myself having to add my CSS to the webapp's main style.scss file, even when I want to apply the rule only to the particular some-other-angular-component instance inside of my-component. It makes styling confusing and needlessly fragmented. Is this intended, or what am I missing?
I think you may want to look into View Encapsulation.
#Component({
selector: 'app-no-encapsulation',
template: `
<h2>None</h2>
<div class="none-message">No encapsulation</div>
`,
styles: ['h2, .none-message { color: red; }'],
encapsulation: ViewEncapsulation.None,
})
export class NoEncapsulationComponent { }
These styles will be added to head and will be applicable to other components as well if style rule matches.
Please note, with this you are only enabling this behaviour for just this component. Chances of overlapping CSS rules is still there but is lot less in comparison to directly putting styles in style.css.
I will also suggest that you add .class or #id attribute in mark up to ensure that your rules don't overlap by default.
For example:
.my-component .rule-one {
}
It will ensure that my rules are only applied are on component that has this class applied on it.
I work with CSS rarely, but I really want to style my chart. The chart is from a vue.js library and has predefined CSS classes. I just don't know how I am able to access them.
HTML:
CSS:
This is how the document describes the use of CSS with the library:
It's hard to get the full picture only from the images you shared. But it should be relatively easy to just override the default styles that the library uses. If you know what the class names are.
For example:
<style scoped>
year: {
display: block;
}
</style>
Take a look at scoped styles docs.
What you need is a "deep" selector.
So if you want to override child component's styles your css should look like
.vtc-statistik /deep/ .vtc {
}
The thing is that your scoped styles get compiled to
.daten[data-v-bla-bla]{
...
}
b[data-v-bla-bla]{
...
}
/* and .vtc-statistik with nested .vtc */
.vtc-statistik .vtc[data-v-bla-bla] {
...
}
in order to work the way you expect it to work it should get compiled to
/* */
.vtc-statistik[data-v-bla-bla] .vtc{
...
}
where data-v-bla-bla is a unique id of your component.
Btw. Nested styles are not part of CSS specifications. You should use SCSS / PostCSS / Less to process them.
I'm trying to use Bootstrap in a Vue component, and I want all CSS to be scoped. I tried something like this:
<style scoped>
#import "~bootstrap/dist/css/bootstrap.css";
#import "~bootstrap-vue/dist/bootstrap-vue.css";
</style>
But it doesn't seem like the css is scoped. Is there any way to do that?
<style scoped src="~bootstrap/dist/css/bootstrap.css"></style>
<style scoped src="~bootstrap-vue/dist/bootstrap-vue.css"></style>
Update: a hack using SCSS
Reason why the first solution won't work:
With scoped, the parent component's styles will not leak into child
components.
If you want a selector in scoped styles to be "deep", i.e. affecting
child components, you can use the >>> combinator
from the Vue doc for scoped CSS
The modal you mentioned is apparently not being controlled by the component where you imported bootstrap. Perhaps it's a child component. Perhaps you're using the jquery version of Bootstrap modal. Either way, the data attributes won't be added to the modal.
In order to solve this, you need Deep Selector. (you may read about it in more detail in https://vue-loader.vuejs.org/en/features/scoped-css.html)
Here's how I would import the entire Bootstrap CSS using SCSS. (I think it's impossible to do this using pure CSS only.)
<template>
<div class="main-wrapper">
/* ... */
</div>
</template>
<style scoped lang="scss">
.main-wrapper /deep/ {
#import "~bootstrap/dist/css/bootstrap.min";
}
</style>
Some pre-processors, such as Sass, may not be able to parse >>>
properly. In those cases you can use the /deep/ combinator instead -
it's an alias for >>> and works exactly the same.
The generated CSS would be similar to
.main-wrapper[data-v-656039f0] .modal {
/* some css... */
}
.. which is what you want.
BUT, I gotta say, importing the entire Bootstrap CSS is a really bad practice. Try to import only and exactly what you are going to use from bootstrap-sass instead.
This solution is hacky. But it's the only way I know that can work for your use case.
I know it's an old question but this solution work for me
<style lang="scss" scoped>
::v-deep {
#import 'bootstrap/scss/bootstrap.scss';
}
</style>
i wanted use vuetify in my app only on a page , and that crashed my css, then I use
<style scoped src="vuetify/dist/vuetify.min.css"></style>
and now all works perfectly .
<template>
<div> ....... </div>
</template>
<style scoped src="vuetify/dist/vuetify.min.css"></style>
<script> ...... </script>
For me this was the solution to get it to work and prevent leaking:
<style lang="less" scoped>
::v-deep {
#import (less) "../node_modules/vuetify/dist/vuetify.min.css";
}
</style>
The casting to less could obviously also be changed to scss.
They changed the ::v-deep selector in Vue 3, the old method still works, but is deprecated (which can lead to a lot of deprecation messages in your build if you're importing css/scss in this way).
So for the record, this is how you would go about it in Vue 3:
<template>
<div class="main-wrapper">
<div class="bootstrap-scope">
/* All children that need Bootstrap including slotted content etc */
</div>
</div>
</template>
<style scoped lang="scss">
.main-wrapper::v-deep(.bootstrap-scope) {
#import "~bootstrap";
}
</style>
You can also drop the div.main-wrapper and select the root div SFC component. Lets say your component name is my-awesome-component the selector would be:
<style scoped lang="scss">
.my-awesome-component::v-deep(.bootstrap-scope) {
#import "~bootstrap";
}
</style>
Or if you prefer not to use a generated class name you can also go for:
<style scoped lang="scss">
div:first-child::v-deep(.bootstrap-scope) {
#import "~bootstrap";
}
</style>
In actual shadowDom you would use the :host selector to select the root of your component which would make this a more concise, but from what I understand (https://github.com/vuejs/vue-loader/issues/1601) the vue-loader team didn't decide yet what to do with this.
The :deep() selector has a small section devoted to it in the official Vue 3 docs: https://v3.vuejs.org/api/sfc-style.html#deep-selectors
There's also a VueJS RFCS on the deep selector which describes in more detail why it keeps on changing: https://github.com/vuejs/rfcs/blob/master/active-rfcs/0023-scoped-styles-changes.md
I'm working on the VueJS 2 project and I'm trying to clean the code but struggle with scoped styling.
Here is my requirements. :)
I have 3 components those are very similar to each others, so I decide to use mixins to merge the code into one file. Each component will use that mixins of both template and vuejs. When I want to customize the conditions of a particular component, I can simply override the code in it and it is working fine in this part.
However, one thing that I want to do more is to move the scoped style to the mixins as well. At the moment, the style is wrapped in <style lang="scss" scoped></style> tag and this style works very well on its component but I have to duplicate the styling codes into all 3 components.
I know I can add these styles to the global css file but I don't want some styles to the global scope, only one these 3 components will apply for these.
Is it any way to add these styles and apply to mixins?
What is the best practice to code this particular case?
Vue makes this easy.
Solution
To use shared styles in a component you can do this.
MyComponent.js
<template>
</template>
<script>
</script>
<style lang="scss" scoped>
#import '#/scss/shared-styles.scss';
#import 'styles.scss'; // this is the regular CSS used just by the component
</style>
Alternative
You can also import the shared CSS files in the component CSS file instead like below.
MyComponent.js
<template>
</template>
<script>
</script>
<style lang="scss" scoped>
#import 'styles.scss';
</style>
styles.scss
#import '#/scss/shared-styles.scss'
// rest of your component CSS
Automatically import global styles
If you want certain styles to be available in ALL your components you can do this.
vue.config.js
module.exports = {
...
css: {
loaderOptions: {
sass: {
prependData: `
#import "#/scss/global.scss";
`
},
},
},
}
I just found out the scoped style also affect on the child components as well.
Therefore, I found the solution, not sure is it the best practice but I feel very nice for it.
Create a WrapperComponent and I put the scoped style here and a small template.
<template>
<div>
<slot></slot>
</div>
</template>
<style lang="scss" scoped>
/* css style that will apply to all children */
</style>
What happen here is that, when we wrap whatever components with this WrapperComponent, the template will pass on the HTML via slot without any modification and style will be able to apply from now on.
In mixins, I import this wrapper and wrap the component template with the WrapperComponent. Here is the example.
import WrapperComponent from './WrapperComponent'
let MyMixins = {
template: `<wrapper-component>
<div>
Whatever HTML code here
</div>
</wrapper-component>`,
components: {
WrapperComponent,
},
};
When we use this mixins or a child component, the style from WrapperComponent will be automatically applied and also can be used with other groups of components those want to use the same parent style.
Perhaps use modules instead of setting up a style section with a scoped attribute.
https://vue-loader.vuejs.org/en/features/css-modules.html
This way your CSS will still be scoped and not part of your global styling.
I just dropped my fadeTransition.css file into my vue app /assets folder, and import like this:
<template>
<transition name="fade">
<div v-if="showContent">test</div>
</transition>
</template>
<script>
import '#/assets/fadeTransition.css';
// component definition
</script>
fadeTransition.css
/* fade menus in, not out */
.fade-enter-active {
transition: opacity .5s;
}
.fade-enter {
opacity: 0;
}
Clean and simple. Should work for scss, too.
Cheers!
I have an angular-cli app and using webpack.
When I try to run it the component specific css doesn't work
styles.css
/* You can add global styles to this file, and also import other style files*/
#import 'http://something/v4/dist/css/bootstrap.min.css';
Component
#Component({
selector: 'app-carousel',
templateUrl: './carousel.component.html',
styleUrls: ['./carousel.component.css']
})
export class CarouselComponent implements OnInit {
Component CSS
.carousel-indicators { display: none; }
angular-cli.config
"styles": [
"styles.css",
"../node_modules/roboto-fontface/css/roboto/sass/roboto-fontface-bold.scss",
"../node_modules/roboto-fontface/css/roboto/sass/roboto-fontface-light.scss",
"../node_modules/roboto-fontface/css/roboto/sass/roboto-fontface-regular.scss"
],
The rendered html
<style type="text/css">#import url(http://something/v4/dist/css/bootstrap.min.css);</style>
<style type="text/css">/* You can add global styles to this file, and also import other style files */
</style><style></style><style>.carousel-indicators[_ngcontent-c5] { display: none; }</style>
but this is not applied to my html element 'carousel-indicators'
If I import the carousel.component.cssinto the styles.css then it works but it appears twice in the generated html
I'm looking for the right way of doing this
By default(as in your case) angular using ViewEncapsulation.Emulated that scopes your css. However there is 3 view encapsulation options in Angular:
Native view encapsulation uses the browser's native shadow DOM implementation (see Shadow DOM on the MDN site) to attach a shadow DOM to the component's host element, and then puts the component view inside that shadow DOM. The component's styles are included within the shadow DOM.
Emulated view encapsulation (the default) emulates the behavior of shadow DOM by preprocessing (and renaming) the CSS code to effectively scope the CSS to the component's view. For details, see Appendix 1.
None means that Angular does no view encapsulation. Angular adds the CSS to the global styles. The scoping rules, isolations, and protections discussed earlier don't apply. This is essentially the same as pasting the component's styles into the HTML.
So when you applying any styles to your component in component.css(with default ViewEncapsulation.Emulated) the styles will be applied just for that particular component, it won't be leaked outside the component and always have a priority above the global styles unless global style has !important.
So as a result you have the style in the head of your html file like:
<style>.carousel-indicators[_ngcontent-c5] { display: none; }</style>
If you referencing your component.css in styles.css then it will became a global style rendered in html head like so:
<style type="text/css">/* You can add global styles to this file, and also import other style files */
.carousel-indicators {
display: none; }
</style>
As you declared you style in competent and then referenced your component.css in styles.css that competent styles just gets doubled in your html: one copy is a global style and other copy is scoped component styles.
I was tried to replicate you issue but my compentnt.css is always gets applied. I am using the latest stable angular cli 1.3.2. If you are using older cli try to update. Otherwise push your code on github or create a plunker so I can take a look.
UPDATE: You might have your custom css gets overridden by some of your global stylesheets you are referencing. You can use chrome dev tools to debug the styles also you can try to put !important to your custom css and see if it does help.
For everybody landing here :
The issue was with the ViewEncapsulation.Emulated I changed it to ViewEncapsulation.None as describe in this stackoverflow answer :
how to hide ngb-carousel indicators and prev-next control
Thanks for your help