how to style react child component under standard HTML element? - css

I'm learning react and while doing projects came across this situation.
I've below scenario where 2 react child components are under standard HTML element
In case I need to target and style individual react child element how to do it ?
In case of normal HTML elements; I would have assigned className to each individual child HTML element and styled them.
But this approach doesn't work with react component, please suggest how to handle it ?

You can style you react component easily with adding className attribute to them and then in a seprate css file write some stylesheets to style them.
1-first import your css file in you components (e.g. App.jsx or App.js ):
import './index.css'
2- give a className to each components:
<div className="testClass" > </div>
your css file is something like this:
.testClass {
width : 100px;
height : 100px;
background-color: red;
}

<div className='parent'>
<h1 className='one'>
Text 1
</h1>
<p className='two'>
Text 2
</p>
<div
className='three'
>
<div className='three-one' >
one
</div>
<div className='three-two' >
trwo
</div>
</div>
</div>
Now you can add a file as 'style.css' and import it in this component as
import '.style.css';
and add styling inside style.css as you do in normal HTML/CSS. Or you can add styling as
<div style={{ backgroundColor: '#000', border: '1px solid #eee' }}> one </div>
Or you can use CSS modules / styled-components. There are many ways to add styling.
How to add styling in React

Related

Can I add a seperate className for a css file

I am using react and I was wondering, I am used to add styling directly in the ClassName.
Let's assume I want to create a seperate css file later to modify the design of the website. For instance this div has a className with the style. What if I want to add a background gradient to it. how do I achieve this from a seperate file. if I add another className it will not work.
<div className="modal-body my-2">
You will probably just have to import your css file with the styles you want to add, then add that same class name in the className tag as you would normally do, it should work without problems
import 'otherStyle.css'
.otherStyles {
//Styles here
}
<div class="currentStyle OtherStyle">
Here you go with a solution
.otherClass {
background: #eee;
}
import CSS from "./path to CSS file";
<div className={`modal-body my-2 ${CSS.otherClass}`}>
import './style1.css';
import './style2.css';
return(
<div className="first second">
</div>
)
//style1.css
.first{
width : 100%;
}
//style2.css
.second{
color : black;
}

Angular 7: Why class style is not applied to DOM component?

I have a component billing that includes ngb-tabset component of Ng Bootstrap.
ngb-tabset has the following DOM element:
<ngb-tabset _ngcontent-c3="" class="content">
<!-- Tabset links-->
<div class="tab-content">
<div _ngcontent-c3="">
<!-- Content -->
</div>
</div>
</ngb-tabset>
<div class="tab-content"> is dynamically displayed according the selected tab.
In my billing.component.scss, the following snippet doesn't work:
.tab-content {
padding-right: 120px;
}
The CSS code is correctly compiled and, normally, seen by navigator but not effect on the item.
But if I apply it on the item outside the component, the code works correctly.
Any idea about this strange behavior?
Method 1 - Set style classes in the tab content template
View encapsulation isolates the CSS styling of each component, preventing the parent component CSS from affecting the child components. The preferred solution in the present case would be to set the style classes in the tab content template definition. Here is an example:
<ngb-tabset>
<ngb-tab title="Simple">
<ng-template ngbTabContent>
<div class="my-style-1">
<p>Some content</p>
</div>
</ng-template>
</ngb-tab>
...
</ngb-tabset>
.my-style-1 {
padding-right: 120px;
color: magenta;
font-style: italic;
}
See this stackblitz for a demo.
Method 2 - Use the ::ng-deep pseudo-class selector
Another method is to use the ::ng-deep shadow-piercing descendant combinator to style the content of the NgbTabset child component:
::ng-deep .tab-content {
padding-right: 120px;
}
See this stackblitz for a demo.
Method 3 - Turn off view encapsulation
Alternatively, you could turn off the view encapsulation of the parent component:
import { Component, ViewEncapsulation } from '#angular/core';
#Component({
...
encapsulation: ViewEncapsulation.None
})
See this stackblitz for a demo.
Angular uses shadow DOM. That means it keeps DOM logics separate from other elements. Components have scoped styles of their own. They are encapsulated in a way that the styles should not effect globally. So, if you want to change ngb-tabset's style you have to come out of its scope. That's why you need to use ViewEncapsulation.None.
In #Component decorator use ViewEncapsulation.None
#Component({
selector: ....,
encapsulation: ViewEncapsulation.None,
styles: [...])}
And, you can use ng-deep also. But you should not use ng-deep because it will be deprecated. See here- https://angular.io/guide/component-styles#deprecated-deep--and-ng-deep

internal CSS styling in React at the top of code

I'm trying to style a component in my React application, but I do not want to create an external stylesheet because it's a small project. How can I style this image component without using an external stylesheet?
return (
<div>
<Image>
<div>
<img src='./resources/image.png alt='image'>
</div>
</Image>
</div>
);
I've found resources online for using inline styling on a specific element, but I want to make my code clean by putting it at the top of the component like using a style tag at the top of an HTML file. I haven't been able to find anything that resembles this in React.
For inline styles you can define a style object, either at the top of the file, or in your render method, and then refer to it:
var myStyle = { margin: 10 }
return (
<div>
<Image>
<div>
<img style={myStyle} src='./resources/image.png alt='image'>
</div>
</Image>
</div>
)
More info in the docs: https://reactjs.org/docs/dom-elements.html#style
Internal CSS styling in JSX is very similar to how it's done in HTML. The only difference is that you need to declare the style names as variables because they are treated like JS objects. With this in mind, you also need to end each property with a comma instead of a semicolon, and the last property should have no punctuation at the end. Using this approach, you should also use style={} instead of className={}. You can read more about JSX styling here.
const myStyle = {
width: '300px',
height: '300px',
border: '2px solid black'
}
const Image = () => {
return (
<div>
<img style={myStyle} src='./resources/image.png alt='image'>
</div>
);
}
You can do something like this:
const Image = styled.div`
background: #1d9ac2;
img {
border: 1px solid red;
}
`;
There are several solutions for this, and a big debate about which one is "the best".
I don't know which one is the best, but I can tell you which one I use:
Styled components (https://www.styled-components.com/)
With this, you would define an object like this
let styled = require('styled-components');
// Or for fancy people
import styled from 'styled-components';
const Image = styled.div`
background-color: red;
/* You can even put classes or selectors in here that will match the sub-components */
.some_class_used_inside { color: black; }
img { width: 100px }
`
and use it like this
return (
<div>
<Image> {/* This will be the `<div>` with `background-color: red` */}
<div className="some_class_used_inside"> {/* This will now have `color: black` applied */
<img src='./resources/image.png alt='image'> {/* This will have `width: 100px` applied to it */}
</div>
</Image>
</div>
);
Ofcourse, there are many other libraries to do it, and everyone will have to find their own favorite I guess :)

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!

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()};
}

Resources