In Angular 2+, we have #component directive where we can pass element-selector, css file, html template file,.. We do it by the following snippet.
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
In Angular 2+, CSS styles are local to that HomeComponent element alone. So, I can add different styles to different components without affecting each other.
AngularLayout.html
<section>
<app-home></app-home>
<app-about></app-about>
<app-contact></app-contact>
</section>
For ReactJs, I tried to add styles to different components like,
LayoutHome.js
import React, { Component } from 'react';
import './LayoutHome.css';
class LayoutHome extends Component {
render() { return <span>home</span>; }
}
export default LayoutHome;
LayoutAbout.js
import React, { Component } from 'react';
import './LayoutAbout.css';
class LayoutAbout extends Component {
render() { return <span>about</span>; }
}
export default LayoutAbout;
ReactLayoutApp.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import LayoutHome from './components/LayoutHome';
import LayoutAbout from './components/LayoutAbout';
class App extends Component {
render() {
return (
<section>
<LayoutHome/>
<LayoutAbout />
</section>
);
}
}
export default App;
For example, let './LayoutAbout.css' be having the following
span {
color: blue;
}
'./LayoutHome.css' be having the following
span {
color: red;
}
CSS styles are getting collapsed with each other.
What could be the cleaner way of tagging CSS file to a local component in ReactJs?
You should probably just add some more CSS selectors.
For instance, your LayoutAbout.css would look like
.about span {
color: red;
}
And your LayoutHome.css
.home span {
color: blue;
}
One way to solve this problem is to be more specific in your css to avoid conflicts by giving a class or id to an outer element within your component and nesting any needed styles for that component under them like so:
LayoutAbout.js
import React, { Component } from 'react';
import './LayoutAbout.css';
class LayoutAbout extends Component {
render() {
return (
<span id="about">
about
<span>nested content</span>
</span>
);
}
}
export default LayoutAbout;
LayoutAbout.css
#about {
color: blue;
}
#about span {
color: dodgerblue;
}
Another alternative would be to take advantage of the shadow dom which will encapsulate your styles within your custom component. This ensures that the css in your component won't affect anything outside and that you'd have to be explicit to affect any elements inside the shadow dom of your custom component.
Related
I have some code that looks like this:
<section>
<div style="height: 100%; max-width: 10%; background-color: deepskyblue;">my content</div>
<router-outlet style="height: 100%; min-width: 90%; background-color: gold;"></router-outlet>
</section>
I want the div to work as a side-bar with the router-outlet taking up the remaining 90% of the space. But what ends up happening is that the content displayed from the router-outlet is pushed beneath the div rather than beside it. It also appears that no CSS is being applied to the router-outlet, as the background color doesn't change. Is there any way to get CSS to make changes to this router-outlet?
simple solution is to to just put router-outlet in a style div.
<section>
<div style="height: 100%; max-width: 10%; background-color: deepskyblue;">my content</div>
<div style="height: 100%; min-width: 90%; background-color: gold;">
<router-outlet ></router-outlet>
</div>
</section>
Short answer
Use:
:host { background: cornflowerblue; }
as the css for the hosted component, to change background of the router outlet.
Long Answer:
Angular CSS pseudo selector/modifier
You can affect the hosting component with the :host modifier. In the case that you would like to change the router oulet styling, add css to the component that will be hosted.
e.g. Change the router outlet blue when showing the page-edit component.
// This is your routing to place your page component in the outlet when
navigating to the edit/1 url.
const routes: Routes = [
{
path: 'edit/:pageId',
component: PageComponent,
}
];
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class PageEditorRoutingModule {}
// PageComponent - stub of component to be rendered in outlet.
#Component({
selector: 'app-page-editor',
templateUrl: './page-editor.component.html', //implement as desired.
styleUrls: ['./page-editor.component.scss']
})
export class PageEditComponent {
// Your implementation
}
// Put this in your page-editor.component.scss to change the router outlet background blue
:host{
background: cornflowerblue;
}
I'm building a library and I have a <my-card> component. It's a component that will often have a (click) handler on it.
What I'm looking to do is to add cursor: pointer automatically when the component has (click) attached to it.
So for example, <my-card> would have the default cursor, and <my-card (click)="onClick()> would apply cursor: pointer to the component element.
Any clean way of doing this?
If you're able to change (click) to click then you could do this using CSS.
HTML:
<my-card>Look at me</my-card>
<my-card click="onClick()">Click me</my-card>
CSS:
my-card {
border-radius: 3px;
display: inline-block;
padding: 5px;
}
[click] {
background-color: red;
color: white;
cursor: pointer;
}
The [click] part in the CSS references an attribute of an element. So, this will target any element you use with the click attribute. If you only want to target any <my-card> element with the click attribute then you would change your CSS to my-card[click].
Here's a fiddle for you to reference: https://jsfiddle.net/8w9Lqxr4/1/
The Angular way to do this is to use a directive, take a look at this example:
import { HostBinding, Directive } from '#angular/core'
#Directive({
selector: '[myClick]'
})
class MyClickDirective {
#HostBinding('class.mousepointer') private isClick: boolean;
constructor(private el: ElementRef,
private renderer: Renderer) {
}
#HostListener('click') onMyElemClicked() {
this.isClick =!this.isClick;
}
}
I've not tested this example but this is the way you must investigate.
I am using a material-ui button and trying to override the border-radius (i.e, make it 0) through styled-components. However, it's not working.
Code:
import React from "react";
import styled from "styled-components";
import { Button } from "#material-ui/core";
const StyledButton = styled(Button)`
background-color: #d29d12;
border-radius: 0;
`;
export default function App() {
return <StyledButton>Hello</StyledButton>;
}
By default, Material-UI injects it styles at the end of the <head> element. This means that its styles will come after styles generated by styled-components and thus the Material-UI styles will win over the styled-components styles when CSS specificity is the same.
You can use the StylesProvider component with the injectFirst property to move the Material-UI styles to the beginning of the <head> and then the styled-components styles will come after it and win.
import React from "react";
import styled from "styled-components";
import Button from "#material-ui/core/Button";
import { StylesProvider } from "#material-ui/core/styles";
const StyledButton = styled(Button)`
background-color: red;
border-radius: 0;
`;
export default function App() {
return (
<StylesProvider injectFirst>
<div className="App">
<StyledButton>Hello</StyledButton>
</div>
</StylesProvider>
);
}
Related answers:
Media Queries in Material-UI Using Styled-Components
Use styled-components higher specificity syntax:
https://styled-components.com/docs/faqs#how-can-i-override-styles-with-higher-specificity
const StyledButton = styled(Button)`
&& {
background-color: red;
border-radius: 0;
}
`;
const StyledButton = styled(Button)({
'&&&': {
backgroundColor: red,
borderRadius: 0
}
)}
By adding className to StyledButton, it can override MUI button style,
<StyledButton className={'myclassName'}>Hello</styledButton>
const StyledButton = styled(Button)`
&.myclassName {
background-color: red,
border-radius: 0
}
`;
You can override the default border-radius of button by applying !important to your styled component.
const StyledButton = styled(Button)`
borderRadius: 0px !important;
`;
I was developing a login screen within angular with the within the app.component.html as such:
app.component.ts
<div class="container">
<app-login></app-login>
</div>
and css as such:
login.css
.form-group {
display: block;
margin-bottom: 15px;
}
.form-group label {
display: block;
margin: 0 0 5px 0;
}
app.component.css
.container {
display: grid;
height: 100%;
}
app-login {
width: 100%;
max-width: 274px;
place-self: center;
}
However, since I have now incorporated routing into my app, I display the login page using the <router-outlet> component, but this has ruined the CSS of the login page is it once was...
app.component.ts
<div class="container">
<router-outlet></router-outlet>
</div>
How can I change my CSS files such that I can get back the look I once had?
Here is a stackblitz to my example
Update
Solution found to the missing CSS (see below)
However now it appears is hogging much of the screen, pushing my element downward?
You need to set
encapsulation: ViewEncapsulation.None
on the AppComponent to allow styles to affect also those components which are used inside AppComponent.
import { Component, ViewEncapsulation } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ],
encapsulation: ViewEncapsulation.None
})
export class AppComponent {
name = 'Angular';
}
But it will be better to use styles on those components for which they were declared.
This is a working Stackblitz.
You were targeting <app-login> in the app.component.css file and styling it to have a fixed width and align it center. What you have to remember is that, Angular enforces emulated view encapsulation and also when you are using router, <app-login> may be changed to some random dynamic name at run time thereby making your css classes that you might have written in app.component.css ineffective.
Its always a best practice to write styles for a component in its respective CSS file rather than the root components css file.
Here is a changed Stackblitz
Here is the result:
Currently I am using Angular 5 to make an SPA.
I want to fill the entire screen with a background (not just one component) but I want different backgrounds for each page, how can I achieve this?
I have tried this code in the component.css of the concerning page (for example
home.component.css):
body {
background-color: aqua;
}
(using background-color as an example)
Using this method, I thought I could override the main body background per component but it does not seem to work, the page remains empty.
I would appreciate any help you can give me, thanks in advance.
I think your issue is that when you add
body {
background-color: aqua;
}
to your component css, Angular rewrites it to something like
body[_ngcontent-c0] {
background-color: yellow;
}
You can see it in dev tools if you check. Because of this, the style does not get attached to the body. You can use Renderer2 to change the body style for each component. For example:
import { Component, Renderer2 } from '#angular/core';
#Component({
selector: 'home',
templateUrl: './home.component.html',
styleUrls: [ './home.component.css' ]
})
export class HomeComponent {
name = 'Home';
constructor(private renderer: Renderer2) {
this.renderer.setStyle(document.body, 'background-color', 'yellow');
}
}
Similar Question: Angular2 add class to body tag
Angular documentation: https://angular.io/api/core/Renderer2
Hope this helps.
Add the following component in all the components that need background color. The color to be used can be passed in the input attribute:
import { Component, OnInit } from '#angular/core';
import { Input } from '#angular/core';
#Component({
selector: 'app-bg',
templateUrl: './bg.component.html',
styleUrls: ['./bg.component.scss']
})
export class BgComponent implements OnInit {
#Input() bgColor = 'red';
constructor() { }
ngOnInit() {
}
public getBgColor() {
return {
'background-color': this.bgColor
};
}
}
Here is the CSS bg.component.scss:
.bg {
position: fixed;
width: 100%;
height: 100%;
background-repeat: no-repeat;
background-position: center;
background-attachment: fixed;
background-size: cover;
overflow: auto;
}
And the template bg.component.html:
<div class="bg" [ngStyle]="getBgColor()"></div>
Finally in all the components that need background color, add this:
<app-bg [bgColor]="'blue'"></app-bg>