How to create a className from dynamic properties in reactjs - css

Hi i have this myStyle object - but i have to apply class on h1 . How can i convert this myStyle into class.I tried this but its not working. its showing object when i inspect the elements.Height i am calculating dynamically based on the device height
class MyHeader extends React.Component {
deviceHeight=()=>document.height+"px";
render() {
const mystyle = {
height: deviceHeight
backgroundColor: "DodgerBlue", };
return (
<div>
<h1 className={mystyle}>Hello Style!</h1>
<p>Add a little style!</p>
</div>
);
}
}

you can't do this if you want to apply dynamic css then you can do it like this way. Add below tag in your jsx before the class tag you are trying it will genrate dynamic css in your component code and you can apply it.
<style>
{`\
.mystyle{\
height:${deviceHeight}px;\
background-color:'red'\
}\
`}
</style>

Change className to style.
Ref: https://reactjs.org/docs/dom-elements.html#style

Here you are not giving the dynamic value for height so simple thing is to create one class write CSS for that class and add class to h1 tag
///CSS Code ///
.heading{
height: '20px';
backgroundColor: "DodgerBlue";
}
/// React code
class MyHeader extends React.Component {
render() {
return (
<div>
<h1 className='heading'>Hello Style!</h1>
<p>Add a little style!</p>
</div>
);
}
}

try this code: style={mystyle}
if you want inject props to css codes you should use styled-component library: https://styled-components.com/docs/basics#passed-props

To use className to style your property what you can do is create a different css module and put your css stylings there
For example:
Header.css
.header {
height: 100vh; //since you're using device height
background: DodgerBlue
}
Now in your component import that css file
import styles from './Header.css';
Next in your h1 tag
<h1 className={styles.header}>Hello Style!</h1>
this way you can use class name for styling.

Related

Is there a way to keep linked stylesheets localized to single components?

I have a component that relies on external stylesheets. I'm bringing the stylesheet into the component like this:
Child component
export default class Child extends Component {
render() {
return (
<div>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" />
...my code here...
</div>
);
}
}
But what's happening is this is forcing those styles onto the parent component as well.
Parent Component
export default class Parent extends Component {
render() {
return (
<div>
...code here...
<Child />
... more code here...
</div>
);
}
}
Is anyone aware of a way that I can keep that stylesheet link localized to just that child component so the styles aren't applied to the parent component as well?
Edit 2
Currently trying the shadow dom route, trying to pass down some children. Getting an error after the initial render saying Cannot read properties of undefined (reading 'children'). It does render the this.props.children initially...
import React, { Component } from 'react';
class MyComponent extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
${this.props.children}
`;
}
};
export default class Child extends Component {
render() {
return (
<div>
<script>
{!customElements.get("my-component") && customElements.define('my-component', MyComponent)}
</script>
<my-component>
<h1>Hello from shadow</h1>
</my-component>
<h1>Hello</h1>
</div>
);
}
}
You can try CSS Modules. Add :local(.className) to the class you want to use in your code which is in the font-awesome-min.css file. Then import the styles to your component. For example import styles from './font-awesome-min.css' then use the module in your code. The styles will only apply to specific element and won't affect other elements in the document. So let's say you have a class called .usericon in your css you do this in the css file.
CSS
:local(.usericon){
fill: red;
}
React Code
import styles from './font-awesome-min.css'
export default function Profile(){
return (
<i className={styles.usericon}>User Icon</i>
)
}
One way to truly isolate your CSS is with Web Components. Web Components are a browser API that allows defining custom elements with their own "shadow DOM". If a style is defined inside the shadow DOM, it is truly sandboxed with no styles going in or out. You can use whatever selectors you like:
class FancyBox extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
.fancy-box {
border: solid 3px darkblue;
background: dodgerblue;
padding: 10px;
color: white;
font: 16px sans-serif;
}
</style>
<div class="fancy-box">
<slot></slot>
</div>
`;
}
}
customElements.define('fancy-box', FancyBox);
.fancy-box {
border: dashed 3px darkred !important;
background: crimson !important;
padding: 10px !important;
color: white !important;
font: 16px sans-serif;
}
<fancy-box>Safe in my shadow DOM</fancy-box>
<div class="fancy-box">I am affected by outside stylesheets</div>
Note the use of <slot></slot>. This is a placeholder for child elements of the component.
If I wanted to use this custom element from React, it needs to be defined separately so it only runs once.
class FancyBox extends HTMLElement { /*...*/ };
customElements.define('fancy-box', FancyBox);
class ReactFancyBox extends React.Component {
constructor() {
super();
this.state = { value: 'hello world!' }
}
handleChange(e) {
this.setState({ value: e.currentTarget.value });
}
render() {
return (
<div>
<fancy-box>
<strong>{this.state.value}</strong>
</fancy-box>
<input value={this.state.value} onChange={e => this.handleChange(e)} />
</div>
);
}
};

React - applying css via className to imported Component

