bradxr
1/11/2019 - 1:07 PM

12 - CSS Modules

review

CSS Modules

  • deep dive
  • Can write normal CSS code and make sure that it only applies to a given component
  • Uses automatically generated unique CSS class names to do this

Enabling CSS Modules

  • CSS Modules can be used without ejecting from Create React App, see here
  • To use the full power of CSS Modules you need to eject, this can be done by doing the following:
    • run npm eject
    • change { test: /\.css$/, } to { test: cssRegex, exclude: cssModuleRegex, use: getStyleLoaders({ importLoaders: 1, modules: true, localIdentName: '[name]__[local]__[hash:base64.5]'})
    • ref

Code Example - Using CSS Modules

  • To use CSS Modules after enabling, we need to do the following:
    • change import from import './App.css; to import classes from './App.css;
    • call classes differently from className="App" to className={classes.App}; we are no longer calling the classes as strings but as properties

Primary Component

import React, {Component} from 'react';
import classes from './App.css';

class App extends Component {
  state = {
    persons: [ { ... }, { ... } ],
      showPersons: false
  }
  
  togglePersonsHandler = () => {
    const doesShow = this.state.showPersons;
    this.setState({showPersons: !doesShow});
  }

  render() {
    const style = {
      backgroundColor: 'green',
      color: 'white',
      font: 'inherit',
      border: '1px solid blue',
      padding: '8px',
      cursor: 'pointer',
    }
  
    let persons = null;
  
    if (this.state.showPersons) {
      persons = (
        <div>
          {this.state.persons.map((person, index) => {
          return <Person ... />
          })}
        </div>
      );
      style.backgroundColor = 'red';
    }
  
    let assignedClasses = [];
  
    // NOTE WE NO LONGER PUSH STRINGS I.E. CLASSES.JOIN(' ')
    // REFERRING TO THE CSS CLASSES NOT AS STRINGS BUT AS PROPERTIES IN THE CSS
    if (this.state.persons.length <= 2) {
      assignedClasses.push(classes.red);
    }
    if (this.state.persons.length <= 1) {
      assignedClasses.push(classes.bold);
    }
  
    return(
      <div className={classes.App}>
        <p className={classes.join(' ')}>Setting Class Names Dynamically</p>
        <button onClick={this.togglePersonsHandler} style={style}>Toggle Persons</button>
        {persons}
      </div>
    )
  }
}
export default App;

Secondary Component

import React from 'react';
// no longer works: import './Person.css';
// MUST USE
import classes from './Person.css';

const person = (props) => {

  const style = {
    // adding media query
    '@media (min-width: 500px)': {
      width: '450px',
    }
  };

  return (
    // CHANGE CLASSNAME ATTRIBUTE
    <div className={classes.Person}>
      <p onClick={props.switchNameHandler}>Hi! Im {props.name}</p>
    </div>
  );
}
export default person;

Code Example - Adding Pseudo Selectors

  • app.js button style, remove inline and remove styles and inline
  • create css class in app.css .App button { ... }
  • create pseudo class .App button:hover { ... }
  • bind the class name of the button in the render method i.e. within render method at the top let btnClass = '';
  • within if statement btnClass = classes.Red;
  • in return method on button className={btnClass}

Code Example - Working with Media Queries

  • add normal CSS media query to Person.css
  • implementation automatic