Override CSS of component selector style from ng module - css

I'm trying to modify the css color picker of a module, in order to adapt it to my website (align it to center).
Here's the code of the color picker:
#Component({
selector: 'color-circle',
template: `
<div
class="circle-picker {{ className }}"
[style.width.px]="width"
[style.margin-right.px]="-circleSpacing"
[style.margin-bottom.px]="-circleSpacing"
>
<color-circle-swatch
*ngFor="let color of colors"
[circleSize]="circleSize"
[circleSpacing]="circleSpacing"
[color]="color"
[focus]="isActive(color)"
(onClick)="handleBlockChange($event)"
(onSwatchHover)="onSwatchHover.emit($event)"
></color-circle-swatch>
</div>
`,
styles: [
`
.circle-picker {
display: flex;
flex-wrap: wrap;
}
`,
],
I'm using justify-content: center to the class circle-picker to align it, but nothing happens, so I don't really know if I'm able to do it.
Here's how I use the selector:
<color-circle [colors]="colors" [color]="productForm.get('color')?.value" (onChange)="onColorChanged($event)" width="190px" circleSize="34" circleSpacing="18"></color-circle>
When I inspect the code with the browser, I can make it, but with the CSS file nothing works.
Could anyone help?
This is what I want:
This is what I have:
Author of the color picker:
https://github.com/scttcper/ngx-color

If you want to set style to elements inside your host component. you must use :host
and to change deeper elements you have to use ::ng-deep
Use
:host color-circle ::ng-deep color-circle-swatch{
justify-content: center;
align-items:center
}

May be this two line of code can fix your problem
.color-circle-swatch{
margin: 0 auto;
width:100%;
}

Related

How to make css recognize a custom angular object is disabled?

I've been having trouble changing the colours of a custom disabled angular button. The button (or better - the button element) is conditionally disabled and that part works perfectly, but I need to set the colour of the disabled button to seem disabled (e.g grey) except when I inspect the element it seems to have the styles shown below despite being disabled. I've tried setting ef-ng-b2b-button:disabled {background: black !important} but it doesn't seem to work.
How it looks currently:
How it's supposed to look:
HTML
<ef-ng-b2b-button
ef-feature-id="vp.configurator.model-info-dialog.create-offer"
size="l"
type="primary"
prefixIcon="add"
(click)="createConfiguration('offer')"
[disabled]="!configurationValid"
>
{{ 'vp.modules.configurator.create.offer' | ppTranslate }}
</ef-ng-b2b-button>
<ef-ng-b2b-button
*ngIf="showContract"
ef-feature-id="vp.configurator.model-info-dialog.create-contract"
size="l"
type="primary"
prefixIcon="add"
(click)="createConfiguration('contract')"
[disabled]="!configurationValid"
>
{{ 'vp.modules.configurator.create.contract' | ppTranslate }}
</ef-ng-b2b-button>
CSS
div:nth-child(1) {
display: flex;
justify-content: flex-start;
}
div:nth-child(2) {
display: flex;
justify-content: flex-end;
ef-ng-b2b-button:first-child {
margin-right: 10px;
}
ef-ng-b2b-button:nth-child(2) {
margin-right: 10px;
}
}
You need to attach a style to this element: ef-ng-b2b-button with angular.
CSS doesnt notice the changes of the disabled button that come from changes in angular. In this case, the behavior isnt like it is for dom events such as 'hover', 'mouseover', 'focus', etc.
Try something along these lines:
<ef-ng-b2b-button
ef-feature-id="vp.configurator.model-info-dialog.create-offer"
size="l"
type="primary"
prefixIcon="add"
(click)="createConfiguration('offer')"
[disabled]="!configurationValid"
[style.color]="!configurationValid ? 'black': 'blue' " >
{{ 'vp.modules.configurator.create.offer' | ppTranslate }}
Look into the NgClass directive to set css classes on your condition with the ternary operator
https://angular.io/api/common/NgClass
<div [ngClass]="condition == true? 'enabledCssClass' : 'disabledCssClass' " >
or just use an ngIf with your condition and place two different button elements on the html page

