Child style applying to parent component in Angular 2? - css

I'm using Bootstrap css as a global style, and then modify it in each component if I need to, in index.htm I have:
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
and then in the child I add the style
.nav li a {
padding: 5px 10px;
}
which also overrides the value the parent receives from bootstrap for nav li a, is this considered ok? Maybe I don't really understand the Shadow DOM...
Plunker http://plnkr.co/edit/O2r3zKlYj7SH7FWHvWnT?p=preview
(But you have to launch it on you pc, because I'm not sure how to make "#import '/styles/UIComponent.css';" in customer.component.css work in plunker, this way it imports the css file in header and makes it global. If you change the line to "#import '../styles/UIComponent.css';" (the two dots added) it won't import the whole css, and the emulator will translate it as needed.)
Edit:
It's a bug in current Angular2 beta: https://github.com/angular/angular/issues/6449

This should do what you want
:host .nav li a {
padding: 5px 10px;
}
This way you are limiting the scope of your styles to your child component.
With ViewEncapsulation.None this doesn't work of course because this is about style encapsulation and None disables exactly this.

Related

How to use vue js scoped style

I am using vue js's ELEMENT UI. And i want to override its style. I can do it with global style. But scoped style doesnt work. When i used global style it changes my all pages design. but i want to do it just for one page.
Here is my style(global style. and this is working):
<style>
.el-icon-close:before{
content: "Back" !important;
}
</style>
but when i used scoped it doesnt work:
<style scoped>
.el-icon-close:before{
content: "Back" !important;
}
</style>
Is there any idea about this?
The scoped keyword means that this the changes to the style will apply only to the elements in the current scope. Meaning all custom made elements in the page. If you want to access elements "created" somewhere else you will have to skip the scoped keyword. The code that is in the scoped tag will apply only for the current page/view else it will apply for all pages/views.
All not scoped elements usually are style in the App.vue file. If you want to apply style of element that is not scoped just wrap it in a div add the class to it and style it in the scoped tag:
<style scoped>
.my-custom-div{
.el-icon-close:before{
content: "Back" !important;
}
}
</style>
Atleast that is working with me.
You must use custom class:
.custom-class{
smthng goes here...
}
This is achievable with Deep selectors
For your use case:
<style scoped>
.parent-div /deep/ .el-icon-close:before{
content: "Back" !important;
}
</style>

Unable to apply simple CSS to an angular Materials element

Here's the Stackblitz.
I'm trying to apply the CSS color: blue to the div with class mat-button-toggle-label-content, but its not getting applied.
A similar CSS is getting successfully applied to a parent element called mat-button-toggle-group.
Just apply color to mat-button-toggle and keep it inside mat-button-toggle-group
Working stackblitz
mat-button-toggle-group {
background-color: orange;
mat-button-toggle {
color: blue;
}
}
You can apply the style to .mat-button-toggle-label-content but you need to break Encapsulation.
Component styles are encapsulated. You can't access component's styles(classes, ids) from outside of the component. You need to pierce into that component and inject the styles like below
Note: /deep/ is deprecated and no more recommended. So you can go with above approach. And for more details check Component Styles
mat-button-toggle-group {
background-color: orange;
/deep/ .mat-button-toggle-label-content {
color: blue;
}
}
There are many reason for that !
Your CSS may not be inserted properly into code
The order of material design CSS take over the order of CSS
My solution is that you may need to put !important after color: blue;
it is : color: blue !important;
Just move it to styles.scss and it will work Stackblitz.

Angular2: styling component dynamically inserted by the router

