why can't #apply imported style mixin without <custom-style></custom-style> - polymer-3.x

Why if i want to #apply the imported mixin, custom-style tag it's needed?
import '#polymer/iron-flex-layout/iron-flex-layout.js';
import {html} from '#polymer/polymer/lib/utils/html-tag.js';
const template = html`
<custom-style>
<style>
body{
#apply --layout-vertical;
#apply --layout-center;
}
</style>
</custom-style>
`;

Some browsers have not implemented the Shadow DOM v1 specifications. To make sure your apps and elements display correctly in these browsers, you'll need to use custom-style to ensure that styling information doesn't "leak" into the local DOM of your elements.
custom-style enables a set of polyfills that ensure that styles in your apps and elements behave as you would expect from the Shadow DOM v1 specifications, even in browsers that don't implement these specifications.
To ensure that your styles behave according to the Shadow DOM v1 specifications in all browsers, use custom-style when you define document-level styles
for more information:

Related

How to change styles of child mat angular component?

As angular official documentation says, ::ng-deep , >>>, /deep/ is deprecated and will be removed soon:
https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep
If i am using mat components like <mat-checkbox> or a more comprehensive one like <mat-table> how could I have some changes to that component from parent?
Should I cancel view encapsulation for that component and write
styles in .SCSS files?
How do I edit styles of inner material angular component if deep selector is going to be removed?
What is the proper way to do that?
As the mention document says you can use the combination of ::ng-deep with :host and it will be OK in this way.
In order to scope the specified style to the current component and all its descendants, be sure to include the :host selector before ::ng-deep. If the ::ng-deep combinator is used without the :host pseudo-class selector, the style can bleed into other components
:host /deep/ h3 {
font-style: italic;
}
But, you also can use the custom CSS class & id to apply your custom css on .CSS or .SCSS files on the Angular Material Components. using .class & #id in combination with mat default classes works.
In addition you can use custom Angular material classes in your componnent style files ( .CSS or .SCSS) to override the like this:
.app-component-style {
/* All the CSS here */
.mat-tab-group .mat-tab-label {color: green;}
}
So, keep using it as Dudewad mention here too:
https://stackoverflow.com/a/49308475/4185370

Using Angular component name in Less stylesheet don't match generated DOM

I'm leaning Angular by following Udemy course and I have this style:
server dl {
display: flex;
}
and server component and it don't work. The style is not applied to html. Because generated style look like this:
server[_ngcontent-c1] dl[_ngcontent-c1] {
display: flex;
}
and DOM look like this:
<server _ngcontent-c0="" _nghost-c1="">
<dl _ngcontent-c1="">
<dt _ngcontent-c1="">Plantform</dt>
<dd _ngcontent-c1="">Linux x86_64</dd>
</dl>
</server>
_ngcontent-c0 instead of _ngcontent-c1, why this is happening? Why the style don't match the DOM?
I'm using Angular app using generated by CLI with Less (but I've created component by hand using server as selector, the same happen if name is app-server).
Why this attribute selectors are added? What about if I use this component in different place? I want to match all elements inside component that's why I've added server as selector to always match all inside this component.
How can I use component name that is added to html as root for my whole style? Or is this not good practice in Angular and this is handled other way, if so can someone explain?
Every element of a component is scoped-automagically / polyfilled by angular (in accordance with css spec for scoping) using those attributes you noticed. So basically, you don't have to write component-name element when you write css for that component but you can just write:
dl {
display: flex
}
Angular will make sure that this style is only applied to dl inside server by using the generated attributes, it is essentially a polyfill for css scoping. If all your targeted browsers support css scoping natively, you can even set ViewEnacpsulation.Native
In some cases where you decide to style the root element, you have to use the special selector :host
The :host selector is the only way to target the host element. You
can't reach the host element from inside the component with other
selectors because it's not part of the component's own template. The
host element is in a parent component's template.
So instead of writing server {background: red} you will write :host {background: red}
This is also inline with css spec for scoping.
Read more about CSS coping and component based CSS to know more about this strategy.
As a primer read the base documentation in Angular
Also, note that you can add your css to any global stylesheet like the way you did:
server dl {
display: flex
}
Which way to go largely depends on how you plan to manage and scale css.
You can use at .TS file below the class.
This is delete all this _ngcontent
#Component
selector,
template,
styles,
This code encapsulation: ViewEncapsulation.None

Angular-cli build generated CSS not working

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

Overriding the encapsulated CSS of external component