Select "toolbar-title" within shadow root of ion-title via css

In Ionic, the ion-title component has the content encapsulated in an extra div within its shadow-dom.
This div has the class .toolbar-title set. How can i select this div via scss-selector to change its overflow behavior?
I tried:
.toolbar-title { ... }
ion-title .toolbar-title
ion-title::shadow .toolbar-title { ... }
ion-title::shadow(div) { ... }
and a lot other combinations including :host & ::ng-deep selectors.
And, yes i know , ::shadow and ng-deep is deprectaded.
I also know that ionic has introduced css-variables for this purposes, but unfortunatley not for the overflow attribute.
THX in advance!
The concept of shadowDOM is you can't touch its content with CSS from the outside.
It is an open shadowDOM, so you can change it with JavaScript.
document.querySelector("ion-title")
.shadowRoot
.querySelector(".toolbar-title")
.style
.overflow = "initial";
Ionic v6 allows you to target and modify shadowDOM contents with CSS. See https://ionicframework.com/docs/theming/css-shadow-parts
However, the element you want to select inside the shadowDOM needs to expose a part attribute. For instance the ion-select element:
<ion-select>
#shadow-root
<div part="placeholder" class="select-text select-placeholder"></div>
<div part="icon" class="select-icon"></div>
</ion-select>
You can select the placeholder element with:
ion-select::part(placeholder) {
color: blue;
opacity: 1;
}
Unfortunately, the ion-title element does not expose any shadow parts. You need to wrap the contents of ion-title in a container to be able to modify them:
<ion-title>
<div class="content">
<img src="..." />
Hello World!
</div>
</ion-title>
CSS:
.content {
display: flex;
align-items: center;
}
StackBlitz example: https://stackblitz.com/edit/ionic-title-modification-8a1qst

How styling works over components in angular?

