Skip to content

Use with CSS Modules to map Class names to the generated name.

License

Notifications You must be signed in to change notification settings

matt-mcmahon/scoper

Repository files navigation

Scoper

CSS Modules are a popular way to style your websites, but could be easier to use.

Enter, Scoper! 🎆

Scoper takes the mapping object tools like WebPack create when you import a CSS Module, and generates a Tagged Template function that you can use to easily attach the generated class-names to your HTML elements. Simply tag a template literal containing any valid className with that function, and Scoper will expand each class-name into its generated equivalent.

Getting Started

Add Scoper to your project using NPM:

> npm install --save @mwm/scoper

Then import Scoper anywhere you're using CSS Modules.

import styles from './App.module.css' // our css
import scoper from '@mwm/scoper' // Scoper!

Scoper won't do anything on it's own; it needs the mapping object WebPack creates. Simply pass the imported styles object to the scoper function, and Scoper will return a tag function (which we named "scope"):

const scope = scoper(styles)

Tagging function in hand, we can apply complicated scoped classes like this 😊:

<div className={scope`my-class otherClass`}>

instead of this 😟:

<div className={styles['my-class'] + ' ' + styles.otherClass}>

Finally, you can call the tagging function like a normal function, too!

<div className={scope('my-class otherClass')}>

Using Scoper With React

This is what the App.js component might look like if create-react-app used CSS Modules and Scoper tagging.

For this example, I've combined the root <div> and <header> elements to show how adding multiple classes works. I've also renamed the "logo" class to "animated-logo", to show-off how easy kebab class-names are to use. Finally, the class-names that WebPack generates are configured to include the "App" prefix by default, so I removed that prefix from them.

Here's the code!

import React, { Component } from 'react'
import logo from './logo.svg'
import styles from './App.module.css'
import scoper from '@mwm/scoper'

const scope = scoper(styles)

class App extends Component {
  render() {
    return (
      <header className={scope`root header`}>
        <img className={scope`animated-logo`} src={logo} alt='logo' />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className={scope`link`}
          href='https://reactjs.org'
          target='_blank'
          rel='noopener noreferrer'
        >
          Learn React
        </a>
      </header>
    )
  }
}

export default App

Using Classer With React

Added alternate function, classer. You can use the classer named export in React apps to avoid typing out className={scope`whatever`}. Instead, combine classer with the spread operator and type less! Using classer is similar to scoper. For example:

import { classer } from '@mwm/scoper'
const className = classer(someImportedCSSModule)
const someJSX = <div {...className`something`} />

Here's React's default App example using the classer tagged function:

import React, { Component } from 'react'
import logo from './logo.svg'
import styles from './App.module.css'
import { classer } from '@mwm/scoper'

const className = classer(styles)

class App extends Component {
  render() {
    return (
      <header {...className`root header`}>
        <img {...className`animated-logo`} src={logo} alt='logo' />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          {...className`link`}
          href='https://reactjs.org'
          target='_blank'
          rel='noopener noreferrer'
        >
          Learn React
        </a>
      </header>
    )
  }
}

export default App

About

Use with CSS Modules to map Class names to the generated name.

Resources

License

Stars

Watchers

Forks

Packages

No packages published