Angular 1.5 component css scoping with nested components - css

I'm trying to use angular 1.5 components to create a button group.
<button-group size="default">
<my-button>Button 1</my-button>
<my-button>Button 2</my-button>
</button-group>
But, it compiles to something like:
<div class="btn-group" ng-transclude>
<my-button class="ng-scope ng-isolate-scope>
<button class="btn>Button 1</button>
</my-button>
<my-button class="ng-scope ng-isolate-scope>
<button class="btn>Button 1</button>
</my-button>
</div>
So now my CSS scoping is all messed up:
.btn-group > .btn:not(:first-child) {
background: red; //<- doesnt work
}
Basic example:
const buttonGroup = {
bindings: {},
transclude: true,
template: myButtonGroupTemplate
};

You can add classes to your component
Something like that:
html
<button-group size="default">
<my-button class="awesome-class-btn">Button 1</my-button>
<my-button class="awesome-class-btn">Button 2</my-button>
</button-group>
css
.btn-group .awesome-class-btn > .btn:not(:first-child) {
background: red;
}

Related

With styled-components, how can I target a child class of a component?

I'm using a mui Badge component and I want to style the little circle. I have:
const BadgeStyled = styled(Badge)`
& > .muibadge-badge: {
background-color: #d3d4d7;
width: 15px;
height: 15px;
}
`;
The generated HTML is:
<span class="MuiBadge-root BaseBadge-root css-1o9b3gb-MuiBadge-root">
... some stuff
<span class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"></span>
</button>
<div class="MuiAvatar-root MuiAvatar-circular MuiAvatar-colorDefault css-f84387-MuiAvatar-root">
<span class="MuiTypography-root MuiTypography-eyebrowSmall css-1bcwatu-MuiTypography-root">J</span>
</div>
<span class="MuiBadge-badge MuiBadge-standard MuiBadge-anchorOriginTopRight MuiBadge-anchorOriginTopRightRectangular MuiBadge-overlapRectangular MuiBadge-colorPrimary BaseBadge-badge css-1es1533-MuiBadge-badge">4</span>
</span>
So I have MuiBadge-badge in the generated HTML, but my style doesn't seem to apply. Any tips would be greatly appreciated! Thanks!
Your syntax is wrong, have a look at this working codesandbox
Here is how you can style the Badge component
const BadgeStyled = styled(Badge)({
"& .MuiBadge-badge": {
backgroundColor: "#d3d4d7",
width: '15px',
height: '15px',
}
});

How to change button colour on click?

I want to change my button colour on click using angular and css as I am very new to it.
.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'title';
}
.html
<mat-sidenav color="primary" #sidenav fxLayout="column" mode="over" opened="false" fxHide.gt-sm="true">
<div fxLayout="column">
<button mat-button style="text-align:left" routerLink="butn1" >Attend</button>
<button mat-button style="text-align:left" routerLink="butn2" >Host</button>
<button mat-button style="text-align:left" routerLink="contact" >Contact</button>
<button mat-button style="text-align:left" routerLink="login" >Login</button>
</div>
</mat-sidenav>
You can add this in the html button tag
‘<button [class.mycolorclass]=’hasClicked’ (click)=’hasClicked=true’
The logic in the click directive can be moved into a method in the typescript class if you prefer that
I'm not familiar with angular, but CSS :active should manage to do this:
button {
line-height: 30px;
height: 30px;
font-size: 15px;
color: red;
border: 1px solid black;
background-color: #eee;
color: black;
}
button:active {
color: red;
border-color: red;
}
<button>Click me!</button>
on button click set variable true/false as per your requirement
buttonClicked=false;
onButtonClick(){
this.buttonClicked=true;
}
and give condition in HTML like this
<button mat-button
[ngClass]="buttonClicked? 'myClassHighlighted' : 'none'"
style="text-align:left" routerLink="attend" >Attend</button>
and in css add classes like
.myClassHighlighted{
//your styles here
}
.none{
//your styles here
}
Use ngClass in your buttons to give 'em conditional classes based on a flag which is set true only when you click on that button so I guess you will need ngClick as well, well I don't know about the version of Angular that you are using right now cuz you didn't mention that but now you know you will need ngClass and ngClick for sure and your code might look like sth like this:
<button mat-button style="text-align:left" [ngClass]="{'button--clicked': clicked}" routerLink="attend" (click)="clicked=!clicked" >Attend</button>
.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'title';
buttons = [
{ title: 'Attend', link: 'butn1', active: false },
{ title: 'Host', link: 'butn2', active: false },
{ title: 'Contact', link: 'contact', active: false },
{ title: 'Login', link: 'login', active: false },
]
toggleColor(button) {
button.active = !button.active;
}
}
.html
<mat-sidenav color="primary" #sidenav fxLayout="column" mode="over" opened="false" fxHide.gt-sm="true">
<div fxLayout="column">
<button
mat-button
*ngFor="let button of buttons"
[color]="button.active ? 'accent' : 'primary'"
style="text-align:left"
[routerLink]="button.link"
(click)="toggleColor(button)">
{{ button.title }}
</button>
</div>
Need to add css class for button based on click css value change

