Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

require css in React component affects other components too

Tags:

css

reactjs

I have the following render in my "main" component:

import ComponentA from './component-a.js'; 
import ComponentB from './component-b.js'; 
const App = React.createClass({
    render: function() {
        return (
            <div>
                <ComponentA/>
                <ComponentB/>
            </div>
        );
    }
});

ComponentA requires a css file. So I have the following in component-a.js:

require ('./component-a.css');
const ComponentA = React.createClass({
    render: function() {
        return (
            <div>component a</div>
        );
    }
});

… whereas ComponentB doesn't. So I have the following in component-b.js:

const ComponentB = React.createClass({
    render: function() {
        return (
            <div>component b</div>
        );
    }
});

The css file required by ComponentA (only) is:

div {
    width: 100px;
    height: 30px;
    border: 1px solid red;
}

Even though it is only ComponentA that requires the css, ComponentB is also affected. This is what gets rendered in the browser:

enter image description here

It seems that all div elements in the page are affected by the style required by ComponentA. That includes the div of the subsequent component ComponentB (which does not require the css style) as well as the div that contains ComponentA and ComponentB and yet another div added by React:

enter image description here

  1. Aren't css files affecting only the component that requires them? If not, and they are effectively global in effect then what exactly are the semantics of requiring a css file from a specific component ?

  2. Other than using inline styles and placing everything in JS code, is there a way to compartmentalize CSS files so that they only affect the React component that requires them ? If one were to use class names to achieve that effect there is no guarantee that the class names would be unique when a component is used alongside other components.

like image 912
Marcus Junius Brutus Avatar asked Oct 25 '16 14:10

Marcus Junius Brutus


1 Answers

CSS is still loaded into the browser to affect the whole page. The importing of css files is only to modularize your css along with your js, so that when you use your module loader to the fullest, not only are you not loading unnecessary js, you also aren't loading unnecessary css.

EDIT: a video on how Instagram works with module loading:
https://www.youtube.com/watch?v=VkTCL6Nqm6Y&noredirect=1

Your best solution is still to namespace your css. Concerning clashing issues, you could use even more verbose classnames than what I used below like mjb-appname-componentname

Have your ComonentA's render be:

render: function() {
    return (
        <div className="component-a">component a</div>
    );
}

and its css file be

.component-a div {
    width: 100px;
    height: 30px;
    border: 1px solid red;
}

preferably with a css preprocessor like less or sass

.component-a {
    div {
        width: 100px;
        height: 30px;
        border: 1px solid red;
    }
}

extra:

an interesting talk about inline style in js: http://blog.vjeux.com/2014/javascript/react-css-in-js-nationjs.html

a discussion about issues raised by using this inline style method:

https://github.com/callemall/material-ui/issues/4066

like image 105
narvoxx Avatar answered Oct 28 '22 02:10

narvoxx