I tried out Angular before switching to Vue and found the :host selector in their components to be very handy. The jist of this is that it applies the stylings for :host to the component itself.
Is there an equivalent of this that works with .vue files in they <style scoped></style> section?
Examples:
Using Scoped
Parent:
<template>
<div class="host">
<layout-header :open-nav="openNav" #toggle-open="toggleOpen"></layout-header>
<layout-sidebar :open-nav="openNav"></layout-sidebar>
<layout-content></layout-content>
<layout-footer></layout-footer>
</div>
</template>
<style scoped>
.host {
display: flex;
height: 100%;
width: 100%;
flex-direction: column;
}
</style>
Content:
(<layout-content>)
<div class="host">
stuff
</div>
<style scoped>
.host{
flex: 1;
}
</style>
Output:
(removing the header, footer, and sidebar for simplicities sake.)
This results in the header, sidebar, content, and footer inheriting the parents css if they have a .host class.
HTML:
<div data-v-238e7577="" class="host">
<div data-v-7412829c="" data-v-238e7577="" class="host">stuff</div>
</div>
The CSS applied to the child element:
There is no equivalent for Angular's :host in Vue.
The closest you are gonna get is by using CSS module.
Demo: App.vue in https://codesandbox.io/s/o4orw9nz35
<template>
<div id="app" :class="$style.container">
<p class="red">p tag</p>
<div class="blue">div tag</div>
</div>
</template>
<style lang="scss" module>
.container :global {
.red {
color: red;
}
.blue {
color: blue;
}
}
</style>
Note how the .container class is used as $style.container as class in the root div.
CSS module will generate unique class name for .container, making it impossible to have class name collisions.
What does :global do?
CSS module transform the CSS class name into something unique by default.
for e.g. .container will be transformed into something like .container_7ba5bd90 when used as $style.container.
To avoid this transformation on certain classes, use :global to wrap them.
(Explanation for :global can be found here.)
Related
I'm learning Angular from a ReactJS and JSVanilla background. I'm trying to understand how Angular build its views and how can we work with them.
My question is: What is the best way (or available options) to make parent css reflect / constraint child css on Angular?
Example, using JSVanilla:
<section class="parent">
<section class="child">
<section class="grandchild">
</section>
</section>
</section>
.parent{
height: 1000px;
width: 800px;
}
.child{
height: 80%;
width: 90%;
}
.grandchild{
height: 30%;
width: 20%;
}
In this case, each section would be a component by itself.
Well, studying for a few, I've come up with a nice solution which involves the :host selector.
In angular, after all the components in a module being rendered, we get the following pseudo-tree:
<app-parent>
<section class="parent">
<app-child>
<section class="child">
<app-grandchild>
<section class="grandchild">
</section>
</app-grandchild>
</section>
</app-child>
</section>
</app-parent>
As we can see, the constraints of the child is being marked by the <app-tag/>, which dictates how the children will be rendered.
In terms of size, but not all attributes, the best option for me was to use the :host selector, which selects the <app-tag/>. In the css, will look like this:
:host{
height:80%;
width: 90%;
}
.child{
/* child styles here */
}
And this resolved my problems.
You can read about View Encapsulation concept in Angular.
There are 3 types of View encapsulation.
ViewEncapsulation.None
ViewEncapsulation.Emulated
ViewEncapsulation.ShadowDom
You can place encapsulation in #Component decorator as shown in the below code snippet
#Component({
selector: 'app-shadow-dom-encapsulation',
template: `
<h2>ShadowDom</h2>
<div class="shadow-message">Shadow DOM encapsulation</div>
<app-emulated-encapsulation></app-emulated-encapsulation>
<app-no-encapsulation></app-no-encapsulation>
`,
styles: ['h2, .shadow-message { color: blue; }'],
encapsulation: ViewEncapsulation.ShadowDom,
})
Please read the below article, Hope it helps!!
https://codecraft.tv/courses/angular/components/templates-styles-view-encapsulation/
I wanted to find out if its possible to separate a vue component's scoped scss with deep selectors into a another file and have it imported back in?
Example:
// Main.vue
<template>
<div id="main">
<h1>Title</h1>
<span>Text</span>
</div>
</template>
<style lang="scss" scoped>
#main::v-deep {
&>h1 {
font-size: 10rem;
}
&>span {
font-size: 5rem;
}
}
</style>
Could I somehow achieve this:
// Main.vue
...
<style lang="scss" scoped>
#import url('./Main.scss');
</style>
// Main.scss
#main::v-deep {
&>h1 {
font-size: 10rem;
}
&>span {
font-size: 5rem;
}
}
without having this style applied to components that may have id/class="main" anywhere else in the project? Mainly just scoped to this component?
You can use :deep() { #import './Main.scss' } to import whole scss file and it will work for your child components too.
I tried to change the background-color in b-modal -> in .modal-header using bootstrap-vue. But the vue doesn't see my styles and I don know why :/
here is the code. I follow by answer in link
HTML:
b-modal(id="card-1" title="CARTÃO DE CRÉDITO" :modal-class="myclass" header-text-variant="light")
VUE
export default {
data: {
myclass: ['myclass']
},
}
CSS
.myclass > .modal-dialog > .modal-content > .modal-header {
background-color: #da2228 !important;
color: white;
}
But I still doesn't see the results. Modal header is white. Any ideas why?
You're probably using a scoped style tag in your .vue file.
If you are, then you need to use a deep-selector to properly target the subcomponent.
The selectors are /deep/, >>> or ::v-deep.
In the below example i use /deep/, but the others should work for you as well.
You can also use the header-class prop on b-modal to directly add the class to the header if you wish.
<template>
<b-modal header-class="my-class">
<template #modal-header>Header</template>
Hello
</b-modal>
<b-modal modal-class="my-second-class">
<template #modal-header>Header</template>
Hello
</b-modal>
</template>
<style scoped>
/deep/ .my-class {
background: black;
color: white;
}
/deep/ .my-second-class > .modal-dialog > .modal-content > .modal-header {
background: black;
color: white;
}
</style>
You can use content-class="your-class" in the vue bootstrap modal.
<b-modal id="myModal" content-class="your-class" title="BootstrapVue">
Body Content
</b-modal>
Or else it is difficult to style the modal cuz the normal class="" does not apply to the code.
I defined styles for my website.
I also include specific content, which is written with a WYSIWYG editor by the users.
This content should have a specific style, but not erase the style of the rest of the website.
I tried using but then no style is applied at all. is there any way to apply a specific style to this content?
<template>
<div id="content">
<div class="content" v-html="content"></div>
</div>
</template>
export default {
name:'content',
props: {
content: {
type: String,
default: '<div>Contenu à définir</div>'
}
}
}
<style scoped>
h1, h2, h3 {
color: #94c946;
margin:0;
font-family: 'Montserrat-ExtraBold';
vertical-align:baseline
button{
font-family: 'Montserrat-ExtraBold';
border-radius: 100px;
background-color: #94c946;
color: #1B1B1B;
}
</style>
The scoped styles in view only work for the elements that are present on the component on the template, but not for dynamic content.
I would recommend you to use some id cascade, for example declare an id for your section like this:
<style>
#content button { .... }
#content h1, #myEditor h2 {....}
</style>
This can be accomplish better using some css preprocessor like sass
<style lang="sass">
#content
button
....
h1, h2, h3
....
</style>
I'm trying to apply a theme to my dart-polymer material-design application, everywhere I look at videos and tutorials, it is suggested that with a few lines of CSS you can change the look of the whole application.
I've even generated a theme just now using: http://www.materialpalette.com/grey/red and it gave me the following CSS:
/* Palette generated by Material Palette - materialpalette.com/grey/red */
.dark-primary-color { background: #616161; }
.default-primary-color { background: #9E9E9E; }
.light-primary-color { background: #F5F5F5; }
.text-primary-color { color: #212121; }
.accent-color { background: #FF5252; }
.primary-text-color { color: #212121; }
.secondary-text-color { color: #727272; }
.divider-color { border-color: #B6B6B6; }
... which I've included in my default stylesheet, but with no colour changes.
So if this is my custom polymer element:
<polymer-element name="main-app" class="default">
<template>
<style type="text/css">
:host {
display: block;
}
</style>
<core-toolbar class="default">
<paper-icon-button icon="menu"></paper-icon-button>
<span flex class="default">
<paper-tabs selected="0">
<paper-tab>ITEM ONE</paper-tab>
<paper-tab>ITEM TWO</paper-tab>
<paper-tab>ITEM THREE</paper-tab>
</paper-tabs>
</span>
<paper-icon-button icon="refresh"></paper-icon-button>
<paper-icon-button icon="more-vert"></paper-icon-button>
</core-toolbar>
</template>
<script type="application/dart" src="main-app.dart"></script>
</polymer-element>
And this is my index.html using that custom main-app component:
<!DOCTYPE html>
<head>
...
<link rel="import" href="packages/falm/main-app.html">
<link rel="stylesheet" href="styles.css">
</head>
<body unresolved>
<main-app class="default"></main-app>
<script type="application/dart">export 'package:polymer/init.dart';</script>
</body>
</html>
... what is the proper way to use the generated theme?
Am I suppose to add those css classes in manually everywhere?
Yes, you need to add the classes somewhere.
You can use the core-style element to reuse styles or you can add the styles to the main page (index.html) and prefix them with * /deep/ (like `* /deep/ .dark-primary-color) but still need to apply the classes to the elements.
Some resources about styling polymer elements
https://www.polymer-project.org/articles/styling-elements.html
https://www.polymer-project.org/docs/polymer/styling.html
https://www.polymer-project.org/docs/polymer/layout-attrs.html