<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dave Irvine</title>
    <description>The latest articles on DEV Community by Dave Irvine (@daveirvine).</description>
    <link>https://dev.to/daveirvine</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F78518%2F0da2c34d-809a-470a-a96a-4f478f5a62f1.jpeg</url>
      <title>DEV Community: Dave Irvine</title>
      <link>https://dev.to/daveirvine</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/daveirvine"/>
    <language>en</language>
    <item>
      <title>PostCSS with CSS Modules and React</title>
      <dc:creator>Dave Irvine</dc:creator>
      <pubDate>Thu, 14 Jun 2018 14:50:18 +0000</pubDate>
      <link>https://dev.to/daveirvine/postcss-with-css-modules-andreact-51ln</link>
      <guid>https://dev.to/daveirvine/postcss-with-css-modules-andreact-51ln</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhh5mfl204fnn392qg91x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhh5mfl204fnn392qg91x.png" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Updates
&lt;/h2&gt;

&lt;p&gt;05/07/20 - The &lt;code&gt;localIdentName&lt;/code&gt; property for css-loader is now a sub-property of the &lt;code&gt;modules&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;02/10/18 - Looks like Create React App now adds support for &lt;a href="https://facebook.github.io/create-react-app/docs/adding-a-css-modules-stylesheet" rel="noopener noreferrer"&gt;CSS Modules&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Intro
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/css-modules/css-modules" rel="noopener noreferrer"&gt;CSS Modules&lt;/a&gt; are meant as a way to locally scope class and animation names to help prevent some of the downfalls of the default global scope that normal CSS is based on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/postcss/postcss" rel="noopener noreferrer"&gt;PostCSS&lt;/a&gt; provides a way to transform styles using JavaScript plugins.&lt;/p&gt;

&lt;p&gt;Can we make them work together? Why would we want to? Let’s answer the second question first.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Why
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fst0gt5g74g800nykv3nk.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fst0gt5g74g800nykv3nk.gif" width="1024" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PostCSS has a deep, deep ecosystem, and of particular interest to me is the &lt;a href="https://preset-env.cssdb.org/" rel="noopener noreferrer"&gt;postcss-preset-env&lt;/a&gt; plugin. Using this plugin gets you access to the newest CSS features, and their polyfills, today. This role used to be filled by &lt;a href="http://cssnext.io/" rel="noopener noreferrer"&gt;cssnext&lt;/a&gt; but this was recently &lt;a href="https://moox.io/blog/deprecating-cssnext/" rel="noopener noreferrer"&gt;deprecated&lt;/a&gt;, so what better time to explore postcss-preset-env?&lt;/p&gt;

&lt;p&gt;An early issue I’ve had using CSS Modules has been its ‘variables’ syntax. While they definitely &lt;a href="https://github.com/css-modules/css-modules/blob/master/docs/values-variables.md" rel="noopener noreferrer"&gt;exist&lt;/a&gt;, I’m really not sold on the syntax, and CSS Variables are already in the &lt;a href="https://www.w3.org/TR/css-variables-1/" rel="noopener noreferrer"&gt;spec&lt;/a&gt; so why are we re-inventing this particular wheel? I don’t think I’m alone in this feeling, other people seem to be &lt;a href="https://github.com/gatsbyjs/gatsby/issues/4933" rel="noopener noreferrer"&gt;asking&lt;/a&gt; how to use CSS Modules with the standard CSS Variables, so here we are.&lt;/p&gt;

&lt;p&gt;Couple this with &lt;a href="https://preset-env.cssdb.org/features#media-query-ranges" rel="noopener noreferrer"&gt;some&lt;/a&gt; &lt;a href="https://preset-env.cssdb.org/features#matches-pseudo-class" rel="noopener noreferrer"&gt;fairly&lt;/a&gt; &lt;a href="https://preset-env.cssdb.org/features#nesting-rules" rel="noopener noreferrer"&gt;sweet&lt;/a&gt; &lt;a href="https://preset-env.cssdb.org/features#grid-layout" rel="noopener noreferrer"&gt;future&lt;/a&gt; CSS functionality, and we’ve got reason enough to tie PostCSS together with CSS Modules.&lt;/p&gt;

&lt;h2&gt;
  
  
  The How
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0w3y6wz8z60ta8eq7pg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0w3y6wz8z60ta8eq7pg.gif" width="500" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alright lets get to it. I hope you’re ready for your &lt;em&gt;node_modules&lt;/em&gt; directory to grow a fair bit, we’ve got some installing to do!&lt;/p&gt;

&lt;p&gt;First up, getting CSS Modules to work at all in the context of your React application.&lt;/p&gt;

&lt;h2&gt;
  
  
  CSS Modules
&lt;/h2&gt;