Question is not clear but I'll break it down. In angular we can write isolated css for styling. It works pretty well for native html elements. But unlike react, angular wrap our html with custom elements like <app-card>...</app-card>. When I write css for those wrapper elements, it doesn't work .
If I have a post list like
<div class="post-list">
<app-card [post]="post" *ngFor="let post of posts"></app-card>
</div>
If I write css to apply some vertical gap between app-card components in PostListComponent. Well nothing happens.
.post-list app-card:not(:last-child) {
margin-bottom: 2rem;
}
How can I make it work? Or with angular logic, how can I apply vertical gap between angular components
Just add display: block; on your app-card component & it will work as expected.
.post-list app-card {
display: block;
}
.post-list app-card:not(:last-child) {
margin-bottom: 2rem;
}
<div class="post-list">
<app-card>Card 1</app-card>
<app-card>Card 2</app-card>
<app-card>Card 3</app-card>
</div>
You can define encapsulation: ViewEncapsulation.None in your Component like this:
#Component({
selector: 'foo',
template: './foo.component.html',
styleUrls: ['./foo.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class FooComponent { }
Which will treat your .css as the same if you were putting it in the global scope.
To be more accurate, it won't append .fooComponent to each css rule in foo.component.scss.
You can make the iteration in div tag then add your class
<div class="post-list">
<div class="post" *ngFor="let post of posts">
<app-card [post]="post"></app-card>
</div>
</div>
And in your css
.post-list .post:not(:last-child) {
margin-bottom: 2rem;
}
There is no reason it shouldn't work. Just tried to put in some of your code here. https://stackblitz.com/edit/angular-scss-demo-icqrye
app.component.html
<div class="post-list">
<app-new *ngFor="let item of [1,2,3,4]"></app-new>
</div>
styles.scss
.post-list app-new:not(:last-child) p {
margin-top: 2rem;
color: green;
}
And it works perfectly. Are you looking for something else?
And if you want to add the style (margins) to the component directly, you will first need to set the display of the component to block/flex as per requirement.
.post-list app-new:not(:last-child) {
display: flex;
}

How to increase b-tooltip width?

I am using b-tooltip tags of BootstrapVue to show information. I want to increase the width of b-tooltip (for long text message), text alignment, etc . How can i do it (basically how can i style it)?
<b-button id="tooltip-target-1">
Hover Me
</b-button>
<b-tooltip target="tooltip-target-1" triggers="hover">
I am tooltip <b>component</b> content!
</b-tooltip>
If you're using SCSS in your project, then the easiest way for a global solution would be to modify the SCSS variables to your liking.
If you want to only apply styles to a specific tooltip, or apply something there isn't a variable for. You can use the custom-class prop on b-tooltip to supply it with a custom class, which allows you to style it to your liking.
If you're placing this CSS in a scoped style tag <style scoped> you will need to use a deep selector to target the subcomponents such as .tooltip-inner.
new Vue({
el: '#app',
})
.custom-tooltip > .tooltip-inner{
/* Removes the default max-width */
max-width: none;
/* Apply whatever other styles you want */
font-size: 150%;
padding: 10px;
}
/* This styling is just for the example */
#app {
display: flex;
height: 100vh;
width: 100vw;
align-items: center;
justify-content: center;
}
<link href="https://unpkg.com/bootstrap#4.4.1/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://unpkg.com/bootstrap-vue#2.14.0/dist/bootstrap-vue.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.14.0/dist/bootstrap-vue.js"></script>
<div id="app">
<div>
<b-button id="tooltip-target-1">
Hover Me
</b-button>
<!-- Use the variant prop to use your theme colors -->
<!-- If you want a custom color, you can use CSS -->
<b-tooltip target="tooltip-target-1" variant="primary" custom-class="custom-tooltip" triggers="click">
I am tooltip <b>component</b> content!
</b-tooltip>
</div>
</div>
The trick to change styles of bootstrapvue tooltip.
<style>
.tooltip-inner {
max-width: 800px;
}
</style>
Don't use scoped in style because the component render the html of tooltip outside of app so if you put scoped your css will not work.

I have a plunker. When I define my css globally, it works. When I define my css in my component, it fails. What's going on?

