Overriding the encapsulated :host-style of external component - css

Is it possible to override :host-styling of an external angular2-component?
We're making a library including a sidebar-component. This component has a default (fallback) background, but this should be overridable by css/theme used in the app.
#Component({
selector: 'sidebar',
styles: [`
:host { background-color: green; }
`],
template: `
<h1>sidebar</h1>
<ng-content></ng-content>
`
})
export class SideBarComponent { .... }
Main App css:
<style>
sidebar {background: red; color: yellow; }
</style>
This returns a sidebar with green background and yellow text, but I want a red background...

Edited:
As found on http://blog.angular-university.io/how-to-create-an-angular-2-library-and-how-to-consume-it-jspm-vs-webpack/: add an attribute to the body-tag:
<body override>
<app></app>
</body>
And in your css: use a selector for this attribute:
[override] hello-world h1 {
color:red;
}
This way, your css does not have to be parsed.
Previous solution:
I've found a solution myself: instead of linking my (theming) css-file in index.html, which isn't parsed, I imported this particular css-file in the app.component.ts annotation.
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet/css" type="text/css" href="/assets/style/app.css" />
</head>
<body>
<app></app>
</body>
</html>
app.component.ts:
import { ... }
#Component({
selector: 'app',
styles: [`
#import "assets/style/theme.css";
`],
template: `
...`,
})
export class AppComponent {...}
theme.css:
sidebar {background: red; }

Its not possible to overwrite styles set in a component's styles this way. See point 3 on the "Using Component Styles" section in the Component Styles docs (https://angular.io/docs/ts/latest/guide/component-styles.html)
Our component's styles cannot be changed by changes to styles
elsewhere in the application.
Using :host-context is probably a nicer way to acheive this (although i have never tried myself).

You should try to check the same with host-context. As per documentation host-context works just like the function form of :host(). It looks for a CSS class in any ancestor of the component host element, all the way up to the document root. It's useful when combined with another selector.
In the following example, we apply a background-color style to all <h2> elements inside the component, only if some ancestor element has the CSS class theme-light.
:host-context(.theme-light) h2 {
background-color: #eef;
}

Related

Vue css variables added as inline style

I'm using css variables in my component and set the width of a div based on data computed in the setup()
setup(props) {
const progressBar = PositionService.getProgressBar(props.position);
const progressWidth = `${progressBar}%`;
...
return { ..., progressWidth };
}
Then I'm using this variable as css variable.
<style lang="scss" scoped>
.progress-bar-width {
--progress-bar-width: v-bind("progressWidth");
width: var(--progress-bar-width);
}
</style>
When rendering the page i noticed that an inline style is added to the html parent component resulting in
.....
The CSP is blocking inline style so this approach doesn't work.
How can I use css variables without inline style?
It's a hacky solution but with the handicap of no inline styles it's the only thing I can think of:
Add a "style" component to your template. This will be replaced with <style> tags in the DOM. Inside the component add the desired CSS variable to :root
<component :is="`style`">
:root { --progress-bar-width: {{ progressWidth }}; }
</component>
<div class="progress-bar-width"></div>
<style lang="scss" scoped>
.progress-bar-width {
width: var(--progress-bar-width);
}
</style>
how about use inline style?
https://vuejs.org/guide/essentials/class-and-style.html#binding-inline-styles
<div :style="`--progress-bar-width:${progressWidth}`" >
your component
</div>

ionic 5 component selector is not applied to html element

I have an ionic 5 app for which I built each page using the cmd line, so they were created using the correct structure.
However, when I try to run it, the page styles aren't used, even though the browser shows the css file has been loaded.
I have the following in the .ts page:
#Component({
selector: 'app-onboard',
templateUrl: './onboard.page.html',
styleUrls: ['./onboard.page.scss'],
})
The html file:
<body>
<app-onboard>
...lots of other elements
<div class="style1">
</div>
</app-onboard>
</body>
The scss file:
app-onboard {
.style1 {
color: #ff00ff;
}
}
style1 is on an html element, but it is not applied. However, when I delete the app-onboard wrapper, the style is applied i.e.:
.style1 {
color: #ff00ff;
}
Why would the presence of the app-onboard selector prevent the styles from being applied in the page?
There should be a . in front of the app-onboard in the scss file as you're calling the scss class instead of the html tag like so
.app-onboard {
.style1 {
color: #ff00ff;
}
}
Hence the reason why the style only applied once you removed it.
If you wish to use the selector as per your current scss you'll have to change your html file to
<body>
<app-onboard>
...lots of other elements
<div class="style1">
</div>
</app-onboard>
</body>
I'm assuming the html file is outside of the app-onboard component and you're calling the component from it.

How to use component variable within css / style tag in Angular 2?

