{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"CSS modules","llmstxt":{"hide":true}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"css-modules","__idx":0},"children":["CSS modules"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"css-what","__idx":1},"children":["CSS what?"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For a quick breakdown on what CSS modules are, check out ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"http://glenmaddern.com/articles/css-modules"},"children":["Glen Maddern's post"]}," which summarizes pretty well."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"how-theyre-used-here","__idx":2},"children":["How they're used here"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["CSS modules allow for module-scoped styling for components. This is done by ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["require"]},"ing the styles file and allowing the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"https://github.com/webpack/css-loader"},"children":["Webpack CSS loader"]}," to process the file as a module. Since there are some styles that need to remain global (mainly webfonts and styles for 3rd party components), we selectively use the CSS module loader through a naming convention of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".module.less"]}," for modules vs simply ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".less"]}," for a non-CSS-module Webpack loader chain."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Whenever a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".module.less"]}," file is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["require"]},"d, it will be passed through the CSS module loader and have all it's class names transformed and exported. CSS modules also have a mechanism for extending and sharing class names across files through the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["composes"]}," keyword. Any file that is referenced by a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["compose"]}," will also be processed as a CSS module, regardless of file extension. In this way, we can use a normal ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".less"]}," file in a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["compose"]}," and gain the benefit of scoped, shared style classes while still letting the styles be used in a more traditional context as necessary (like being referenced though a LESS ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["extend"]}," which would break if class names were transformed). In the following example, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["coolText.less"]}," will be processed and have a scoped form of neatStyle generated (something like ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["coolText_neatStyle__3woeh"]},") which will be paired with the scoped form of ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["awesomeClass"]}," in the CSS module export list."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"css","header":{"controls":{"copy":{}}},"source":".awesomeClass {\n  composes: neatStyle from '../coolText.less'\n}\n","lang":"css"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In general, all of the components will have a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".module.less"]}," as the styles are ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["require"]},"d from within the JavaScript of the component. The files under ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/styles/core"]}," are a slightly mixed bag as they aren't generally ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["require"]},"d individually from a JavaScript file (excepting ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["main.less"]},"). The files in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/core"]}," marked as modules don't use any module-incompatible LESS syntax features and are intended to be used as single-responsibility modules solely through the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["composes"]}," keyword from other ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".module.less"]}," files. The plain ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":[".less"]}," files can be used through ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["composes"]},", but for one reason or another require the ability to be used in a global context in addition to a scoped context and therefore cannot be exclusively loaded by the Webpack CSS module loader."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"concerning-classnames","__idx":3},"children":["Concerning classnames"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When creating names for classes in a CSS module, it's good to keep in mind the final use for the file. If one is going to be ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["require"]},"ing the file for inclusion in a JavaScript module, then a good practice is to keep all the names camelCase in order to ease addressing them in React/JSX components. For example,"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"css","header":{"controls":{"copy":{}}},"source":".classOne {\n  color: #BADA55;\n}\n.class-two {\n  color: #C0FFEE;\n}\n","lang":"css"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In order to use these class names in JSX it would look something like this:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"JavaScript","header":{"controls":{"copy":{}}},"source":"<div className={styles.classOne}>One</div>\n<div className={styles['class-two']}>Two</div>\n","lang":"JavaScript"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["where the first is less cumbersome."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If the module that you're creating will be a single-responsibility module (like ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["typography"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["layout"]},") and will only ever have it's class names referenced by external ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["composes"]}," from other modules, then the advantage of the JSX syntax simplicity isn't present. If there's some reason to not use camelCase (e.g. legacy code or third party dependency) then it may make more sense to use another naming scheme. In general, for consistency, default to camelCase when possible."]}]},"headings":[{"value":"CSS modules","id":"css-modules","depth":1},{"value":"CSS what?","id":"css-what","depth":2},{"value":"How they're used here","id":"how-theyre-used-here","depth":2},{"value":"Concerning classnames","id":"concerning-classnames","depth":2}],"frontmatter":{"seo":{"title":"CSS modules"}},"lastModified":"2026-05-28T16:33:56.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/docs/uploader/misc/cssmodules","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}