With reference to this plunker:
https://plnkr.co/edit/GWsbdDWVvBYNMqyxzlLY?p=preview
I have the same css specified in the styles.css file, and in the src/app.ts file.
If I comment in the css in styles.css and comment out the css in src/app.ts, it works.
styles.css:
/* If these are commented in, and the ones in src/app.ts are
* commented out, the three items are spaced appropriately. */
/***
md-toolbar-row {
justify-content: space-between;
}
md-toolbar {
justify-content: space-between;
}
***/
If I comment out the css in styles.css and comment in the css in src/app.ts, it fails.
src/app.ts:
#Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<md-toolbar color="primary">
<span><md-icon>mood</md-icon></span>
<span>Yay, Material in Angular 2!</span>
<button md-icon-button>
<md-icon>more_vert</md-icon>
</button>
</md-toolbar>
</div>
`,
// If these are commented in, and the ones in style.css are
// commented out, the three items are scrunched together.
/***/
styles: [
`md-toolbar-row {
justify-content: space-between;
}`,
`md-toolbar {
justify-content: space-between;
}`
]
/***/
})
export class App {
name:string;
constructor() {
this.name = `Angular! v${VERSION.full}`
}
}
I'm having trouble visualizing the difference between defining the css for the whole application, and for the specific component. Can someone tell me what's going on?
=================================
#bryan60 and #Steveland83 seem to indicate that the problem lies somewhere in the view encapsulation. And upon further investigation, it does in a sense.
If you look at the code below, you will see that the styles for md-toolbar and md-toolbar-row have an attribute attached. But the html for md-toolbar and md-toolbar-row does not match. Only md-toolbar has the attribute attached. md-toolbar-row doesn't. I have marked the relevant four lines with >>>>>.
So that's the problem but:
1. Do I report it to the material design people as an error?
2. Is there some workaround I can use today?
<html>
<head>
:
<script src="config.js"></script>
<script>
System.import('app')
.catch(console.error.bind(console));
</script>
<link href="https://rawgit.com/angular/material2-builds/master/prebuilt-themes/indigo-pink.css" rel="stylesheet">
<style>
>>>>> md-toolbar-row[_ngcontent-c0] {
justify-content: space-between;
}
</style>
<style>
>>>>> md-toolbar[_ngcontent-c0] {
justify-content: space-between;
}
</style>
<style>
.mat-toolbar {
display: flex;
: :
.mat-mini-fab,
.mat-raised-button {
outline: solid 1px
}
}
</style>
</head>
<body class="mat-app-background">
<my-app _nghost-c0="" ng-version="4.4.0-RC.0">
<div _ngcontent-c0="">
<h2 _ngcontent-c0="">Hello Angular! v4.4.0-RC.0</h2>
>>>>> <md-toolbar _ngcontent-c0="" class="mat-toolbar mat-primary" color="primary" role="toolbar" ng-reflect-color="primary">
<div class="mat-toolbar-layout">
>>>>> <md-toolbar-row class="mat-toolbar-row">
<span _ngcontent-c0=""><md-icon _ngcontent-c0="" class="mat-icon material-icons" role="img" aria-hidden="true">mood</md-icon></span>
<span _ngcontent-c0="">Yay, Material in Angular 2!</span>
<button _ngcontent-c0="" class="mat-icon-button" md-icon-button=""><span class="mat-button-wrapper">
<md-icon _ngcontent-c0="" class="mat-icon material-icons" role="img" aria-hidden="true">more_vert</md-icon>
</span>
<div class="mat-button-ripple mat-ripple mat-button-ripple-round" md-ripple="" ng-reflect-trigger="[object HTMLButtonElement]" ng-reflect-centered="true" ng-reflect-disabled="false"></div>
<div class="mat-button-focus-overlay"></div>
</button>
</md-toolbar-row>
</div>
</md-toolbar>
</div>
</my-app>
</body>
</html>
One of the Angular features is View Encapsulation which basically means that you can define styles scoped only to a specific component without affecting any other components.
By default styles are scoped only for the component they are referenced in, but you can choose to override that to make them available globally by setting your components encapsulation to None.
E.g.
import { Component, ViewEncapsulation } from '#angular/core';
#Component({
selector: 'component-that-shares-styles',
templateUrl: './component-that-shares-styles.component.html',
styleUrls: ['./component-that-shares-styles.component.scss'],
encapsulation: ViewEncapsulation.None // <-- Set encapsulation here
})
*Note that you will need to import ViewEncapsulation from #angular/core
Okay, with help from #Steveland83 and #bryon60, I came to a definite answer. The Material Design people are aware of this problem. They have made a writeup.
https://github.com/angular/material2/blob/master/guides/customizing-component-styles.md
Here's their summary:
Styling other components
If your component has view encapsulation turned on (default), your component styles will only
affect the top level children in your template. HTML elements belonging to child components cannot
be targeted by your component styles unless you do one of the following:
Add the overriding style to you global stylesheet. Scope the selectors so that it only affects
the specific elements you need it to.
Turn view encapsulation off on your component. If you do this, be sure to scope your styles
appropriately, or else you may end up incidentally targeting other components elswhere in your
application.
Use a deprecated shadow-piercing descendant combinator to force styles to apply to all the child
elements. Read more about this deprecated solution in the
Angular documentation.
I don't want to use global css, or a deprecated solution. I guess I will style with classes, and not elements. If someone has a better idea, tell me!

Resources