Searched for an answer for this and saw people struggling with this but no direct answer, especially with regards to the released 2.x version of Angular.
Suppose you have app.component.html with the following code:
<div>
<router-outlet></router-outlet>
</div>
The router dynamically inserts your custom component, say my-component and (strangely enough) places that component as a sibling of router-outlet element like so:
<div>
<router-outlet></router-outlet>
<my-component></my-component>
</div>
Obviously, the router can place another component in there, so you can't rely on the name being my-component when creating styles in your app.component.css file.
So... How do you do this?
Why this matters? Why not just set the styles on the :host inside of the my-component CSS? Well, because not all styles belong there. For example, if the app.component decides that it's a flex container (i.e., display: flex;), that would mean that the my-component element should be styled as a flex item (i.e., flex: 1 0 0;). Placing the flex item style inside of the my-component seems like a bad practice because you are coupling it with the style of its parent component.
Chime in if you know the answer.
Thanks!
I haven't tried but I guess the adjacent sibling selector should allow you to do that
:host div + * {
display: flex;
}
The key is /deep/ keyword:
the style will apply to whatever element followed by router-outlet.
Or make it specific to apply different style to known components.
:host /deep/ router-outlet + my-component {
display: block;
border: 10px solid black;
}
:host /deep/ router-outlet + my-component2 {
display: block;
border: 10px solid red;
}

Shadow DOM reset stylesheet

I'd like the app I'm making to use a reset.css at the global level. I'd also like it to penetrate all shadow roots but have low specificity. How can I accomplish this?
Let's say my reset.css contains something like:
li, ::shadow li {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
Then my custom element has a template like:
<template>
<style>
li {
padding: 10px;
}
<style>
<ol>
<li>Foo</li>
<li>Bar</li>
<li>Baz</li>
</ol>
</template>
My issue is the template's li selector doesn't have enough specificity to beat ::shadow li. I don't want to have to repeat myself in every custom element. I think I could add a <link> to each <template> but then I'd be repeating myself again. I could also have JavaScript inject the <link> but I'm not sure that's the best way.
What are some other ways I could use a reset.css that penetrates shadow roots but has very little specificity?
I understand that post deprecation of ::shadow and /deep/ selectors this question might not be valid anymore, but if you are still facing this issue, then I would suggest you to use css #imports to inject your common reset.css in shadow-root template.
Since it has to be first tag inside template, your inline stylesheet will take precedence over reset.css, where ever applicable.
I have written an answer here on same topic and one here to inject those #imports at runtime if you don't want to repeat it yourself for each template. Probably it will be work out for you.

Boostrap style overrides custom style even though custom stylesheet included second?

I always modify Bootstrap by including my custom stylesheet after the Bootstrap one, in this particular case, like this:
<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="css/mainstyle.css" rel="stylesheet">
I have a list on the site, some of whose elements also have the class advanced-only.
The list elements have the style in Bootstrap:
.nav > li {
position: relative;
display: block;
}
And the advanced-only class in my custom stylesheet has:
.advanced-only {
display: none;
}
There are other styles such as color and border but they are not relevant here. As you see, the advanced-only elements should be hidden when the page loads, but they are displayed. When I inspect one of these elements, I see that the .advanced-only style is crossed out and the .nav li style from Bootstrap is active. When I deactivate the Bootstrap one from there, then the custom one activates and all is well.
Also, when I do
.advanced-only {
display: none !important;
}
it hides it like it should. However, this would interfere with a bunch of Javascript code (for example, show() and hide() won't work properly with !important elements) so I would like to understand why Bootstrap is overriding the custom style and what I can do about this.
The HTML looks like this:
<ul class="nav nav-sidebar">
<li>
<a>Pending Actions</a>
</li>
<li class="advanced-only">
<a>Hidden stuff</a>
</li>
</ul>
That is because the specificity of your selectors are lower than the Bootstrap selectors. Strongly suggest you reading http://www.w3.org/TR/CSS2/cascade.html#specificity.
The specificity is calculated based on many factors, not just by the order of definition.
For example, this selector .nav > li has an attribute selector and a tag selector, while your rule .advanced-only has only an attribute selector. So your rule is not making affect. Try to make your selector more specific when giving customized styles.
This is because bootstrap's styling is more specific than your custom styling.
To fix this you need to add a more specific selector, e.g:
nav .advanced-only {
display: none;
}
For more reading on CSS Specifity check out this link.

Resources