Maria
Maria

Reputation: 3525

How to add scoped css in react?

Is there a React equivalent of scoped css as in Vue that's super easy to work with, without a bunch of re-writes? One which I can just import an existing css file, and hook it up to a component, and it just works?

In Vue, it's as easy as

<style scoped src="./boxes.css"></style>

And Bam! Your css is now scoped to your component.

Is there anything similar in React? Something like

// import the css file
import styles from "./boxes.css";

// hook it to a component, or using any other methods
@inject(styles)
class Boxes extends Component {
  render(){
    <div className='container'>
       /* must support multiple classes out-of-the-box, unlike CSSModule where you have to 
       re-write into a super long array like className={[styles.box, styles.green, styles.large]} */
      <div className='box green large'></div> 
      <div className='box red small'></div> 
    </div>
  }
}

Upvotes: 19

Views: 18780

Answers (6)

whoismuktar
whoismuktar

Reputation: 351

For anyone that stumbles upon this...

Coming from Vue, I faced this issue as well. I was able to device a flexible scoped styling structure for each component

Consider the below.

const useOwnStyles = () => ({
    hero: {
        backgroundColor: "red",
        height: "300px",
    },
    // add more classes
});

const Home = () => {
    const classes = useOwnStyles();
    return (
        <div style={classes.hero}>
           <div>My Section</div>
        </div>
    );
}
 
export default Home;

Upvotes: 1

Bastien
Bastien

Reputation: 158

You can use css modules with the webpack css-loader.

It will scope your css by adding a unique hash in the name of your css classes.

For exemple if you have a ComponentA with a style definition in a file named stylesA.css and a ComponentB with a style definition in a file named stylesB.css like:

import * as React from 'react'

const stylesA = require('./stylesA.css')
const stylesB = require('./stylesB.css')

class ComponentA extends React.Component {
  render <div className={stylesA.container}>
}

class ComponentB extends React.Component {
  render <div className={stylesB.container}>
}

class Main extends React.Component {
  render <div>
    <ComponentA />
    <ComponentB />
  </div>
}

your HTML file will result as

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>title</title>
  </head>
  <body>
    <div id="app">
      <div class="container-[HASH FOR A]">
      </div>
      <div class="container-[DIFFERENT HASH FOR B]">
      </div>
    </div>
    <script src="bundle.js"></script>
  </body>
</html>

Upvotes: 0

Every answer here is about CSS Modules, but scoped styles in Vue works another way.

Here the library for React that works like <style scoped> in Vue: https://github.com/gaoxiaoliangz/react-scoped-css

Input:

import React from 'react'
import './Title.scoped.css'

const Title = props => {
  return (
    <h1 className="title">
      <p>{props.children}</p>
    </h1>
  )
}

export default Title

Output:

<h1 class="title" data-v-hi7yyhx>
.title[data-v-hi7yyhx] {}

Upvotes: 17

Gal Margalit
Gal Margalit

Reputation: 5844

https://facebook.github.io/create-react-app/docs/adding-a-css-modules-stylesheet

Button.module.css

.error {
  background-color: red;
}

another-stylesheet.css

.error {
  color: red;
}

Button.js

import React, { Component } from 'react';
import styles from './Button.module.css'; // Import css modules stylesheet as styles
import './another-stylesheet.css'; // Import regular stylesheet

class Button extends Component {
  render() {
    // reference as a js object
    return <button className={styles.error}>Error Button</button>;
  }
}

Result: No clashes from other .error class names

<!-- This button has red background but not red text -->
<button class="Button_error_ax7yz">Error Button</button>

Upvotes: 9

dungmidside
dungmidside

Reputation: 518

There's nothing like that in React. 3 common ways to style:

  1. Import a css file then use className like normal HTML => nothing have to learn, just add an import and you ready to go.
  2. Css-in-js libraries. I prefer styled-component - it's awesome.
  3. Inline style

Upvotes: 1

kingdaro
kingdaro

Reputation: 12018

As far as I know, there's no way to do it exactly the way Vue does it, but there are plenty of libraries for doing this kind of thing, which gives you lots of choice for however you prefer to work. My personal recommendation is emotion.

Upvotes: 0

Related Questions