I have a React component with the following files:
- src/components/HomePage/index.js
- src/components/HomePage/style.scss
The component is very simple:
import React from 'react';
import './style.scss';
const HomePage = () => {
return (
<div className="homepage">
<h1>Landing page</h1>
</div>
);
};
export default HomePage;
Within style.scss
I am applying a style to all <h1>
tags:
h1 {
color: #f3f3f3;
font-family: "Cambria";
font-weight: normal;
font-size: 2rem;
}
And it works as expected. However, I now see that the h1 style within styles.scss
is being applied to every h1 on my site, even on pages that do not use this component.
I am using Gatsby, but it's a React app at heart. My understanding is that React's code-splitting feature would take care of this, that the code from style.scss
would only be included in bundles for any page that uses my component.
It's the why that I am asking about. I have two easy fixes:
- Wrap everything in
style.scss
in a.homepage
wrapper - Use CSS modules and rename the file to
style.module.scss
. When I see people do that they always do `import style from './style.module.scss' - is there a way to have CSS modules without assigning it to an object like that?
Update: Coming back to this question after spending a lot of time with React and I think there's a gap in the market for React styling. CSS modules is syntactically poor in my opinion and having to manually wrap everything in a .home
tag to localise it is manual work I don't want to do. Someone should really create a React plugin that automatically does this so that whenever I have a file called Home.js
and I import Home.css
that all the CSS is automatically restricted to Home.js
without me having to do anything special.
I have a React component with the following files:
- src/components/HomePage/index.js
- src/components/HomePage/style.scss
The component is very simple:
import React from 'react';
import './style.scss';
const HomePage = () => {
return (
<div className="homepage">
<h1>Landing page</h1>
</div>
);
};
export default HomePage;
Within style.scss
I am applying a style to all <h1>
tags:
h1 {
color: #f3f3f3;
font-family: "Cambria";
font-weight: normal;
font-size: 2rem;
}
And it works as expected. However, I now see that the h1 style within styles.scss
is being applied to every h1 on my site, even on pages that do not use this component.
I am using Gatsby, but it's a React app at heart. My understanding is that React's code-splitting feature would take care of this, that the code from style.scss
would only be included in bundles for any page that uses my component.
It's the why that I am asking about. I have two easy fixes:
- Wrap everything in
style.scss
in a.homepage
wrapper - Use CSS modules and rename the file to
style.module.scss
. When I see people do that they always do `import style from './style.module.scss' - is there a way to have CSS modules without assigning it to an object like that?
Update: Coming back to this question after spending a lot of time with React and I think there's a gap in the market for React styling. CSS modules is syntactically poor in my opinion and having to manually wrap everything in a .home
tag to localise it is manual work I don't want to do. Someone should really create a React plugin that automatically does this so that whenever I have a file called Home.js
and I import Home.css
that all the CSS is automatically restricted to Home.js
without me having to do anything special.
- check this thread out stackoverflow.com/questions/47090574/… – martin Commented Jul 25, 2020 at 20:35
- Does this answer your question? How to make React CSS import component-scoped? – jmargolisvt Commented Jul 25, 2020 at 20:37
- I understand that CSS modules will simply do the job of wrapping my CSS in a parent tag for me. My question is really about why code splitting does not take care of this? I thought the whole point of code splitting is that JS/CSS wasn't loaded until it was needed. – MSOACC Commented Jul 25, 2020 at 20:41
2 Answers
Reset to default 8If you want to localize CSS rules, then you would have to switch to modular stylesheets (works the same for sass stylesheets).
In your current structure, the component imports non-modular stylesheet and doesn't localize the changes with a unique identifier. Therfore added rules live in a global scope without a unique identifier that would localize them so that only selected components could understand them. That means that they are capable of easily overwriting the same-named rules which were previously established (import order matters here, because it would dictate how the bundler appends the output stylesheet).
So instead of holding component-related rules within ./style.scss
file, rename it to ./index.module.scss
and then you would utilize it within the component like so:
import React from 'react';
import styles from './index.module.scss';
const HomePage = () => {
return (
<div className={style.homepage}>
<h1 className={style.heading}>Landing page</h1>
</div>
);
};
export default HomePage;
and your stylesheet would look like:
.heading {
color: #f3f3f3;
font-family: "Cambria";
font-weight: normal;
font-size: 2rem;
}
disclaimer:
I've changed the styling convention from selecting elements by their tag, to selecting them by class, because targetting elements by tag is widely considered a bad practice [ref] , but if you want to maintain it, then you would have to provide a parent scope for such a rule (it already exists since the parent <div/>
element has an assigned class.
In this case the implementation would look like:
import React from 'react';
import styles from './index.module.scss';
const HomePage = () => {
return (
<div className={style.homepage}>
<h1>Landing page</h1>
</div>
);
};
export default HomePage;
and styles:
.homepage {
h1 {
color: #f3f3f3;
font-family: "Cambria";
font-weight: normal;
font-size: 2rem;
}
}
You can either go with the easiest way that is mentioned below.
import React from 'react';
import './style.scss';
const HomePage = () => {
return (
<div className = "home">
<div className="homepage">
<h1>Landing page</h1>
</div>
</div>
);
};
export default HomePage;
You can wrap whole html inside one div of particular component name
CSS:
.home h1 {
color: #f3f3f3;
font-family: "Cambria";
font-weight: normal;
font-size: 2rem;
}
This is the easiest way. However this is my personal solution because I also face the same issues when I was beginner at react.