Add className attribute to dangerouslySetInnerHTML contents - css

How to specify className attribute for div which contains 'hello world':
<div dangerouslySetInnerHTML={{__html: '<div>hello world</div>'}} />
One way is to set is to outer div like so:
<div dangerouslySetInnerHTML={{__html: '<div>hello world</div>'}} className='class-name'/>
and then in css style the child:
.class-name div {
(css stuff here)
}
But I want to set className directly to the div with 'hello world'
EDIT: Adding class name to injected html does not solve the problem, for example:
let content = '<div class="class-name">hello world</div>'
<div dangerouslySetInnerHTML={{__html: content}}
does not work, because in case same content is used many times then CSS collisions occur (I am using style-loader with CSS modules on)

I came across this question after 2 years and I wanted to achieve the exact same results. I didn't find any accurate answers here but I came up with a solution thanks to #jash8506 due to the brilliant answer to this question.
We have to utilize two react hooks
useRef
useLayoutEffect
According to the documentation basically, useRef can be used to access the DOM elements in React and useLayoutEffect can be used to read layout from the DOM and synchronously re-render.
We can access the firstChildElement in the container div and add classes to it's classList
Here is how the completed code looks like
const containerRef = useRef();
useLayoutEffect(()=>{
if (containerRef.current){
containerRef.current.firstElementChild.classList.add('class-name');
}
});
return (
<div ref={elRef} dangerouslySetInnerHTML={{__html: '<div>hello world</div>'}} />
)

<div className="post-excerpt" dangerouslySetInnerHTML={{ __html: post.excerpt}}/>

Related

inline style vs className in Componet context

Hello I try to understand when it's necessary to use inline style instead className in this case. I take a long time to solve my problem of translation. At the beginning I want to translate component by using classNameand that's don't work. it's very weird because in my point of view there is no reason that's happen. So I figure there is something wrong in my code, but what... I have not yet found. So I finish trying to translate by using a inline style. Miracle, that's work fine.
My question is why ?
Work well
export function Content() {
return (
<div style={{transform: 'translateY(100px)'}}>
<Test/>
<Footer />
</div>)
}
don't work
export function Content() {
return (
<div className={container_content}>
<Test/>
<Footer />
</div>
)
}
css
.container_content {
transform: translateY(100px);
}
Nota bene :
The problem is not from the method. To use className in my jsx
must be like that:
import { container_content } from "./test.module.css";
and next
<div className={container_content}><div>
So this part of code is good, the issue seems to come from elsewhere...
What's happening is that when you use the inline style you are passing an object that includes the styling for that component. When you use the className you need to pass in a string for the class you want to use. Right now you are passing a variable name. Either of these works:
<div className={"container_content"}>
OR
<div className="container_content">
If you think about it in regular html you would do
<div class="container_content">
EDIT: Given your updated question, you should just import the css file with:
import "./test.module.css"
and then use the solution I mentioned.
inside the js file, you need to import the CSS file like this
import " css-file-dir";
and then you can Reference to the CSS classes inside your component as a string
example :
className="container_content"

How to load different .css files on different components of a react application?

