{"id":15015766,"url":"https://github.com/soxhub/ember-scoped-css","last_synced_at":"2025-04-12T09:32:56.879Z","repository":{"id":181310591,"uuid":"604514645","full_name":"soxhub/ember-scoped-css","owner":"soxhub","description":null,"archived":false,"fork":false,"pushed_at":"2024-04-29T00:31:22.000Z","size":1981,"stargazers_count":11,"open_issues_count":17,"forks_count":0,"subscribers_count":40,"default_branch":"main","last_synced_at":"2024-05-01T23:24:31.244Z","etag":null,"topics":["addon","build","css","ember","emberjs","hacktoberfest","library","package","scoped","styles","tool"],"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/soxhub.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","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":"2023-02-21T08:13:35.000Z","updated_at":"2024-05-22T14:00:17.034Z","dependencies_parsed_at":"2023-11-22T18:32:08.726Z","dependency_job_id":"1a13298a-02e2-460c-b136-a5bb07d67122","html_url":"https://github.com/soxhub/ember-scoped-css","commit_stats":null,"previous_names":["soxhub/ember-scoped-css"],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soxhub%2Fember-scoped-css","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soxhub%2Fember-scoped-css/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soxhub%2Fember-scoped-css/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soxhub%2Fember-scoped-css/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/soxhub","download_url":"https://codeload.github.com/soxhub/ember-scoped-css/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248546325,"owners_count":21122294,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["addon","build","css","ember","emberjs","hacktoberfest","library","package","scoped","styles","tool"],"created_at":"2024-09-24T19:47:54.086Z","updated_at":"2025-04-12T09:32:56.860Z","avatar_url":"https://github.com/soxhub.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ember-scoped-css\n\n`ember-scoped-css` is a modern addon that allows you to isolate your CSS in a modular way with co-located scoped CSS. This is a build-time-only addon and therefore is fully supported if your app is built with Embroider.\n\nWith `ember-scoped-css` you can write your component styles in a co-located `.css` file next to your `.hbs` or `.gjs/.gts` files. Every selector you write in your styles is automatically scoped to the component. So you can develop your component with styles isolated from the rest of the application and you don't have to worry about CSS selectors collisions or issues with the CSS cascade.\n\nIf you want to read more specifics on how this addon achieves isolation with CSS you can read more in the [detailed CSS isolation documentation](docs/css-isolation.md)\n\nAs selectors are scoped/renamed during the build process. So there is no performance hit when running the app.\n\nThe philosophy of `ember-scoped-css` is to stick as close to CSS and HTML as possible and not introduce new syntax or concepts unless it is absolutely necessary. \n\nYou may also find the docs on [CSS `@layer`](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer) interesting.\nThis build tool emits CSS in a `@layer`.\n\n## Compatibility\n\n- Vite\n- V2 addons\n- non-embroider apps \n- embroider apps\n\n| You Have | ember-scoped-css | ember-scoped-css-compat |\n| -------- | ----------- | ---------------------- |\n| ember-template-imports@v4 or babel-plugin-ember-template-compilation@2.2.5+ | 0.19.0 | 10.0.0 |\n| ember-template-imports@v3 or babel-plugin-ember-template-compilation@2.2.1 or rollup-plugin-glimmer-template-tag | \u003c= 0.18.0 | \u003c= 9.0.0 |\n| classic components | \u003c= 0.18.0 | \u003c= 8.0.0 |\n| ember \u003c 4 | \u003c= 0.18.0 | \u003c= 8.0.0 |\n\n## Installation for a Vite app\n\n```bash\nnpm install --save-dev ember-scoped-css\n```\n\n### Configuration\n\nIn your `vite.config.js`, import and add the `scopedCSS` plugin:\n```js\nimport { defineConfig } from 'vite';\nimport { scopedCSS } from 'ember-scoped-css/vite';\n\nexport default defineConfig({\n  // ...\n  plugins: [\n    scopedCSS(),\n    // ...\n  ],\n});\n```\n\nand then in your `babel.config.cjs`, add a template-transform:\n```js\nconst scopedCSS = require(\"ember-scoped-css/build\");\n\nmodule.exports = {\n  plugins: [\n    // ...\n    [\n      'babel-plugin-ember-template-compilation',\n      {\n        // ...\n        transforms: [scopedCSS.templatePlugin({})],\n      },\n    ],\n    // ...\n  ],\n  // ...\n};\n\n```\n\n## Installation for a non-embroider ember app\n\n```bash\nnpm install --save-dev ember-scoped-css ember-scoped-css-compat\n```\n\n### Configuration\n\nIn your `ember-cli-build.js`, you can configure the behavior of scoped-css transformations within the app via \n```js \n\nconst app = new EmberApp(defaults, { \n  /* ... */ \n  'ember-scoped-css': {\n    layerName: 'app-styles', // default: 'components', set to false to disable the layer\n    additionalRoots: ['routes/'], // default: [], set this to use scoped-css in pods-using apps\n    passthrough: ['some-other-file.css'], // default: [] this is only used in a non-embroider app to pass files through the build pipeline\n    passthroughDestination: 'assets' // default: undefined this alters where the passthrough files are placed in the output tree\n  }\n});\n```\n\nNote that supporting `pods` is _opt in_, because all apps can have their pods root directory configured differently.\n\n## Installation for an embroider app\n\n```bash \nnpm install --save-dev ember-scoped-css ember-scoped-css-compat\n```\n\nSetup webpack:\n```js \n// ember-cli-build.js\nmodule.exports = async function (defaults) {  \n  const app = new EmberApp(defaults, { /* ... */ });\n\n  const { Webpack } = require('@embroider/webpack');\n\n  return require('@embroider/compat').compatBuild(app, Webpack, {\n    /* ... */\n    packagerOptions: {\n      webpackConfig: {\n        module: {\n          rules: [\n            // css loaders for your app CSS\n            {\n              test: /\\.css$/,\n              use: [\n                {\n                  loader: require.resolve(\n                    'ember-scoped-css/build/app-css-loader'\n                  ),\n                  options: {\n                    layerName: 'the-layer-name', // optional\n                  }\n                },\n              ],\n            },\n          ],\n        },\n      },\n    },\n  });\n}\n```\n\n## Installation for a V2 Addon\n\n```\nnpm install --save-dev ember-scoped-css\n```\n\n1. If you want to use `.gjs/gts` components, [`@embroider/addon-dev`](https://github.com/embroider-build/embroider/tree/main/packages/addon-dev) provides a plugin for you, `addon.gjs()`.\n\n\u003cdetails\u003e\u003csummary\u003eAn older approach\u003c/summary\u003e\n\nThere is a deprecated plugin (superseded by `@embroider/addon-dev`) that uses ember-template-imports -- to use this follow the instructions from [rollup-plugin-glimmer-template-tag](https://github.com/NullVoxPopuli/rollup-plugin-glimmer-template-tag) addon.\n\nThis plugin is not recommended, and is archived.\n\n\u003c/details\u003e\n\n2. Add the following to your `rollup.config.mjs`:\n\n```diff\n+ import { scopedCssUnplugin } from 'ember-scoped-css/build';\n\n// if you want to have some global styles in your addon then\n// put them in the styles folder and change the path to the styles folder\n// if there are no global styles then you can remove addon.keepAssets\n- addon.keepAssets(['**/*.css']),\n+ addon.keepAssets(['**/styles/*.css']),\n\n// add the following to the rollup config\n+ scopedCssUnplugin.rollup(),\n```\n\nNote that if you're using [`rollup-plugin-ts`](https://github.com/wessberg/rollup-plugin-ts), `scopedCssUnpulugin.rollup()` must come before `typescript(/*...*/)` \n\n### Configuration\n\nIn the rollup config, you may pass options:\n\n```js \nscopedCssUnplugin.rollup({ \n  layerName: 'utilities', // default: 'components', set to false to disable the layer\n});\n```\n\n## Usage\n\nWith `ember-scoped-css` you define styles in `.css` files that are colocated with your components\n\n```hbs\n{{! src/components/my-component.hbs }}\n\u003cdiv data-test-my-component class='hello-class header'\u003e\u003cb\u003eHello\u003c/b\u003e, world!\u003c/div\u003e\n```\n\n```css\n/* src/components/my-component.css */\n.hello-class {\n  color: red;\n}\n\n/* the :global() pseudo-class is used to define a global class. It mean that header class wont be scoped to that component */\n.hello-class:global(.header) {\n  font-size: 20px;\n}\n\nb {\n  color: blue;\n}\n```\n\nNOTE: that if you're using pods, css co-located with templates/routes/etc will need to be named `styles.css`\n\n\n\n### Passing classes as arguments to a component\n\nThere is a `scoped-class` helper that you can use to pass a class name as an argument to a component. The helper takes a class name and returns a scoped class name. `scoped-class` helper is replaced at build time so there is no performance hit when running the app.\n\n```hbs\n{{! src/components/my-component.hbs }}\n\u003cOtherComponent @internalClass={{scoped-class 'hello-class'}} /\u003e\n\u003cOtherComponent @internalClass={{(scoped-class 'hello-class')}} /\u003e\n\u003cOtherComponent\n  @internalClass={{concat (scoped-class 'hello-class') ' other-class'}}\n/\u003e\n```\n\nIn gjs/gts/`\u003ctemplate\u003e`, the above would look like:\n```gjs\nimport { scopedClass } from 'ember-scoped-css';\n\n\u003ctemplate\u003e\n  \u003cOtherComponent @internalClass={{scopedClass 'hello-class'}} /\u003e\n  \u003cOtherComponent @internalClass={{(scopedClass 'hello-class')}} /\u003e\n  \u003cOtherComponent\n    @internalClass={{concat (scopedClass 'hello-class') ' other-class'}}\n  /\u003e\n\u003c/template\u003e\n```\n\n## Testing\n\nAs classes are renamed during the build process you can't directly verify if classes are present in your tests. To solve this problem you can use the `scopedClass` function from the `ember-scoped-css/test-support` module. The function takes the class names and path to the CSS file where are the classes defined and returns the scoped class names.\n\nThe path to the CSS file is always relative to the V2 addon root no matter where the test is located.\n\n```js\nimport { scopedClass } from 'ember-scoped-css/test-support';\n\ntest('MyComponent has hello-class', async function (assert) {\n  assert.expect(1);\n\n  await render(hbs`\n    \u003cMyComponent /\u003e\n  `);\n\n  const rewrittenClass = scopedClass(\n    'hello-class',\n    '\u003cmodule-name\u003e/components/my-component'\n  );\n\n  assert.dom('[data-test-my-component]').hasClass(rewrittenClass);\n});\n```\n\n## Linting\n\n`ember-scoped-css` exports a ember-template-lint plugin with one rule `scoped-class-helper`. This lint rule is intended to help you prevent improper use of the `scoped-class` helper which might not be immediately obvious during regular development. You can read more information in the [lint rules documentation](docs/lint-rules.md)\n\n### Steps for adding the rule to the project\n\n1. Add `ember-scoped-css` plugin to `.template-lintrc.js`\n\n```diff\n'use strict';\n\nmodule.exports = {\n\tplugins: [\n+    'ember-scoped-css/src/template-lint/plugin'\n  ],\n\n```\n\n2. Add `scoped-class-helper` rule to `.template-lintrc.js`\n\n```diff\n'use strict';\n\nmodule.exports = {\n\tplugins: [\n    'ember-scoped-css/src/template-lint/plugin'\n  ],\n  rules: {\n+    'scoped-class-helper': 'error',\n  }\n\n```\n\n## License\n\nThis project is licensed under the [MIT License](LICENSE.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoxhub%2Fember-scoped-css","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoxhub%2Fember-scoped-css","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoxhub%2Fember-scoped-css/lists"}