{"id":25092827,"url":"https://github.com/biril/modcss","last_synced_at":"2026-04-16T12:39:25.542Z","repository":{"id":149660657,"uuid":"64321983","full_name":"biril/modcss","owner":"biril","description":"Modular CSS with postCSS and npm scripts","archived":false,"fork":false,"pushed_at":"2017-02-02T17:45:11.000Z","size":5486,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-04-01T22:33:10.791Z","etag":null,"topics":["css","css-modules","example","npm-scripts","postcss","tutorial"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/biril.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-07-27T15:54:11.000Z","updated_at":"2017-02-02T17:14:29.000Z","dependencies_parsed_at":null,"dependency_job_id":"cca1d3e3-01bd-4a64-93c8-efd02a842928","html_url":"https://github.com/biril/modcss","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/biril/modcss","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/biril%2Fmodcss","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/biril%2Fmodcss/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/biril%2Fmodcss/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/biril%2Fmodcss/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/biril","download_url":"https://codeload.github.com/biril/modcss/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/biril%2Fmodcss/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31886627,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-16T11:36:10.202Z","status":"ssl_error","status_checked_at":"2026-04-16T11:36:09.652Z","response_time":69,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["css","css-modules","example","npm-scripts","postcss","tutorial"],"created_at":"2025-02-07T14:35:02.862Z","updated_at":"2026-04-16T12:39:25.523Z","avatar_url":"https://github.com/biril.png","language":"JavaScript","readme":"Modular CSS with postCSS and npm scripts\n========================================\n\nThis is an experiment in achieving 'modular CSS' by use of postCSS as a build-step, invoked\nby appropriately constructed npm scripts. We start out with an example project (see\n`./index.html` / `./src`) which uses a BEM-ish approach to enforce modular styles. We then\ngradually tweak it until we get to the point where we can get rid of the unique prefixes and\nthe relevant maintenance hassle.\n\nThere are 5 stages to this, 0 to 4, which are laid out below. For each stage you can\n`git checkout` the relevant tag (`0basics` to `3usefulScripts`) to force the example project's\nsource to the state which is relevant to the stage.\n\n\n0: Basics\n---------\n\n* `npm run serve`: **Run a local dev server on port 8888.** (Depends on\n    [local-web-server](https://www.npmjs.com/package/local-web-server), a simple web-server\n    for productive front-end development.)\n* `js:bundle`: **Build a JS bundle.** (Depends on\n    [requirejs](https://www.npmjs.com/package/requirejs), the node adapter for RequireJS,\n    for loading AMD modules. Includes the RequireJS optimizer.)\n* `css:bundle`: **Build a CSS bundle.** (Depends on\n    [node-sass](https://www.npmjs.com/package/node-sass), the node bindings for the Sass\n    stylesheet preprocessor.) This will transpile all the `*.scss` files in our project and output\n    a `bundle.css` at the root of our app - which is the (one-and-only) CSS file referenced in\n    `index.html`. Note that `css:bundle` relies on `style/style.scss` to 'know' which `.scss` files\n    to bundle. We need to maintain `style/style.scss` as we add/remove/relocate `.scss` files.\n* `css:bundle-when-styles-change`: **Watch for style changes and rebuild CSS bundle in response.**\n    (Depends on [node-sass](https://www.npmjs.com/package/node-sass) and\n    [onchange](https://www.npmjs.com/package/onchange). The latter module facilitates the use of\n    glob patterns to watch file sets and run commands when anything is added, changed or deleted.)\n\n1: PostCSS - Does this thing even work?\n---------------------------------------\n\nInstall [postcss](https://www.npmjs.com/package/postcss). Also install\n[postcss-cli](https://www.npmjs.com/package/postcss-cli), the command line for postcss.\n\nLet's create an experimental `css:prefix` script based on\n[autoprefixer](https://www.npmjs.com/package/autoprefixer) (yes, install that too). Take a\nlook at [browserslist](https://github.com/ai/browserslist) for a way to configure autoprefixer\n(go ahead and add a browserslist file). Our script should look like:\n\n```json\n{\n  \"css:prefix\": \"postcss -u autoprefixer\"\n}\n```\n\ntry `npm run css:prefix -- ./src/views/ui/users/user-plain/user-plain.scss`.\n\n(The `--` token allows passing custom arguments to invoked scripts, courtecy of\n[npm's `run-script`](https://docs.npmjs.com/cli/run-script).)\n\n\n2: Enter the CSS module\n-----------------------\n\nOkay, we're now ready to add a `css:create-module` npm script. Let's install\n[postcss-modules](https://www.npmjs.com/package/postcss-modules) and create a new script based on\nthe previous `css:prefix`:\n\n```json\n{\n  \"css:create-module\": \"postcss -u autoprefixer -u postcss-modules\"\n}\n```\n\nUsing autoprefixer is not really relevant at this point but it's a nice-to-have so let's leave it\nin there. Try out our new script with\n`npm run css:create-module -- ./src/views/ui/users/user-plain/user-plain.scss`. Notice the\ngenerated `.scss.json`. Revel in its glory.\n\nWe now have a method of uniquefying the class names per module without having to manually prefix\nthem. Let's pick a module and remove all prefixes, applying our `create-module` script and making use\nof the generated JSON files to get the unique class names into our templates.\n\nWe'll have to run `css:create-module` script with the `-o` switch to generate a `scss.module` file:\n\n```bash\nnpm run css:create-module -- -o ./src/views/.../foo.scss.module ./src/views/.../foo.scss\n```\n\nHaving generated the `.scss.module` file we'll have to `@import` it in `styles/modules.scss` in\nplace of the original `.scss` file: It is the `.scss.module` file that contains the uniquefied\nclass names that we want in our stylesheets. On the JS side, we'll have to swap direct references to\nclass names for references to attributes in the generated `.scss.json` file. Something along the\nlines of:\n\n```javascript\nvar classNames = JSON.parse(require('./foo.scss.json'));\n\n// .. and then, further down\n$(classNames.title).text('War and Peace'); // Instead of $('.title').text('War and Peace')\n```\n\n\n3: Useful scripts\n-----------------\n\nWe can go over each and every one of our defined modules applying step 2. We will _have to_, given\nthat we need to change all our scripts to make use of generated JSON files when referencing class\nnames. However, we naturally want to automate the creation of CSS-modules. So here's the scripts that\nwe'll be using:\n\n#### `css:create-module`\n\nWe already have that. We can run it as described in step 2 above to generate the `scss.module` and\n`scss.json` files per module. (Remember to run `css:bundle` afterwards, in order to get the updated\nstyles into `bundle.css`.)\n\n#### `css:create-modules`\n\nNotice the `s` at the end. This is a script to go over _all_ defined modules in our code and run\n`css:create-module` on them. This is a necessity as we don't want to be manually iterating our\ncodebase looking for modules and re-running `css:create-module` all the time. A user checking out\nour repo will start out without any `scss.module` or `scss.json` files (these are _generated_ and\nas such _not versioned_). To generate _all_ of them it should be enough to run this script. The\nimplementation will be based on [bash find](http://linux.die.net/man/1/find):\n\n```json\n{\n  \"css:create-modules\":\n    \"find ./src -iname '*.scss' -exec npm run css:create-module -- -o '{}.module' '{}' \\\\;\"\n}\n```\n\n(The `{}` token is the path of the found file, available courtecy of `find`.)\n\n#### `css:create-module-when-styles-change`\n\nWatch `.scss` files and whenever they change, re-create `scss.module` / `scss.json`. So that we\ndon't have to do it manually. We can use [onchange](https://www.npmjs.com/package/onchange) for the\nwatching and delegate back to `css:create-module`:\n\n```json\n  \"css:create-module-when-styles-change\":\n    \"onchange 'src/**/*.scss' -v -- npm run css:create-module -- -o '{{changed}}.module' '{{changed}}'\",\n```\n\n(The `{{changed}}` token is the path of the changed file, available courtecy of `onchange`.)\n\n#### `css:bundle`\n\nWe've had this script all along, even before we introduced any of the modular CSS stuff. It'll always\nhave to be run after a `css:create-module` to get the new styles into `bundle.css`. As was previously\nmentioned, the bundle script relies on the presence of a `styles/modules.scss` file which enumerates\n(`@import`s) each and every `scss.module` file in our project. This is obviously a maintenance\nhassle - idealy, we'd like to automate this as well. This brings us to\n\n\n4: More useful scripts\n----------------------\n\n#### `css:collect-modules`:\n\nCollect all `scss.module` files into the `styles/modules.scss` 'import-list'. This is yet another\napplication of `find`:\n\n```json\n  \"css:collect-modules\":\n    \"find ./src -iname '*.scss.module' -exec echo '@import \\\"{}\\\";' \u003e ./style/modules.scss \\\\;\"\n```\n\n#### `css:collect-modules-and-bundle` / `-when-module-changes`\n\nCollect all modules and then (re)create the CSS bundle. This is just a sequential combination of\nother scripts we've already put together. It's quite typical however so it's worth a dedicated\nscript of its own. We'd also like to be able to run this automatically, watching the project's files\nand responding to any CSS module changing (or being added). This, again, can be done with `onchange`:\n\n```json\n  \"css:collect-modules-and-bundle\": \"npm run css:collect-modules \u0026\u0026 npm run css:bundle\",\n  \"css:collect-modules-and-bundle-when-module-changes\":\n    \"onchange 'src/**/*.scss.module' -v -- npm run css:collect-modules-and-bundle\"\n```\n\n#### `css:watch`\n\nThis is our\n[finishing move](http://www.accelerator3359.com/Wrestling/pictures/finishers/hoganlegdrop.jpg). Watch\nthe project's files and a) (re)create CSS modules when any style changes, b) (re)create entire CSS\nbundle when any module changes (or is added). We already have these scripts - we just combine them\ninto the handy `css:watch` that we can run and forget:\n\n```json\n  \"css:watch\":\n    \"npm run css:create-module-when-styles-change \u0026 npm run css:collect-modules-and-build-when-module-changes \u0026\"\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbiril%2Fmodcss","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbiril%2Fmodcss","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbiril%2Fmodcss/lists"}