I have two .jsx files that represent their respective components.
The first one is, Blog.jsx
import React from "react";
import '../assets/css/blog.css';
export const Blog = () => (
<div>
<h1>Hello Blog</h1>
</div>
)
With its respective CSS file, blog.css
div { background: #ff481f; }
and the second one is, Landing.jsx
import React from "react";
import '../assets/css/landing.css'
export const Landing = () => (
<div>
<h1>Hello Landing</h1>
</div>
)
With its respective CSS file, landing.css
div { background: #86ff2b; }
I have added routing and called instances of those two components on the App.js file which is the default file of a React application. After running the application, when navigated to components, I faced a problem that the background color is the same for both of the components (It loads landing.css only and never changes).
How can I fix that problem that each component only uses its respective .css file and loads it?
By default webpack and other build tools will compile all CSS files into one, even if css was imported in separate JSX files. So you can't use different CSS files and expect you don't affect on another part of page.
You have some options:
Use BEM for naming class names.
Use cssModules. In this case elements will have their own css class name and styles will not affect any other elements except if you use :global selector.
css-module
Using html tags as css selectors is a bad practice (because there is the behaviour you describe).
You should use only css classes or inline styles (using id's is another bad practise, id's have high priority).
div {
width: 20px;
height: 20px;
}
#id {
background: red;
}
.class {
background: green;
}
<div id="id" class="class"></div>
In case using css classes there is the same problem (when you have two similar classes). And this case is decided using css modules (set of rules of building) or you can use css-in-js (external library) which has its pros and cons. Also you can use BEM (methodology) and if your application is not big you can avoid this trouble.
css modules will add to your classes random hash and instead .my-awesome-class-name you will get .my-awesome-class-name-dew3sadf32s.
So, if you have two classes .class in the first file and .class in the second file in the end you will get two classes .class-dew23s2 and .class-dg22sf and you styles will resolve as expected.
css-in-js is a similar way except you should write your styles using javascript with some profits like including only those styles that are needed at the moment (what you are looking for right now) and several others.
You can code using pure css / scss / postcss / etc but many companies already choose between css modules and css-in-js.
BEM is just naming conventions for your class names.
And lastly - if you use inline-styles using react you should remember:
{} is constructor of object and {} returns new object on every call, it's mean if you write something like:
class MyAwesomeComponent extends Component {
render() {
return <div style={{color: "red"}}></div>;
}
}
or
class MyAwesomeComponent extends Component {
render() {
const divStyles = {color: "red"};
return <div style={divStyles}></div>;
}
}
div will re-render every time your render will call because div takes new prop.
Instead, you should define your styles (for example) in outside of your class:
const divStyles = {color: "red"};
class MyAwesomeComponent extends Component {
render() {
return <div style={divStyles}></div>;
}
}
Don't define your css using HTML tags because it will affect your entire application.
use className,id or inline styling.
like- App.css
.myApp{ color: red;}
#myApp2{ color: blue;}
App.js
import './App.css'
<div className="myApp">color changed by className</div>
<div id="myApp2">color changed by id</div>
<div style={{color:'red'}}>color changed by inline object styling</div> // inline styling
This is not the best solution if you are looking forward to improve yours css imports/loads.
However could be the best solution if you dont want to go in deep in css, resolve the problem fast and keep working with HTML tag.
You can add a div for each component, define an Id for the div and wrap the component. Afterwards in the component's css fies you are going to define all the styles starting with the #id so all the css classe or HTML tag will affect just the corresponding component.
//App render in root
ReactDOM.render(
<App />,
document.getElementById('root')
);
//App
function App(props){
return [
<Blog />, <OtherComponent />
]
}
//Blog component
function Blog(props){
return <div id="blog">
<h1>I am Blog</h1>
</div>
}
//Other component
function OtherComponent(props){
return <div id="otherComponent">
<h1>Im am other component</h1>
</div>
}
/* blog.css*/
#blog h1{
color:yellow;
}
/* otherComponent.css*/
#otherComponent h1{
color:green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Styling from separate CSS files not applied with new components