ngClass one conditional and other from variable

I have the following data structure:
this.filters = [
{
key: 'filter1',
active: true,
class: 'filter1Class'
},
{
key: 'filter2',
active: false,
class: 'filter2Class'
},
{
key: 'filter3',
active: true,
class: 'filter3Class'
}
];
And with this I want to create some icons in my html, every icon will have each own css class and it can be enabled or not depending on the active flag in the model.
My classes are quite simples, every filterNClass is just a color and the one I applied to set it enabled or nor is an opacity value:
.disabled {
opacity: 0.2;
}
.filter1Class {
color: #1993a0;
}
.filter2Class {
color: #720053;
}
.filter3Class {
color: #000055;
}
this is my html:
<div *ngFor="let filter of filters">
<mat-icon [ngClass]="filter.class"
[ngClass]="{disabled: !filter.active}">alarm_on
</mat-icon>
</div>
in this way, the second ngClass is not working, it does if I remove the first one, but I'm not able to manage both at the same time.
How can it be done?
I finally solved it by including a div:
<div *ngFor="let filter of filters">
<div [ngClass]="filter.class">
<mat-icon
[ngClass]="{disabled: !filter.active}">alarm_on
</mat-icon>
</div>
</div>
you can write so:
<div *ngFor="let filter of filters">
<mat-icon [ngClass]="{disabled: !filter.active,filter.class }">alarm_on
</mat-icon>
</div>
You will need to use object array syntax and include all checks under the same ngclass attribute as follows:
<div *ngFor="let filter of filters">
<mat-icon [ngClass]="{filter.class : true, 'disabled' : !filter.active }">alarm_on
</mat-icon>
</div>

How to change the styleurls link after pressing a button and keep it that way

I am working on an angular 2 project and am trying to include a setting themes. I have created 3 component.scss file red.component.scss, yellow.component.scss and blue.component.scss. I want to make it so that as per the user input from a button the styleURLS in the component.ts file changes with the selected color related scss file url. Is it possible and how? or are there any other effective and easy way to achieve this?
you can use property binding
my solution
//// in css file
.red {
color: red;
}
.yellow {
color: yellow;
}
.blue {
color: blue;
}
.green {
color: green;
}
/// in html
<div [class.red]="isRed" [class.yellow]="isYellow" [class.blue]="isblue" [class.green]="isGreen" ></div>
//// and isRed, isBlue ... are boolean in ts file
You can include multiple stylesheets in styleUrls property.
You cannot add dynamic property in styleUrl.
You can achieve this by many ways.
Style Binding
<div [ngStyle]="setStyle()">
LOREM IPSUM
</div>
<button (click)="changeColorCode('#9FD068')">#9FD068 </button>
<button (click)="changeColorCode('#0C66A1')">#0C66A1 </button>
<button (click)="changeColorCode('#fff000')">#fff000 </button>
selectedColor: any = '';
changeColorCode(colorCode: string) {
this.selectedColor = colorCode;
}
setStyle() {
return {
'color': this.selectedColor
};
}
Class Binding
<div [ngClass]="setClass()" #divRef>
LOREM IPSUM
</div>
<button (click)="changeClass('red')">Red </button>
<button (click)="changeClass('green')">Green </button>
<button (click)="changeClass('blue')">Blue </button>
selectedClass: string = '';
changeClass(className: string) {
this.selectedClass = className;
}
setClass() {
return [this.selectedClass];
}
changeColorCode(colorCode: string) {
this.selectedColor = colorCode;
}

In vue.js component, how to use props in css?

