Dealing with stylesheet order and css module className overrides - reactjs

I have a component that has its own style, e.g.
.prompt { color: red; }
It's declared as so:
import cn from 'classnames';
import styles from './styles.css';
const MyComponent = ({className}) => {
return (
<div className={cn(styles.prompt, className)}>
test
</div>
);
}
In my specific use case, the stylesheet for the className being passed in is actually defined and added to the head BEFORE the stylesheet from the module, so the module's css always overrides the style of the className being passed in. Something like:
Notice the background: yellow from second class is being overridden by the background from the module's own class.
Other than using !important in the secondary class, how can I work around this?

Based on Mr. Lister's response, I re-evaluated my existing knowledge of specificity and came up with the following solution in the higher level css:
// in app.scss
.offline.prompt {
color: red;
}
// in app.tsx
const classes = cn(Styles.offline, Styles.prompt);
return <OfflineApp className={classes}>...</OfflineApp>;
Essentially, I just tag the module markup with another sibling class to increase specificity and target the necessary properties using that. WAY better than abusing !important.

Related

React className naming convention

As we know, we are supposed to use lowercase and dash for css class name in raw html (e.g. <div class="lower-case-dash" />). What about in React JSX?
For html elements and other React components, what is the naming convention for css class name? camelcase or dash?
<div className="divClass">Something</div>
<div className="DivClass">Something</div>
<div className="div-class">Something</div>
<SomeComponent className="SomeComponent" />
<SomeComponent className="some-component" />
TLDR: PascalCase and Block__Element--Modifier
Check out the official doc of create-react-app. It provides a minimum example of creating a custom component. The js and css filenames as well as the className are all following PascalCase.
// Button.css
.Button {
padding: 20px;
}
// Button.js
import React, { Component } from 'react';
import './Button.css'; // Tell Webpack that Button.js uses these styles
class Button extends Component {
render() {
// You can use them as regular CSS styles
return <div className="Button" />;
}
}
Besides, the doc also provides an external link, which describes BEM naming conventions (link) for elements inside the component.
// MyComponent.js
require('./MyComponent.less');
import { Component } from 'react';
export default class MyComponent extends Component {
render() {
return (
<div className="MyComponent">
<div className="MyComponent__Icon">Icon</div>
...
</div>
);
}
}
// MyComponent.less
.MyComponent__Icon {
background-image: url('icon.svg');
background-position: 0 50%;
background-size: fit;
height: 50px;
}
Some of the naming conventions (Recommended) are:
Component Name
Component name should be in PascalCase.
For example, MyComponent, MyChildComponent etc.
Attributes
Attribute name's should be camelCase.
For example, className, onClick etc.
Inline styles
Inline styles should be camelCase.
For example, <div style={{color: 'blue', backgroundColor: 'black', border: '1px solid', borderRadius:'4px'}}>My Text</div> etc.
Variable Names
Variable names can be camelCase (Good practice), PascalCase (Avoidable), lowercase, can also contain number and special characters.
For example, state = {variable:true, Variable:true, variableName:true} etc.
Class Name
Class names can be anything camelCase, PascalCase, lowercase, can also contain number and special characters, because after all it is a string.
For example, className="myClass MyClass My_Class my-class" etc.
That totally depends on your (and your team's) preference. React (nor plain HTML) doesn't restrict you from using lower, dashed or camel-cased class names.
However, I would recommend that you choose an existing CSS convention like BEM. This will make sure that class names stay consistent throughout the process (if followed correctly).
We've chosen for a custom convention in our projects to match our components class names with the component name.
Example:
const NavBar = () => (
<header className="NavBar NavBar--fixed">
<div className="NavBar-brand"></div>
</header>
);
As you can see, this looks a lot like BEM, except for the pascal-cased block, single dash separator for elements and a double dash separator for block modifiers.

custom grid component react, background image

I have a component in react, a custom grid that I want to use twice in the same page but with different background images, I would like to pass this images with props form the root component, what is the right way to do it?
and it is a good idea to do this at all?
this code I wrote is working but i'm not sure is the right thing to do
`import React, { Component } from 'react';
import InnerTextGridCategory from './InnerTextGridCategory';
import InnerTextGridTitle from './InnerTextGridTitle';
import PlayLink from './PlayLink';
class CustomGrid extends Component {
render() {
const styles = {
img1: {
background: `linear-gradient(61deg, #000000 0%, rgba(0, 0,
0, 0) 70%),url(${this.props.img1})`,
backgroundSize: `cover`,
backgroundPosition: `center`,
}
};
return (
<div className={`${this.props.gridSize}`}>
<div className={`${this.props.gridSize} item1`} style=
{styles.img1}>
<div className="wrapper-text-grid">`
If can't hardcode these image URLs in CSS but you a going to get them from props I don't see a better way to do it.
Here what React docs say:
Some examples in the documentation use style for convenience, but using the style attribute as the primary means of styling elements is generally not recommended. In most cases, className should be used to reference classes defined in an external CSS stylesheet. style is most often used in React applications to add dynamically-computed styles at render time.
https://reactjs.org/docs/faq-styling.html#can-i-use-inline-styles
BTW, you can set all the static props in CSS and leave just image to inline styles