I have been trying to build a small project with React for the past few days and all went great until today. For some reason, no CSS is applied to new components! All the CSS that worked before is still up and running but if I'd add something like a div in between an already existing div, the new div will not pick up any CSS!
Example:
<div className="DivStyle"> // Styling applied!
<div className="DivStyle"> </div> // Styling completely ignored!
<div>
It is probably worth mentioning that I am still able to style the components inline.
Also, looking at the sources in Chrome, the styles are uploaded!
Here is my concrete example:
import '../styles/drawers.css';
class BottomFilterDrawer extends React.Component<IBottomFilterDrawerProps, IBottomFilterDrawerState> {
...
public render() {
return(
<Drawer
open={this.state.isOpen}
anchor="bottom"
// tslint:disable-next-line jsx-no-lambda
onClose={() => this.toggleDrawer(false)}>
<div className="BottomDrawerContainer" style={{margin: "10px"}}> // Styling for "BottomDrawerContainer" class not applied!
...
</div>
</Drawer>
);
}
}
The CSS file:
#BottomDrawerContainer {
margin: 10px;
}
I am certain that the import path is correct, Typescript wouldn't even let me run it if it weren't.
You are applying css for class not for id. So your css must be like below.
.BottomDrawerContainer {
margin: 10px;
}
if you want to apply for inner div.
.DivStyle .DivStyle {
//style for inner div
}
do not use again same id, React create error and if show any error first you solve error otherwise browser not show anything

React css layouting inner components

Imagine that I have such html code:
<header>
<div class="header__logo logo">
<img class="logo__img" ...>
<span class="logo__status"...>
</div>
</header>
Here
.logo - is class that has styles, special for logo component.
.header-logo - has styles positioning logo inside the header.
So in react inside header component I would like to have something like:
<header>
<Logo className="header__logo" />
<header/>
But I can't since react is not automaticly handle className property.
Here I see this options:
Create a div wrapper to the Logo component and add this class to wrapper. As for me it is not an elegant way because it produce a lot of unnecessary divs.
Add logic to the Logo component, that will handle className property and append all outer classes to the root div inside the component. This is also ugly, because I have to add this boilerplate logic each time I want to layout a component inside some other component.
What is the react approach for solving such problems?
Yes, you cannot provide className attribute to a react Component. If you want to provide custom class to the same component, you can provide the className as a prop to the component which is added as a className in the child component.
I believe u need to do something like this.
var Header = React.createClass({
render: function() {
return (
<header>
<Logo customClass="header__logo logo"/>
</header>
);
}
});
var Logo = React.createClass({
render: function() {
return (
<div className={this.props.customClass}>
<img className="logo__img" />
<span className="logo__status" ></span>
</div>
);
}
});
Let me know if this is what you wanted to know or something else.

How to add multiple style attributes to a react element? [duplicate]

This question already has answers here:
How to combine multiple inline style objects?
(20 answers)
Closed 6 years ago.
How would I go about adding multiple style attributes to my React element?
Some of the components in my app are using the same styles throughout with minor variations in styles. I am trying to accomplish something along the lines of <div style={this.styles.mainStyle, this.styles.variationInStyle}></div>.
These styles are in a file called styles.js hence the this.styles.x. It works with only one style in it. The closest I found to this solution was in a Reddit Post. The solution was <div style={$.extend({}, style1, style2)}></div> but of course, it doesn't work nor does the variation <div style={style1, style2)}></div>.
Any insight would be greatly appreciated! I will also be posting in Reddit and the Reactiflux Discord group if the answer should come from either source, I will post the answer here.
style is just an Object, with css value turn to camelCase, so you could use any way to merge two object, and it should work.
ES6: style={Object.assign({}, style1, style2)}
ES7: style={{...style1, ...style2}}
lodash: style={_.merge({}, style1, style2)}
as #michealmuxica said, the style prop is is just a JS object with camel casing for the keys. So you can set your style on your components as such:
<MyComponent style={{height:"100%", marginLeft:"70%"}} />
I prefer to create another JS file per component to contain the style objects, then import them into the component's file. I feel like this keeps the code more clean and modular:
//in MyComponentStyles.js
var style = {
base:{
height:"100%",
width: "100%",
marginLeft: "auto",
marginRight: "auto"
},
//...other styles...
};
export default styles;
//in MyComponent.js
import {default as MyComponentStyles} from "./<path to styles>/MyComponentStyles.js;
var App = React.createClass({
render: function() {
return ( <MyComponent style={MyComponentStyles.base} /> );
}
});

Resources