I was wondering how to override the encapsulated CSS of an external component.
So I am using material2 in my project and the tabs component has a the attribute overflow set on tab-body. Is it possible to override the overflow value?
You can use the special css /deep/ instruction. See the documentation
So, if you have
app
sub-component
target-component
<div class="target-class">...</div>
You can put in your apps css (or less):
/deep/ .target-class {
width: 20px;
background: #ff0000;
}
Obviously, you can put this css fragment in sub-component as well.
From this article
Although the style of a component is well isolated, it can still be easily overridden if necessary. For that, we just need to add an attribute to the body of the page:
<body override>
<app></app>
</body>
The name of the attribute can be anything. No value is needed and the name override makes it apparent what its being used for. To override component styles, we can then do the following:
[override] hello-world h1 {
color:red;
}
Where override is the attribute, hello-world is the target component, and h1 is whatever you are trying to restyle. (get this right or it wont work).
Your component hello-world would be
selector: 'hello-world',
styles: [`
h1 {
color: blue;
}
`],
template: ` <h1>Hello world</h1> `
I think this is the most elegant way.
Alternatively if you are building a library of some sort, you can reset the styling altogether by doing something fancy in your css like:
:host-context(.custom-styles) {
//.. css here will only apply when there is a css class custom-styles in any parent elem
}
So then to use your component you'd use
<hello-world class="custom-styles">
But this is way less convenient than the first option.
::ng-deep .tag-or-css-class-you-want-to-override {
/* Add your custom css property value. */
}
The syntax ::ng-deep is used to override outside css class or tags without using ViewEncapsulation.None.
I see variations of this question a lot and since this is the top question on the subject I want to give the simplest answer. ng-deep and similar functionality is deprecated, so it's best to just rely on vanilla CSS.
Simply create a CSS selector with a higher specificity.
Most people (including myself) get hung up trying to do that because they don't understand two things:
Angular View Encapsulation
CSS Specificity
Angular View Encapsulation
View Encapsulation ensures CSS within a component only affects that component. To affect other components, you need some global CSS. You can do this by using a global style file like styles.css or by disabling View Encapsulation on a component.
#Component({
...
encapsulation: ViewEncapsulation.None
})
CSS Specificity
When two selectors select the same element, the CSS that actually gets applied is based on specificity: https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity
You can increase specificity by simply adding more elements to your CSS selector. For example p.className is more specific than just .className. If you're lazy, you can just repeat a class name to increase specificity. .className.className is more specific than .className.
So to override any CSS in an Angular project, go into styles.css and repeat the class selector until your CSS has a higher specificity than the original.
.className.className.className {
color: red;
}
Didn't work? Add another .className.
Just check the class that is being applied to the tabs by the external component (use Inspector or any other tool). In your style css file, add the same name of the class for the tabs and set the overflow property along with adding !important to it to make sure it overwrites the previous one. Also make sure your css link to the page is added after the external component css link if any.
Hope this helps.
::ng-deep .css-class-you-want-to-override{
/*your custom css property value. like below */
background: white !important;
}

Issue with upgrade to Polymer 0.5.1 and styling paper-dialog

So I just updated my project from Polymer v0.4.2 to v0.5.1 of the Polymer library. One thing that seemed to have changed is how the paper-dialog element is implemented.
In v0.4.2, when I had a paper-dialog inside of my custom element, I could customize it with CSS inside of my element using core-style elements.
In v0.5.1, if I understand correctly, the paper-dialog is no longer implemented inside my component, but instead it's implemented in the core-overlay-layer element which is in the html page outside of my component.
So does that mean that I now have to add a CSS style sheet to the html page that contains my component? If so, then I can no longer use core-style along with the benefits of the CoreStyle.g object. It also means that everything related to my component is no long all encapsulated inside of my component.
Please tell me that I am wrong and that there is a way for me to style the paper-dialog from within my component still.
Thanks!
In Polymer 0.5.1 the layered property (doc: https://www.polymer-project.org/docs/elements/core-elements.html#core-overlay) defaults to true which allows it to always display above page content. If layered is false, the dialog may not display on top if there is something after it in DOM with a higher stacking context.
However because layered reparents the dialog to a global core-overlay-layer it's not possible to style it from an outer scope. There are a couple options for styling:
If you know you don't have any DOM with a higher stacking context than the dialog, set layered="false" to get the non-layered behavior and you can style it from the outer scope.
Style the dialog with a /deep/ rule in a global style. You can still use core-style by referencing the style in the global scope. You can also include it in the same file as your element definition, e.g.
<core-style id="x-dialog">
html /deep/ #dialog {
color: red;
}
</core-style>
<core-style ref="x-dialog"></core-style>
<polymer-element name="my-element" noscript>
<template>
<paper-dialog id="dialog"></paper-dialog>
</template>
</polymer-element>
Extend paper-dialog and style the new element:
<polymer-element name="my-paper-dialog" extends="paper-dialog" noscript>
<template>
<!-- or use core-style -->
<style>
:host {
color: red;
}
</style>
</template>
</polymer-element>
Live examples: http://jsbin.com/subanakuna/1/edit?html,output

Resources