I'm new to vue.js. Here is my problem:
In a *.vue file like this:
<template>
<div id="a">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['color']
}
</script>
<style scoped>
#a {
background-color: ?
}
<style>
How can I use the props color in background-color: (where is a ? now).
Thanks.
You actually can!
You should define the CSS variables in a Computed Property, then call the computed property as a style attribute to the element that will require the CSS variable, and finally you may use the variable within the tags at the bottom of your document.
new Vue({
el: '#app',
data: function() {
return {
baseFontSize: 1,
bgHoverColor: "#00cc00",
hoverContent: "Hovering!"
}
},
computed: {
cssProps() {
return {
'--hover-font-size': (this.baseFontSize * 2) + "em",
'--bg-hover-color': this.bgHoverColor,
'--hover-content': JSON.stringify(this.hoverContent)
}
}
}
})
div {
margin: 1em;
}
div.test:hover {
background-color: var(--bg-hover-color);
font-size: var(--hover-font-size);
}
div.test:hover::after {
margin-left: 1em;
content: var(--hover-content);
}
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app" :style="cssProps">
<div>Hover text: <input type="text" v-model="hoverContent"></div>
<div>Hover color: <input type="color" v-model="bgHoverColor"></div>
<div class="test">Hover over me</div>
</div>
Or have a look here: https://codepen.io/richardtallent/pen/yvpERW/
And here: https://github.com/vuejs/vue/issues/7346
You don't. You use a computed property and there you use the prop to return the style of the div, like this:
<template>
<div id="a" :style="style" #mouseover="mouseOver()">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['color'],
computed: {
style () {
return 'background-color: ' + this.hovering ? this.color: 'red';
}
},
data () {
return {
hovering: false
}
},
methods: {
mouseOver () {
this.hovering = !this.hovering
}
}
}
</script>
<style scoped>
<style>
As we are in 2020 now, I suggest using this trick with a css function called var
<template>
<div id="a" :style="cssVars"></div>
</template>
<script>
export default {
props: ['color'],
computed: {
cssVars () {
return{
/* variables you want to pass to css */
'--color': this.color,
}
}
}
<script>
<style scoped>
#a{
background-color: var(--color);
}
</style>
This method is very useful because it allows you to update the passed values through css later on (for example when you apply hover event).
credit
I know we're talking vue 2 here, but in case anyone from vue 3 lands in this question (like I did), vue 3 introduced a much cleaner way to do this:
<template>
<div id="a">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['color']
}
</script>
<style scoped>
#a {
background-color: v-bind(color);
}
<style>
What Vue actually does behind the scenes is the same "introducing css variables through component's style process", but it sure looks much better on the eyes now.
Documentation source: https://v3.vuejs.org/api/sfc-style.html#state-driven-dynamic-css
Why not just use :style prop in this way:
<template>
<div :style="{ backgroundColor: color }">
</template>
<script>
export default {
props: {
color: {
type: String,
default: ''
}
}
}
</script>
Make sure you define css properties in camelCase style.
If you need css that can't be applied by a style attribute like pseudo classes or media queries, what I do is the following:
Create a globally available style component when initializing Vue (you need it as otherwise you run into linting issues). It creates a style tag that simply renders the content in the slot:
I would only use this if you really need both dynamic values in your css and css features that can't be applied to a style attribute.
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
Vue.component('v-style', {
render: function(createElement) {
return createElement('style', this.$slots.default)
}
})
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
Then use it at the top of your template like this and you get the full JavaScript scope of your component and the full css syntax combined:
<template>
<v-style>
#media screen and (max-width: 820px) {
.gwi-text-media-{{ this.id }} {
background-image: url({{ mobileThumb }});
}
}
</v-style>
</template>
It seems a bit hacky to me, but it does it's job and I would rather go like this in some cases than having to add additional JS for mouse-over or resize events that have a big potential to slow down your application performance.
Vue 3 added new way of binding styles, so now you can easily bind your props to css properties.
Read source:
https://learnvue.co/2021/05/how-to-use-vue-css-variables-reactive-styles-rfc/
<template>
<div>
<div class="text">hello</div>
</div>
</template>
<script>
export default {
data() {
return {
color: 'red',
}
}
}
</script>
<style>
.text {
color: v-bind(color);
}
</style>
You could utilise the CSS var(--foo-bar) function. It is also useful if you are trying to pass an asset that has its own dynamic path, like Shopify does.
This method also works for styling the :before and :after elements as they refer back to the style applied on the owner element.
Using the original post example for passing a colour:
<template>
<div
id="a"
:style="{ '--colour': color }">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['color']
}
</script>
<style scoped>
#a {
background-color: var(--colour);
}
</style>
Using the original post example for passing an URL:
<template>
<div
id="a"
:style="{ '--image-url': 'url(' + image + ')' }">
</div>
</template>
<script>
export default {
name: 'SquareButton',
props: ['image']
}
</script>
<style scoped>
#a {
background-url: var(--image-url);
}
</style>
Source

Resources