{"id":14962253,"url":"https://github.com/shiyangzhaoa/css-modules-to-tailwind","last_synced_at":"2025-09-08T08:32:05.358Z","repository":{"id":65109262,"uuid":"534119659","full_name":"shiyangzhaoa/css-modules-to-tailwind","owner":"shiyangzhaoa","description":"Tailwind css convert tool","archived":false,"fork":false,"pushed_at":"2024-07-22T07:24:04.000Z","size":783,"stargazers_count":32,"open_issues_count":5,"forks_count":5,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-12-26T23:05:19.459Z","etag":null,"topics":["codemod","command-line-tool","reactjs","tailwind-css","tailwindcss","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/shiyangzhaoa.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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":"2022-09-08T08:28:46.000Z","updated_at":"2024-11-07T09:01:54.000Z","dependencies_parsed_at":"2023-02-19T16:01:41.053Z","dependency_job_id":"627ccc52-36e7-4ba4-b5ff-8a66c69b3ddd","html_url":"https://github.com/shiyangzhaoa/css-modules-to-tailwind","commit_stats":{"total_commits":39,"total_committers":4,"mean_commits":9.75,"dds":0.3589743589743589,"last_synced_commit":"aa19d9c2063f9c2719bf5668af89a95e8413ce4d"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shiyangzhaoa%2Fcss-modules-to-tailwind","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shiyangzhaoa%2Fcss-modules-to-tailwind/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shiyangzhaoa%2Fcss-modules-to-tailwind/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shiyangzhaoa%2Fcss-modules-to-tailwind/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shiyangzhaoa","download_url":"https://codeload.github.com/shiyangzhaoa/css-modules-to-tailwind/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":232293182,"owners_count":18500734,"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":["codemod","command-line-tool","reactjs","tailwind-css","tailwindcss","typescript"],"created_at":"2024-09-24T13:29:46.960Z","updated_at":"2025-09-08T08:32:05.341Z","avatar_url":"https://github.com/shiyangzhaoa.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CSS Modules to Tailwind CSS\n\nThis is a tool to convert css-modules to tailwind-css\n\n\u003cp\u003e\n  \u003cimg src=\"./logo.svg\" alt=\"Tailwind Tool\"\u003e\n\u003c/p\u003e\n\u003cp\u003e\n  \u003ca href=\"https://www.npmjs.com/package/css-modules-to-tailwind\"\u003e\u003cimg src=\"https://img.shields.io/npm/dm/css-modules-to-tailwind?style=flat-square\" alt=\"Total Downloads\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/css-modules-to-tailwind\"\u003e\u003cimg src=\"https://img.shields.io/bundlephobia/minzip/css-modules-to-tailwind?style=flat-square\" alt=\"Latest Release\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/shiyangzhaoa/css-modules-to-tailwind/blob/main/LICENSE\"\u003e\u003cimg src=\"https://shields.io/github/license/shiyangzhaoa/css-modules-to-tailwind?style=flat-square\" alt=\"License\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n## Support list\n\n- [x] tsconfig.json alias support, like `alias/component/index.module.css`\n- [x] css file circular reference\n- [x] project level support, just run this command: `npx css-modules-to-tailwind src/**/*.tsx`\n- [x] arbitrary values support, `margin: 15px` =\u003e `m-[15px]`\n- [ ] pseudo-classes support\n- [x] tailwind prefixes support, e.g. `tw:`\n\n## About\n\n- [CSS Modules](https://github.com/css-modules/css-modules)\n- [Tailwind CSS](https://tailwindcss.com/)\n\n## Install\n\nGlobal install:\n\n  ```shell\n  npm install css-modules-to-tailwind -g\n  ```\n\nOr use `npx`:\n\n  ```shell\n  npx css-modules-to-tailwind src/index.tsx\n  // npx css-modules-to-tailwind src/**/*.tsx\n  ```\n\nIt will check your git directory is clean, you can use '--force' to skip the check.\n\n## How it works\n\nIt uses [jscodeshift](https://github.com/facebook/jscodeshift) and [postcss](https://github.com/postcss/postcss).\n\nTry it yourself:\n\n1. First, Create a new jsx/tsx file(index.tsx/jsx):\n\n   ```tsx\n   import React from 'react';\n   import style from './index.module.css';\n\n   export const User = () =\u003e (\n     \u003cdiv className={style.header}\u003e\n       \u003cdiv className={style.user}\u003e\n         \u003cimg className={style.avatar} alt=\"avatar\" /\u003e\n         \u003cspan className={style.username}\u003eusername\u003c/span\u003e\n       \u003c/div\u003e\n       \u003cdiv className={style.channelName}\u003ename\u003c/div\u003e\n     \u003c/div\u003e\n   );\n   ```\n\n2. Create a new css modules file:\n\n   ```css\n   .header {\n     width: 100%;\n     display: flex;\n     align-items: center;\n     justify-content: space-between;\n   }\n \n   .user {\n     display: flex;\n     align-items: center;\n     font-weight: bold;\n   }\n\n   .avatar {\n     width: 0.625rem;\n     height: 0.625rem;\n   }\n\n   .username {\n     font-size: 0.75rem;\n     line-height: 1rem;\n     color: #7DD3FC;\n     margin-left: 0.25rem;\n   }\n   ```\n\n3. Use this tool now:\n\n   ```shell\n   npx css-modules-to-tailwind index.tsx\n   ```\n\n4. You will get:\n\n   ```ts\n   // index.tsx\n   import React from 'react';\n\n   export const User = () =\u003e (\n     \u003cdiv className='items-center flex justify-between w-full'\u003e\n       \u003cdiv className='items-center flex font-bold'\u003e\n         \u003cimg className='h-2.5 w-2.5' alt=\"avatar\" /\u003e\n         \u003cspan className='text-sky-300 text-xs ml-1'\u003eusername\u003c/span\u003e\n       \u003c/div\u003e\n       \u003cdiv className={` `}\u003ename\u003c/div\u003e\n     \u003c/div\u003e\n   );\n   ```\n\n   \u003e If the css file content is empty, import specifiers and css files will be removed, unused class will be replaced with \\` \\`, You should search globally for \\` \\`, then delete them.\n\n🙋‍♂️ Flat and single structure design makes this tool work better.\n\n## Only css-modules?\n\nOf course not. It can also be used for less/scss modules, but it doesn't work very well, like:\n\n```less\n.selector1 {\n  selector2();\n}\n\n.selector2 {\n  font-size: 0.75rem;\n  line-height: 1rem;\n}\n```\n\nIt just becomes:\n\n```less\n.selector1 {\n  selector2();\n}\n```\n\nI think you should use `composes`.\n\n## Inappropriate scenes\n\n### Unreasonable nesting\n\n```tsx\nimport style form 'index.module.css';\n\nconst User = () =\u003e (\n  \u003c\u003e\n    \u003cdiv className={style.parentA}\u003e\n      \u003cdiv className={style.childrenA}\u003echildrenA\u003c/div\u003e\n    \u003c/div\u003e\n    \u003cdiv className={style.parentB}\u003e\n      \u003cdiv className={style.childrenA}\u003echildrenA\u003c/div\u003e\n    \u003c/div\u003e\n  \u003c/\u003e\n);\n```\n\n```css\n.parentA {\n  .childrenA {\n    // some decl\n  }\n}\n```\n\nYou shouldn't use nesting as namespace.\n\n### You should not write multiple/conflicting declarations in a selector\n\n```tsx\nimport clsx from 'clsx';\nimport style form 'index.module.css';\n\nconst User = () =\u003e (\n  \u003c\u003e\n    \u003cdiv className={clsx(style.cls1, style.cls2)}\u003e\u003c/div\u003e\n  \u003c/\u003e\n);\n```\n\n```css\n.cls1 {\n  margin-left: 0.5rem;\n  display: none;\n}\n\n.cls2 {\n  margin-left: 0.375rem;\n  display: block\n}\n```\n\nAlways, it will become like this:\n\n```tsx\nconst User = () =\u003e (\n  \u003c\u003e\n    \u003cdiv className={clsx('hidden ml-2', 'block ml-1.5')}\u003e\u003c/div\u003e\n  \u003c/\u003e\n);\n```\n\nI mean, in tailwind, \"`ml-2 ml-1.5`\" === \"`ml-2`\", but in your code, is the latter declaration overriding the former.\n\n## Support detail\n\n### Composes\n\n1. Quote itself\n\n   ```css\n   .class1 {\n     display: flex;\n   }\n\n   .class2 {\n     compose: class1\n   }\n   ```\n\n   it just becomes:\n\n   ```css\n   .class1 {\n     @apply flex;\n   }\n\n   .class2 {\n     composes: class1\n   }\n   ```\n\n2. Other CSS file:\n\n   ```css\n   /** index1.module.css */\n   .test1 {\n     display: flex;\n   }\n\n   /** index2.module.css */\n   .test2 {\n     composes: test1 from './index1.module.css'\n   }\n   ```\n\n   `index1.module.css` will be removed, and `index2.module.css`:\n\n   ```css\n   .test2 {\n     @apply flex;\n   }\n   ```\n\n### Multiple states\n\nFor example:\n\n```css\n.button {\n  width: 1.25rem; /* 20px */\n}\n\n.box .button {\n  width: 2rem; /* 32px */\n}\n```\n\nIt just becomes:\n\n```css\n.button {\n  @apply w-5; /* 20px */\n}\n\n.box .button {\n  @apply w-8; /* 32px */\n}\n```\n\nClasses with multiple states will not do too much processing, because I don't know if there is a conflict between the states.\n\n### Permutations\n\nMultiple style declarations can form a Tailwind CSS class. For example:\n\n```css\n.truncate {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n```\n\n```tsx\nconst Com = () =\u003e \u003cdiv className={style.truncate}\u003etext\u003c/div\u003e\n```\n\nIt will become:\n\n```tsx\nconst Com = () =\u003e \u003cdiv className='truncate'\u003etext\u003c/div\u003e\n```\n\nOf course, it supports more complex permutations and combinations, you can try it.\n\n### Tailwind Prefixes\n\nFor example:\n\n```css\n.tw-bg-red-500 {\n  background-color: #f56565;\n}\n```\n\n```tsx\nconst Com = () =\u003e \u003cdiv className='tw-bg-red-500'\u003etext\u003c/div\u003e\n```\n\n```\nnpx css-modules-to-tailwind src/**/*.tsx --prefix=tw:\n```\n\nIt will become:\n\n```tsx\nconst Com = () =\u003e \u003cdiv className='tw:bg-red-500'\u003etext\u003c/div\u003e\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshiyangzhaoa%2Fcss-modules-to-tailwind","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshiyangzhaoa%2Fcss-modules-to-tailwind","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshiyangzhaoa%2Fcss-modules-to-tailwind/lists"}