5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/css-modules-by-example/README.md:
--------------------------------------------------------------------------------
1 | CSS Modules by Example
2 | ---
3 |
4 | These are the example components shown in my [CSS Modules by Example](http://andrewhfarmer.com/css-modules-by-example/) post.
5 |
6 |
7 |
8 | Setup
9 | ---
10 |
11 | ```
12 | npm install
13 | ```
14 |
15 |
16 |
17 | Running
18 | ---
19 |
20 | 1. Run `node server.js`
21 | 2. Open [http://localhost:8080](http://localhost:8080)
22 |
23 | Changes to your Javascript will automatically rebuild webpack and reload the browser.
24 |
25 | Note that HTML changes will require a manual reload.
26 |
27 |
28 |
29 | Notes
30 | ---
31 |
32 | CSS Modules take all the classes out of your `.css` file and turn them into JavaScript variables.
33 |
34 | If you are used to SCSS, this can be a little weird.
35 |
36 | You can't really use nested classes in the same way that you would in SCSS.
37 |
38 | In fact, you can't specify ANY class names as strings.
39 |
40 | ```
41 | className="meow" // this will NEVER WORK
42 | ```
43 |
--------------------------------------------------------------------------------
/css-modules-by-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cssmodules-project",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "babel": "^6.5.2",
14 | "babel-core": "^6.7.4",
15 | "babel-loader": "^6.2.4",
16 | "babel-preset-es2015": "^6.6.0",
17 | "babel-preset-react": "^6.5.0",
18 | "classnames": "^2.2.3",
19 | "css-loader": "^0.23.1",
20 | "extract-text-webpack-plugin": "^1.0.1",
21 | "node-sass": "^3.4.2",
22 | "react": "^0.14.7",
23 | "react-dom": "^0.14.7",
24 | "sass-loader": "^3.2.0",
25 | "style-loader": "^0.13.1",
26 | "webpack": "1.12.12",
27 | "webpack-dev-server": "1.14.1"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/css-modules-by-example/server.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-var, no-console */
2 | /**
3 | * This file runs a webpack-dev-server, using the API.
4 | *
5 | * For more information on the options passed to WebpackDevServer,
6 | * see the webpack-dev-server API docs:
7 | * https://github.com/webpack/docs/wiki/webpack-dev-server#api
8 | */
9 | var WebpackDevServer = require('webpack-dev-server');
10 | var webpack = require('webpack');
11 | var config = require('./webpack.config.js');
12 |
13 | var compiler = webpack(config);
14 | var server = new WebpackDevServer(compiler, {
15 | contentBase: 'www',
16 | hot: true,
17 | filename: 'bundle.js',
18 | publicPath: '/',
19 | stats: {
20 | colors: true,
21 | },
22 | });
23 | server.listen(8080, 'localhost', () => {
24 | console.log('Server started, webpack is compiling...');
25 | });
26 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/0_Cat/Cat.css:
--------------------------------------------------------------------------------
1 | .meow {
2 | color: orange;
3 | }
4 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/0_Cat/Cat.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styles from './Cat.css';
3 |
4 | class Cat extends React.Component {
5 | render() {
6 | return (
7 |
8 | Orange Cat
9 |
10 | );
11 | }
12 | }
13 | export default Cat;
14 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/0_Cat/README.md:
--------------------------------------------------------------------------------
1 | Simple cat example.
2 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/1_Single_Class_Name/README.md:
--------------------------------------------------------------------------------
1 | This is the simplest possible example of CSS Modules. There is only a single class name in the CSS file.
2 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/1_Single_Class_Name/Widget1.css:
--------------------------------------------------------------------------------
1 | .button {
2 | border-radius: 4px;
3 | background-color: #94D0F9;
4 | }
5 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/1_Single_Class_Name/Widget1.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styles from './Widget1.css';
3 |
4 | console.log('Widget1 styles:', styles);
5 |
6 | class Widget1 extends React.Component {
7 | render() {
8 | return (
9 |
12 | );
13 | }
14 | }
15 | export default Widget1;
16 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/2_Multiple_Class_Names/README.md:
--------------------------------------------------------------------------------
1 | In this example the CSS file has 3 different class names. They all become accessible to the component in the `styles` object.
2 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/2_Multiple_Class_Names/Widget2.css:
--------------------------------------------------------------------------------
1 | .title {
2 | font-weight: bold;
3 | font-size: 16px;
4 | }
5 |
6 | .email {
7 | padding: .5rem;
8 | }
9 |
10 | .submitButton {
11 | padding: .5rem;
12 | margin-top: .5rem;
13 | border: 1px solid #2F79AD;
14 | border-radius: 4px;
15 | background-color: #6DB9EE;
16 | }
17 |
18 | .submitButton:hover {
19 | background-color: #2F79AD;
20 | }
21 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/2_Multiple_Class_Names/Widget2.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styles from './Widget2.css';
3 |
4 | console.log('Widget2 styles:', styles);
5 |
6 | class Widget2 extends React.Component {
7 | render() {
8 | return (
9 |
10 |
Email Signup
11 |
15 |
16 |
17 |
18 | );
19 | }
20 | }
21 | export default Widget2;
22 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/3_Combination_Class_Names/README.md:
--------------------------------------------------------------------------------
1 | In this example there are style rules that only apply to elements that contain two class names: 'button' and 'disabled'.
2 |
3 | You can see that both classnames are returned separately. In your component, you must add both class names in order for the styles to take effect.
4 |
5 | NOTE: CSS Modules will NOT combine `.button.disabled` into a single rule. It will return class names for both `button` and `disabled`.
6 |
7 | NOTE: We are using the [classnames](https://github.com/JedWatson/classnames) package here to combine classnames. In this situation it just adds a space between the two classnames.
8 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/3_Combination_Class_Names/Widget3.css:
--------------------------------------------------------------------------------
1 | .button {
2 | padding: .5rem;
3 | margin-top: .5rem;
4 | border: 1px solid #2F79AD;
5 | border-radius: 4px;
6 | background-color: #6DB9EE;
7 | }
8 |
9 | .button.disabled {
10 | background-color: #aaa;
11 | border-color: #999;
12 | }
13 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/3_Combination_Class_Names/Widget3.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styles from './Widget3.css';
3 | import cx from 'classnames';
4 |
5 | console.log('Widget3 styles:', styles);
6 |
7 | class Widget3 extends React.Component {
8 | render() {
9 | return (
10 |
11 |
15 |
16 |
20 |
21 | );
22 | }
23 | }
24 | export default Widget3;
25 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/4_Nested_Class_Names/README.md:
--------------------------------------------------------------------------------
1 | In this example there are style rules that only apply to elements with a particular class name that are also nested within another element with a particular class name.
2 |
3 | You can see that both classnames are returned separately. In your component, you must add both class names in order for the styles to take effect.
4 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/4_Nested_Class_Names/Widget4.css:
--------------------------------------------------------------------------------
1 | .button {
2 | padding: .5rem;
3 | margin-top: .5rem;
4 | border: 1px solid #2F79AD;
5 | border-radius: 4px;
6 | background-color: #6DB9EE;
7 | }
8 |
9 | .fun .button {
10 | font-weight: bold;
11 | background: linear-gradient(90deg, #ff0000, #ffff00, #00ff00, #00ffff, #ff00ff, #ff0000);
12 | }
13 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/4_Nested_Class_Names/Widget4.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styles from './Widget4.css';
3 |
4 | console.log('Widget4 styles:', styles);
5 |
6 | class Widget4 extends React.Component {
7 | render() {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | );
17 | }
18 | }
19 | export default Widget4;
20 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/5_Composition/README.md:
--------------------------------------------------------------------------------
1 | Obviously you are going to want to share some styles between components.
2 |
3 | With CSS Modules, what is shared is explicit.
4 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/5_Composition/Widget5.css:
--------------------------------------------------------------------------------
1 | .button {
2 | composes: grape from './util.css';
3 | padding: .5rem;
4 | margin-top: .5rem;
5 | }
6 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/5_Composition/Widget5.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styles from './Widget5.css';
3 |
4 | console.log('Widget5 styles:', styles);
5 |
6 | class Widget5 extends React.Component {
7 | render() {
8 | return (
9 |
10 | );
11 | }
12 | }
13 | export default Widget5;
14 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/5_Composition/util.css:
--------------------------------------------------------------------------------
1 | /* grapes are round and purple */
2 | .grape {
3 | border: 2px solid #ff00ff;
4 | border-radius: 10px;
5 | background-color: purple;
6 | color: white;
7 | }
8 |
9 | .grape:hover {
10 | background-color: #ff00ff;
11 | }
12 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/6_Tag_Names/README.md:
--------------------------------------------------------------------------------
1 | CSS Modules rewrite class names, but they don't touch tag names.
2 |
3 | Selectors like `input`, `div`, or `h1` will be left alone.
4 |
5 | In a selector like `.signup input`, the `signup` class will be renamed, but the `input` portion of the selector will be left alone and you get something like this: `.filename_signup_123 input`.
6 |
7 | May I strongly suggest: Never use a selector that is JUST a tag name. Always specify a class name also.
8 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/6_Tag_Names/Widget6.css:
--------------------------------------------------------------------------------
1 | input.large {
2 | font-size: 20px;
3 | }
4 |
5 | .medium input {
6 | font-size: 14px;
7 | }
8 |
9 | .tiny * {
10 | font-size: 9px;
11 | }
12 |
13 | /* Don't do this!
14 | This style will be global. */
15 | input {
16 | padding: 0.5rem;
17 | }
18 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/6_Tag_Names/Widget6.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styles from './Widget6.css';
3 |
4 | console.log('Widget6 styles:', styles);
5 |
6 | class Widget6 extends React.Component {
7 | render() {
8 | return (
9 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | );
21 | }
22 | }
23 | export default Widget6;
24 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/7_Media_Queries/README.md:
--------------------------------------------------------------------------------
1 | Since all CSS Modules do is rewrite your classnames, all the features you are used to in CSS still work as-is.
2 |
3 | Here's an example that uses media queries. Resize your browser window to the media queries in action.
4 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/7_Media_Queries/Widget7.css:
--------------------------------------------------------------------------------
1 | .small {
2 | opacity: 0.2;
3 | }
4 | .large {
5 | opacity: 1.0;
6 | }
7 |
8 | @media (max-width: 600px) {
9 | .small {
10 | opacity: 1.0;
11 | }
12 | .large {
13 | opacity: 0.2;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/7_Media_Queries/Widget7.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styles from './Widget7.css';
3 |
4 | console.log('Widget7 styles:', styles);
5 |
6 | class Widget7 extends React.Component {
7 | render() {
8 | return (
9 |
10 |
11 | The Window is Small
12 |
13 |
14 | The Window is Big
15 |
16 |
17 | );
18 | }
19 | }
20 | export default Widget7;
21 |
--------------------------------------------------------------------------------
/css-modules-by-example/src/index.js:
--------------------------------------------------------------------------------
1 | import Cat from './0_Cat/Cat';
2 | import Widget1 from './1_Single_Class_Name/Widget1';
3 | import Widget2 from './2_Multiple_Class_Names/Widget2';
4 | import Widget3 from './3_Combination_Class_Names/Widget3';
5 | import Widget4 from './4_Nested_Class_Names/Widget4';
6 | import Widget5 from './5_Composition/Widget5';
7 | import Widget6 from './6_Tag_Names/Widget6';
8 | import Widget7 from './7_Media_Queries/Widget7';
9 | import React from 'react';
10 | import ReactDOM from 'react-dom';
11 |
12 | ReactDOM.render(