How can I use component variables within style TAG in Angular 2?
I do have an Angular 2 component for my header which I like to color depending on a users setting. Thus I'd like to assign an background and font color. While I know how to to this with an attribute binding to an element, I couldn't figure out how to use in a style tag.
Using attribute binding for style works well, however this gets pretty anoying for several subelements, especially if they are nested within other sub components. [ngStyle]= attribute is also only working on a single element.
<header id="header" [style.background-color]="changeBackground()">
<div>
Some Text
Some Link
<subcomponent></subcomponent>
</div>
<div> ... a lot mor stuff </div>
</header>
Thus I'd like to add something like
<style>
#header, #header a {
color: {{mycolor}};
}
</style>
to the html template. However this is not working
Similar Questions do not answer this question yet and only show attribute binding as a solution:
Angular2 dynamic change CSS property
Dynamically updating css in Angular 2
https://scotch.io/tutorials/all-the-ways-to-add-css-to-angular-2-components
https://coryrylan.com/blog/introduction-to-angular-2-ngclass-and-ngstyle
It looks to me like you are just creating a new component called 'subcomponent', why not do that?
subcomponent.ts:
import { Component } from '#angular/core';
#Component({
selector: 'subcomponent',
templateUrl: './subcomponent.html',
})
export class SubComponent {
mycolor = 'blue';
}
subcomponent.html:
<style>
#header, #header a {
color: {{mycolor}};
}
</style>
To your #Component object, add
styles:[ `#header, #header a {
color: {{mycolor}};
}`]
So for example:
#Component({
template: `<header id="header" [style.background-color]="changeBackground()">
<div>
Some Text
Some Link
<subcomponent></subcomponent>
</div>
<div> ... a lot mor stuff </div>
</header>`,
styles: [ `#header, #header a {
color: {{mycolor}};
}`
`]
})
Use NgStyle as explained in this answer
https://stackoverflow.com/a/41903349
in short
<header id="header" [ngStyle]="getStyle()">
<div>
Some Text
Some Link
<subcomponent></subcomponent>
</div>
<div> ... a lot mor stuff </div>
</header>
and
getStyle(): any {
return {"background-color" : this.changeBackgroundColor()};
}

Styling not applying to child component

I'm trying to apply styling to a child component tag, but I can't do that.
I have child component with anchor tag.
Even though i have styling for anchor tag in the parent component, it's not applying. What's the solution for it?
Working code: http://plnkr.co/edit/CJCpV4ZbG7hdxT2AeSmt?p=preview
Google
In the parent component i'm using the child component and applying styling for this child component.
Html code:
<div class="container">
<div class="test">
<testapp></testapp>
</div>
</div>
Css code:
.container{
font-family:sans-serif;
font-size:18px;
border: 1px solid black;
}
.test{
width:50%;
background-color:#f0f5f5;
}
.container:hover .test{
background-color:#e6ffe6;
}
.container:hover .test:hover{
background-color:#ffffe6;
}
.container .test a {
color: red ;
}
.container .test a:hover {
color:green;
}
It's because by default components have view encapsulation (shadow dom). To disable this behavior, you can leverage the encapsulation attribute, as described below:
import {Component, ViewEncapsulation} from '#angular/core';
import {TestApp} from 'testapp.component.ts';
#Component({
selector:'test-component',
styleUrls: ['test.component.css'],
templateUrl: './test.component.html',
directives:[TestApp],
encapsulation: ViewEncapsulation.None // <------
})
export class TestComponent{
}
See this plunkr: http://plnkr.co/edit/qkhkfxPjgKus4WM9j9qg?p=preview.
When using the styleUrls property, the styles are local to the one component, not to its children. So I made two changes:
1) Moved the styleUrls to the testapp component.
2) Moved the div to the testapp component.
import {Component} from '#angular/core';
#Component({
selector:'testapp',
styleUrls: ['./test.component.css'],
template: `
<div class="test">
Google
</div>
`
})
export class TestApp{
}
EDITED: This should solve:
In the css of child class write below code
:host.parentclass childclass{
}
The parentclass is immediate parent of child. childclass is the class applied to child component.

Polymer deep CSS

I am building a Polymer Single Page Interface with a lot of custom elements.
Now I want my elements to have some sort of master style, which I can define in the index.html or my main content element. Think of it like this:
index.html
<style>
.classWhichWillBeUsedInCustomElements {
mainColor: #e0e0e0;
}
</style>
or
<script>
mainColor = "#e0e0e0";
</script>
my-cool-element.html
<polymer-element name="my-cool-element">
<template>
<paper-button style="color: {{mainColor}}"></paper-button>
</template>
</polymer-element>
or
<polymer-element name="my-cool-element">
<template>
<style>
.coolButton {
width: 300px;
color: {{mainColor}};
}
</style>
<paper-button class="coolButton"></paper-button>
</template>
</polymer-element>
Except that this doesn't work.
I have tried:
Creating a global variable window.defaultColor and using it like color: {{defaultColor}};
Using core-style in a parent element, without much luck
Creating a css class in my index.html and calling it in a custom element
What is the right way to achieve this? I am trying to avoid using Less
Use the following pattern in the index.html or a global stylesheet:
<style>
body /deep/ .classWhichWillBeUsedInCustomElements {
mainColor: #e0e0e0;
}
</style>
Then you could use the class within the custom element. The global style will punch the shadow boundary. You could replace body with any other element or selector under which you want to punch the shadow dom boundary.
More on deep here: https://www.polymer-project.org/0.5/articles/styling-elements.html#cat

Resources