I'm new to react and I have a quick question about styling imported components. I made a basic Title component that simply outputs the props passed. My Title.js file:
import React from 'react';
import '../App.css'
class Title extends React.Component{
render(){
return <h1>{this.props.prop}</h1>
}
}
export default Title
I'm using it in my App.js file and trying to style it via a className
import React from 'react';
import Title from './components/Title'
import './App.css';
function App() {
return (
<Title className = 'title' prop = 'Title!'/>
);
}
export default App;
my css:
.title{
background-color: rgba(255, 0, 0, 0.2);
text-align: center;
margin-top: 100px;
padding: 20px;
border: solid black;
}
This does not works, even if I apply an inline style to the Title tag. However it does works when I apply the className to the h1 tag within the Title.js file. Is it because everything written within the Title tag is just passed as a prop? If that's true how are third-party library components styled? Any help is much appreciated!
In order for this to work the way you want to, you need to pass the className prop form your Title component to the h1 inside it:
class Title extends React.Component{
render(){
return <h1 className={this.props.className}>{this.props.prop}</h1>
}
}

I cannot center the Button component in Material-UI using Styled Components

I am quite new to Material UI # next, and I like the fact that it supports Styled Components.
However, I am struggling in aligning the Button component to the center through Styled Components. I only manage to align it by using the styles technique such as this:
const styles = {
container: {
textAlign: "center"
}
};
class Landing extends Component {
render() {
return (
...
<div style={styles.container}>
<Button variant="raised" color="primary">
I am a button
</Button>
</div>
);
}
}
This is something that I like to avoid, and instead use the Styled Components such as:
const Container = styled.div`
text-align: "center";
`;
However, for some reason it is not working although they look exactly identical. Can someone explain whether text-align and textAlign are pointing to the same CSS property?
It works using styled component here is the code
import React from 'react';
import Button from "react-bootstrap/es/Button";
import styled from 'styled-components';
const Container = styled.div`
text-align: center;
`;
class Landing extends React.Component {
render() {
return (
<Container>
<div>
<Button color="primary">
I am a button
</Button>
</div>
</Container>
)};
};
You have to wrap the styled component which you have taken. Here I've taken container and then inside the container, I've added the needed CSS.
For more information and usage about the styled component, you can visit this URL - https://www.styled-components.com/docs/basics
Thanks

PrimeReact and styled-component

I can't seem to style a PrimeReact component with styled-component.
Given the below code to render an InputText, my intention is to change the width of it. But it doesn't work.
import styled from "styled-components";
import {InputText} from 'primereact/components/inputtext/InputText';
class Component extends React.Component {
render() {
return (
<InputText/>
)
}
const ComponentView = styled(Component)`
.ui-inputtext {
width: 1000px;
}
`;
styled-components generates a className that should be passed to the component.
import styled from "styled-components";
import {InputText} from 'primereact/components/inputtext/InputText';
class Component extends React.Component {
render() {
return (
<InputText className={this.props.className} /> <---- here
)
}
const ComponentView = styled(Component)`
.ui-inputtext {
width: 1000px;
}
`;
If InputText doesn't accept className, you can simply wrap it with another component:
import styled from "styled-components";
import {InputText} from 'primereact/components/inputtext/InputText';
class Component extends React.Component {
render() {
return (
<div className={this.props.className}> <---- here
<InputText />
</div>
)
}
const ComponentView = styled(Component)`
.ui-inputtext {
width: 1000px;
}
`;
PrimeReact has a lot of styles applied with a separate sass stylesheet, often combining multiple classnames and html tags.
To get your styles to win, you need more CSS specificity.
A solution is to use a nested selector, like:
const ComponentView = styled(Component)`
&&& {
width: 1000px;
}`
This will generate 3 identical classnames and is recommended by the Styled Components docs. More classname specificity needed? Use more &s.
Or you could put in a !important. I've seen this around.
Or edit their sass file.

How do you add multiple browser specific values into a CSS style in React?

This is mainly to define browser specific values like this one for a given CSS property:
<div style="cursor: -moz-grab; cursor: -webkit-grab; cursor: grab;">Grab me!</div>
If I wrap it into object like this:
<div style={{
cursor: "-moz-grab",
cursor: "-webkit-grab",
cursor: "grab"
}}>Grab me!</div>
then you duplicate keys in an object (would fail in strict mode and would overwrite otherwise). And simply putting all values into single string doesn't seem to work either.
Figuring out browser with JS and then applying right value seems to be too much work.. Or is there a different approach to do this? Any ideas?
If you want to use inline styles and also get vendor prefixing, you can use a library like Radium to abstract the vendor prefixing for you.
By adding a #Radium decorator to your component, Radium will hook into the styles you pass to the component and automatically manage and prefix them.
var Radium = require('radium');
var React = require('react');
#Radium
class Grabby extends React.Component {
render() {
return (
<div style={style}>
{this.props.children}
</div>
);
}
}
var style = {
cursor: "grab" // this will get autoprefixed for you!
};
The best you could do is to create a css class with the cursor attribute, and add it to your component
.container {
height: 10px;
width: 10px;
}
.grab {
cursor: -moz-grab,
cursor: -webkit-grab,
cursor: grab,
}
Then in your react component:
var isGrabEnabled = true;
<div className={['container', (isGrabEnabled ? 'grab' : '')]}>Grab me!</div>

Resources