&lt;p&gt;Let’s get &lt;a href="https://github.com/gajus/babel-plugin-react-css-modules" rel="noopener noreferrer"&gt;babel-plugin-react-css-modules&lt;/a&gt; (is there a longer npm package name?) installed. It has a runtime component, so it actually belongs in your &lt;em&gt;dependencies&lt;/em&gt; rather than your &lt;em&gt;devDependencies&lt;/em&gt;. Install it like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install babel-plugin-react-css-modules --save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Make sure your &lt;em&gt;.babelrc&lt;/em&gt; or whatever equivalent you are using to configure Babel includes the new plugin:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plugins: [‘react-css-modules’]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And now we need to configure &lt;a href="https://webpack.js.org/" rel="noopener noreferrer"&gt;Webpack&lt;/a&gt; to tell it how to load in CSS files. We’ll need &lt;a href="https://github.com/webpack-contrib/style-loader" rel="noopener noreferrer"&gt;style-loader&lt;/a&gt; and &lt;a href="https://github.com/webpack-contrib/css-loader" rel="noopener noreferrer"&gt;css-loader&lt;/a&gt; for this one. These are regular &lt;em&gt;devDependencies&lt;/em&gt; so make sure you install them as such.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install css-loader style-loader --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now lets tell Webpack to use these loaders for CSS files. Add the following to your webpack.config.js&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  test: /\.css$/,
  use: [
    { loader: 'style-loader' },
    {
      loader: 'css-loader',
      options: {
        modules: {
          localIdentName: '[path]___[name]__[local]___[hash:base64:5]',
        },
      },
    },
  ],
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;What’s up with that &lt;em&gt;localIdentName&lt;/em&gt;? Good question! When you switch on the CSS Modules spec, css-loader will munge your css classes according to this ident. This means you can have two &lt;em&gt;.button&lt;/em&gt; classes in your codebase and they wont conflict.&lt;/p&gt;

&lt;p&gt;However this means that when you add a class name to your React component you’d need to know what css-loader is going to transform your class names into, right? Well that’s where babel-plugin-react-css-modules comes in. It’ll do the same munging of class names as css-loader, we just have to make sure they are configured to use the same method of munging.&lt;/p&gt;

&lt;p&gt;The default value for this option in css-loader is different to babel-plugin-react-css-modules, so specifying it to be &lt;em&gt;[path]&lt;em&gt;__[name]&lt;/em&gt;&lt;em&gt;[local]&lt;/em&gt;__[hash:base64:5]&lt;/em&gt; fixes that.&lt;/p&gt;

&lt;p&gt;Great, now in your React component you should be able to import the CSS file directly:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;App.css&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.app {
  border: 1px solid red;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;App.jsx&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';

import './App.css';

const App = () =&amp;gt; (
  &amp;lt;div styleName="app"&amp;gt;
    Hello, world!
  &amp;lt;/div&amp;gt;
);

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;em&gt;styleName&lt;/em&gt; property is babel-plugin-react-css-modules’s replacement for &lt;em&gt;className&lt;/em&gt;, but you get used to it pretty quickly.&lt;/p&gt;

&lt;p&gt;Assuming everything has worked, you’ll have class names that look like word soup:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fghwdaquyaahub7b6oin3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fghwdaquyaahub7b6oin3.png" width="496" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  PostCSS
&lt;/h2&gt;

&lt;p&gt;And now for the fun stuff. Lots of modules to install, so lets get started:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install postcss postcss-import postcss-loader postcss-preset-env postcss-url --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We will need to change our &lt;em&gt;webpack.config.js&lt;/em&gt; to make sure the postcss-loader gets used:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  test: /\.css$/,
  use: [
    { loader: 'style-loader' },
    {
      loader: 'css-loader',
      options: {
        importLoaders: 1,
        modules: {
          localIdentName: '[path]___[name]__[local]___[hash:base64:5]',
        },
      },
    },
    { loader: 'postcss-loader' }
  ],
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And now we need a new &lt;em&gt;postcss.config.js&lt;/em&gt; file&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  plugins: [
    require('postcss-import'),
    require('postcss-url'),
    require('postcss-preset-env')({
      browsers: 'last 2 versions',
      stage: 0,
    }),
  ],
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now we can try it out! Make a new &lt;em&gt;colors.css&lt;/em&gt; file&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:root {
  --errorRed: #e03030;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;and change App.css to use it:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@import "../colors.css";

.app {
  border: 1px solid var(--errorRed);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;How’s that style block looking?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ga6gsrk6e1azwugktg0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ga6gsrk6e1azwugktg0.png" width="286" height="156"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nice! You get the &lt;em&gt;var()&lt;/em&gt; rule for browsers that support it, or the fallback for those that don’t.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Getting the right combination of modules to make this work was the real challenge on this one, the configuration itself was fairly easy.&lt;/p&gt;

&lt;p&gt;If this doesn’t work for you, something is missing, or you think I’ve gone about this the wrong way, I’d love to hear from you in the comments.&lt;/p&gt;

</description>
      <category>postcss</category>
      <category>react</category>
      <category>css</category>
      <category>webpack</category>
    </item>
  </channel>
</rss>
