Stylesheets - Phizzard/Reactbase-cms GitHub Wiki
This project setup uses Webpack for handling all assets. Webpack offers a custom way of “extending” the concept of import
beyond JavaScript. To express that a JavaScript file depends on a CSS file, you need to import the CSS from the JavaScript file:
.Button {
padding: 20px;
}
import React, { Component } from 'react';
import './Button.css'; // Tell Webpack that Button.js uses these styles
class Button extends Component {
render() {
// You can use them as regular CSS styles
return <div className="Button" />;
}
}
This is not required for React but many people find this feature convenient. You can read about the benefits of this approach here. However you should be aware that this makes your code less portable to other build tools and environments than Webpack.
In development, expressing dependencies this way allows your styles to be reloaded on the fly as you edit them. In production, all CSS files will be concatenated into a single minified .css
file in the build output.
If you are concerned about using Webpack-specific semantics, you can put all your CSS right into src/index.css
. It would still be imported from src/index.js
, but you could always remove that import if you later migrate to a different build tool.
This project setup minifies your CSS and adds vendor prefixes to it automatically through Autoprefixer so you don’t need to worry about it.
For example, this:
.App {
display: flex;
flex-direction: row;
align-items: center;
}
becomes this:
.App {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
If you need to disable autoprefixing for some reason, follow this section.
Generally, we recommend that you don’t reuse the same CSS classes across different components. For example, instead of using a .Button
CSS class in <AcceptButton>
and <RejectButton>
components, we recommend creating a <Button>
component with its own .Button
styles, that both <AcceptButton>
and <RejectButton>
can render (but not inherit).
Following this rule often makes CSS preprocessors less useful, as features like mixins and nesting are replaced by component composition. You can, however, integrate a CSS preprocessor if you find it valuable. In this walkthrough, we will be using Sass, but you can also use Less, or another alternative.
First, let’s install the command-line interface for Sass:
npm install --save node-sass-chokidar
Alternatively you may use yarn
:
yarn add node-sass-chokidar
Then in package.json
, add the following lines to scripts
:
"scripts": {
+ "build-css": "node-sass-chokidar src/ -o src/",
+ "watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
Note: To use a different preprocessor, replace
build-css
andwatch-css
commands according to your preprocessor’s documentation.
Now you can rename src/App.css
to src/App.scss
and run npm run watch-css
. The watcher will find every Sass file in src
subdirectories, and create a corresponding CSS file next to it, in our case overwriting src/App.css
. Since src/App.js
still imports src/App.css
, the styles become a part of your application. You can now edit src/App.scss
, and src/App.css
will be regenerated.
To share variables between Sass files, you can use Sass imports. For example, src/App.scss
and other component style files could include @import "./shared.scss";
with variable definitions.
To enable importing files without using relative paths, you can add the --include-path
option to the command in package.json
.
"build-css": "node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/",
"watch-css": "npm run build-css && node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/ --watch --recursive",
This will allow you to do imports like
@import 'styles/_colors.scss'; // assuming a styles directory under src/
@import 'nprogress/nprogress'; // importing a css file from the nprogress node module
At this point you might want to remove all CSS files from the source control, and add src/**/*.css
to your .gitignore
file. It is generally a good practice to keep the build products outside of the source control.
As a final step, you may find it convenient to run watch-css
automatically with npm start
, and run build-css
as a part of npm run build
. You can use the &&
operator to execute two scripts sequentially. However, there is no cross-platform way to run two scripts in parallel, so we will install a package for this:
npm install --save npm-run-all
Alternatively you may use yarn
:
yarn add npm-run-all
Then we can change start
and build
scripts to include the CSS preprocessor commands:
"scripts": {
"build-css": "node-sass-chokidar src/ -o src/",
"watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
- "start": "react-scripts start",
- "build": "react-scripts build",
+ "start-js": "react-scripts start",
+ "start": "npm-run-all -p watch-css start-js",
+ "build": "npm run build-css && react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
Now running npm start
and npm run build
also builds Sass files.
Why node-sass-chokidar
?
node-sass
has been reported as having the following issues:
-
node-sass --watch
has been reported to have performance issues in certain conditions when used in a virtual machine or with docker. -
Infinite styles compiling #1939
-
node-sass
has been reported as having issues with detecting new files in a directory #1891
node-sass-chokidar
is used here as it addresses these issues.