CSS for ReactJS - Referencing a div works fine, referencing a className does not

My CSS files work fine when I just use the element names like this:
div {
background-color: blue;
}
But when I use className to identify that div, the CSS is ignored, like this:
.containerInner {
background-color: blue;
}
Here is the js file, so you can see how I'm using className:
import React, { Component } from 'react'
import styles from './Game.css'
import GameContainer from './GameContainer/GameContainer.js'
class Game extends React.Component {
render() {
return (
<div className={styles.containerOuter}>
<div className={styles.containerInner}>
<h1 className={styles.header}>MEMORY</h1>
<GameContainer />
</div>
</div>
)
}
}
export default Game
Notes:
1. I am using create-react-app.
2. I am not using modular css like sass. I'm just using raw css.
3. This is a problem throughout my entire project, not just a couple files
4. There are no error messages in Chrome, or in the terminal
This is the same issue on Stack Overflow, but it does not appear to have been resolved on the thread, and the comments did not lead me to a solution. CSS class selector styles not being applied in React Project
Any ideas? Thanks in advance
If you want to apply a class name to a class, just apply the name. Class names are strings, not objects;
<div className="containerInner">

Material-UI #next Does not support props-based styling?

With the arrival of Material-UI#next comes the replacement of LESS-based styling with CSS-to-JS-based styling. However, the component demos on Material-UI's website appear to ignore the creation of props-based-styling. I'm trying to create divs containing various Material-UI components at specific absolute heights on my page, however, the requirement of the stylesheet being predefined outside of the class means that the properties within the stylesheet can't be based on props passed to the component. Am I missing something?
For example:
import React, {Component} from 'react';
import {withStyles, createStyleSheet} from 'material-ui/styles';
import Button from 'material-ui/Button';
const styleSheet = createStyleSheet({
container: {
position: "absolute",
top: /*How can this be dependent upon the props passed to the component?*/,
height: /*How can this be dependent upon the props passed to the component?*/,
}
});
class Foo extends Component {
render() {
let classes = this.props.classes;
return (
<div className={classes.container}>
<Button raised/>
</div>
);
}
}
export default withStyles(styleSheet)(Foo);
The example component displayed above can't have props-dependent styles, because props is not defined when the stylesheet is created. So how do I solve this problem? IS there a solution?
I would strongly advise you check out Styled Compoments. They make styling very simple and even allow you to pass third party components (in your case Material UI components). They also allow you to pass in props like the following:
const Stylesheet = styled.div`
color: ${props => props.primary ? 'white' :
`
<Stylesheet primary>My Div</Stylesheet>
Check out the docs for more details, that was a very simple example, but they are super easy to work with and you can accomplish exactly what you need with them.

Target specific CSS classes with Styled Components

How would I go about styling something like the react-datepicker with styled-components? The datepicker library looks like it uses some type of BEM style (screenshot below) which I would normally just use their provided class names and style those using Sass. But, how would I target those class names with styled-components? Is that even possible?
Since styled-components is just CSS™ you'd do it like with any other style sheet, by using the class names react-datepicker provided.
The only difference is that you'll have to wrap the datepicker in one wrapper styled component which applies all of these classes:
const Wrapper = styled.div`
&.react-datepicker {
color: blue;
}
`
<Wrapper>
<Datepicker />
</Wrapper>
Searching for hours, I found that the best solution is to add a stylized parent component (it can be a div) overlying the component that needs a className and add the definition of the className directly into the stylized parent component.
VERY IMPORTANT:
A space is needed between the ampersand & and the class for this to take effect!
const StyledParent = styled.div`
& .your-class-name {
border-color: red;
}
`;
<StyledParent>
<Datepicker yourClassName="your-class-name" />
</StyledParent>
If you ever need to access and style another component you can do this if they are not in the same file:
Export whatever you need to access:
export { Wrapper as CircledButtonWrapper };
Import it where you need it:
import { CircledButtonWrapper } from "/Bla/CircledButton";
Use it where you need to style it:
const Wrapper = styled.div`
/* Some other styles */
&:hover {
${CircledButtonWrapper} {
opacity: 1;
}
} `;
Edit:
I see now that the question was refering to accessing className...

Resources