{"id":19777324,"url":"https://github.com/catamphetamine/react-styling","last_synced_at":"2025-06-22T06:02:59.943Z","repository":{"id":34674382,"uuid":"38647383","full_name":"catamphetamine/react-styling","owner":"catamphetamine","description":"Transforms CSS-alike text into a React style JSON object","archived":false,"fork":false,"pushed_at":"2017-09-17T08:17:50.000Z","size":660,"stargazers_count":121,"open_issues_count":0,"forks_count":5,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-06-04T21:43:27.536Z","etag":null,"topics":["css","react"],"latest_commit_sha":null,"homepage":null,"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/catamphetamine.png","metadata":{"files":{"readme":"README.md","changelog":"HISTORY.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-06T21:29:18.000Z","updated_at":"2024-09-29T10:58:20.000Z","dependencies_parsed_at":"2022-08-28T11:11:32.240Z","dependency_job_id":null,"html_url":"https://github.com/catamphetamine/react-styling","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/catamphetamine/react-styling","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/catamphetamine%2Freact-styling","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/catamphetamine%2Freact-styling/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/catamphetamine%2Freact-styling/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/catamphetamine%2Freact-styling/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/catamphetamine","download_url":"https://codeload.github.com/catamphetamine/react-styling/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/catamphetamine%2Freact-styling/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261243972,"owners_count":23129634,"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":["css","react"],"created_at":"2024-11-12T05:24:20.476Z","updated_at":"2025-06-22T06:02:54.934Z","avatar_url":"https://github.com/catamphetamine.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# react-styling\n\n[![npm version](https://img.shields.io/npm/v/react-styling.svg?style=flat-square)](https://www.npmjs.com/package/react-styling)\n[![npm downloads](https://img.shields.io/npm/dm/react-styling.svg?style=flat-square)](https://www.npmjs.com/package/react-styling)\n[![build status](https://img.shields.io/travis/catamphetamine/react-styling/master.svg?style=flat-square)](https://travis-ci.org/catamphetamine/react-styling)\n[![coverage](https://img.shields.io/coveralls/catamphetamine/react-styling/master.svg?style=flat-square)](https://coveralls.io/r/catamphetamine/react-styling?branch=master)\n\nIs a helper function to convert various CSS syntaxes into a React style JSON object\n\n## Autoprefixing\n\nThis library doesn't perform CSS autoprefixing. Use [postcss autoprefixer](https://github.com/postcss/postcss-js) for that.\n\n## Installation\n\n```bash\n$ npm install react-styling\n```\n\n## Usage\n\nThis module uses an ES6 feature called [template strings](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings) which allows you to write multiline strings (finally). You can still use this module with the old ES5 (regular javascript) syntax passing it a regular string, but it's much more convenient for you to just use [Babel](https://babeljs.io/docs/setup/) for ES6 to ES5 conversion (everyone out there does it by the way).\n\n```javascript\nimport React from 'react'\nimport styler from 'react-styling'\n\nexport default class Page extends React.Component\n{\n  render()\n  {\n    return (\n      \u003cdiv\u003e\n        \u003cheader\u003e\n          \u003cul style={style.menu}\u003e\n            \u003cli style={style.menu.item}\u003e\u003cLink to=\"login\" style={style.menu.item.link} activeStyle={style.menu.item.link.current}\u003eLogin\u003c/Link\u003e\u003c/li\u003e\n            \u003cli style={style.menu.item}\u003e\u003cLink to=\"about\" style={style.menu.item.link} activeStyle={style.menu.item.link.current}\u003eAbout\u003c/Link\u003e\u003c/li\u003e\n          \u003c/ul\u003e\n        \u003c/header\u003e\n\n        \u003cRouteHandler/\u003e\n      \u003c/div\u003e\n    )\n  }\n}\n\nconst style = styler\n`\n  menu\n    list-style-type: none\n\n    item\n      display: inline-block\n\n      link\n        display         : inline-block\n        text-decoration : none\n        color           : #000000\n        padding         : 0.4em\n\n        // notice the ampersand character here:\n        // this feature is called a \"modifier\" class \n        // (see the \"Modifiers\" section of this document)\n        \u0026current\n          color            : #ffffff\n          background-color : #000000\n\n  // supports comma separated style classes\n  // and further style class extension\n  \n  can_style, multiple_classes, at_once\n    font-family : Sans\n\n  can_style\n    font-size : 12pt\n\n  multiple_classes, at_once\n    font-size : 8pt\n\n  /*\n  multi\n  line\n  comment\n  */\n\n  .old-school-regular-css-syntax {\n    box-sizing: border-box;\n    color: black;\n  }\n\n  .scss_less {\n    color: white;\n\n    \u0026:hover {\n      text-decoration: underline;\n    }\n  }\n\n  curly_braces_fan {\n    background: none\n\n    curly_braces_fan_number_two {\n      background: transparent\n    }\n  }\n\n  YAML_fan:\n    display: inline-block\n\n    python:\n      length: 99999px\n\n  // for Radium users\n  @media (min-width: 320px)\n    width: 100%\n\n    :hover \n      background: white\n`\n```\n\nThe example is self-explanatory. The CSS text in the example above will be transformed to this JSON object\n\n```javascript\n{\n  menu:\n  {\n    listStyleType: 'none',\n\n    item:\n    {\n      display: 'inline-block',\n\n      link:\n      {\n        display        : 'inline-block',\n        textDecoration : 'none',\n        color          : '#000000',\n        padding        : '0.4em',\n\n        current:\n        {\n          display         : 'inline-block',\n          textDecoration  : 'none',\n          color           : '#ffffff',\n          backgroundColor : '#000000',\n          padding         : '0.4em'\n        }\n      }\n    }\n  },\n\n  can_style:\n  {\n    fontFamily : 'Sans',\n    fontSize   : '12pt'\n  },\n\n  multiple_classes:\n  {\n    fontFamily : 'Sans',\n    fontSize   : '8pt'\n  },\n  \n  at_once:\n  {\n    fontFamily : 'Sans',\n    fontSize   : '8pt'\n  },\n\n  'old-school-regular-css-syntax':\n  {\n    boxSizing: 'border-box',\n    color: 'black'\n  },\n\n  scss_less:\n  {\n    color: 'white',\n\n    ':hover' \n    {\n      color: 'white',\n      textDecoration: 'underline'\n    }\n  },\n\n  curly_braces_fan:\n  {\n    background: 'none',\n\n    curly_braces_fan_number_two:\n    {\n      background: 'transparent'\n    }\n  },\n\n  YAML_fan:\n  {\n    display: 'inline-block',\n\n    python:\n    {\n      length: '99999px'\n    }\n  },\n\n  '@media (min-width: 320px)': \n  {\n    width: '100%',\n\n    ':hover': \n    {\n      background: 'white'\n    }\n  }\n}\n```\n\nAnd that's it. No fancy stuff, it's just what this module does. You can then take this JSON object and use it as you wish.\n\nPay attention to the tabulation as it's required for the whole thing to work properly. If you're one of those people who (for some strange reason) prefer spaces over tabs then you can still use it with spaces. Again, make sure that you keep all your spacing in order. And you can't mix tabs and spaces.\n\nYou can use your good old pure CSS syntax with curly braces, semicolons and dotted style class names (in this case the leading dots in CSS style class names will be omitted for later JSON object keying convenience).\n\nCurly braces are a survival from the dark ages of 80s and the good old C language. Still you are free to use your curly braces for decoration - they'll simply be filtered out.\n\nYou can also use YAML-alike syntax if you're one of those Python people.\n\nYou can use both one-line comments and multiline comments.\n\n### Nesting\n\nIn the example above the result is a JSON object with a nested tree of CSS style classes. You can flatten it if you like by using `import { flat as styler } from 'react-styling'` instead of the default `import styler from 'react-styling'`.\n\nThe difference is that the flat styler will flatten the CSS style class tree by prefixing all the style class names accordingly. \n\nThe reason this feature was introduced is that, for example, [Radium](#radium) would give warnings if a style object contained child style objects.\n\nAlso, I noticed that React, given a style object containing child style objects, creates irrelevant inline styles, e.g. `\u003cspan style=\"color: black; child_style_object_name: [Object object]; background: white\"/\u003e`: it doesn't break anything, but if some day React starts emitting warnings for that then just start using the `flat` styler.\n\n### Modifiers\n\nIn the example above, notice the ampersand before the \"current\" style class - this feature is optional (you don't need to use it at all), and it means that this style class is a \"modifier\" and all the style from its parent style class will be included in this style class. In this example, the padding, color, display and text-decoration from the \"link\" style class will be included in the \"current\" style class, so it works just like LESS/SASS ampersand. If you opt in to using the \"modifiers\" feature then you won't need to do manual merging like `style=\"extend({}, style.menu.item.link, style.menu.item.link.current)\"`.\n\nModifiers, when populated with the parent's styles, will also be populated with all the parent's pseudo-classes (those ones starting with a colon) and media queries (those ones starting with an at). This is done for better and seamless integration with [Radium](https://github.com/catamphetamine/react-styling#radium).\n\nModifiers are applied all the way down to the bottom of the style subtree and, therefore, all the child styles are \"modified\" too. For example, this stylesheet\n\n```javascript\noriginal\n  display : inline-block\n\n  item\n    border : none\n    color  : black\n\n  \u0026active\n    item\n      color      : white\n      background : black\n```\n\nwill be transformed to this style object\n\n```javascript\noriginal:\n{\n  display: 'inline-block',\n\n  item:\n  {\n    border : 'none',\n    color  : 'black'\n  },\n\n  active:\n  {\n    display: 'inline-block',\n\n    item:\n    {\n      border     : 'none',\n      color      : 'white',\n      background : 'black'\n    }\n  }\n}\n```\n\n### Shorthand style property expansion\n\n[A request was made](https://github.com/catamphetamine/react-styling/issues/3) to [add](https://github.com/catamphetamine/react-styling/pull/4) shorthand style property expansion feature to this library. The motivation is that when writing a CSS rule like `border: 1px solid red` in a base class and then overriding it with `border-color: blue` in some modifier class (like `:hover`) it's all merged correctly both when `:hover` is added and when `:hover` is removed. In React though, style rule update algorythm is not nearly that straightforward and bulletproof, and is in fact [a very basic one](https://github.com/facebook/react/issues/5397) which results in React not handling shorhand CSS property updates correctly. In these cases a special flavour of `react-styling` can be used:\n\n```js\nimport { expanded as styler } from 'react-styling'\n\nstyler `\n  margin: 10px\n  border: 1px solid red\n`\n```\n\nWhich results in the following style object\n\n```js\n{\n  marginTop    : '10px',\n  marginBottom : '10px',\n  marginLeft   : '10px',\n  marginRight  : '10px',\n\n  borderTopWidth: '1px',\n  borderTopStyle: 'solid',\n  borderTopColor: 'red',\n  // etc\n}\n```\n\n### Radium\n\nThere's a (popular) thing called [Radium](https://github.com/FormidableLabs/radium), which allows you to (citation):\n\n  * Browser state styles to support :hover, :focus, and :active\n  * Media queries\n  * Automatic vendor prefixing\n  * Keyframes animation helper\n\nYou can use react-styling with this Radium library too: write you styles in text, then transform the text using react-styling into a JSON object, and then use that JSON object with Radium. If you opt in to use the \"modifiers\" feature of this module then you won't have to write `style={[style.a, style.a.b]}`, you can just write `style={style.a.b}`.\n\nHere is the [DroidList example](https://github.com/FormidableLabs/radium/tree/master/docs/faq#how-do-i-use-pseudo-selectors-like-checked-or-last) from Radium FAQ rewritten using react-styling. Because `first` and `last` are \"modifiers\" here the `:hover` pseudo-class will be present inside each of them as well.\n\n```javascript\n// Notice the use of the \"flat\" styler as opposed to the default one:\n// it flattens the nested style object into a shallow style object.\nimport { flat as styler } from 'react-styling'\n\nvar droids = [\n  'R2-D2',\n  'C-3PO',\n  'Huyang',\n  'Droideka',\n  'Probe Droid'\n]\n\n@Radium\nclass DroidList extends React.Component {\n  render() {\n    return (\n      \u003cul style={style.droids}\u003e\n        {droids.map((droid, index, droids) =\u003e\n          \u003cli key={index} style={index === 0 ? style.droid_first : index === (droids.length - 1) ? style.droid_last : style.droid}\u003e\n            {droid}\n          \u003c/li\u003e\n        )}\n      \u003c/ul\u003e\n    )\n  }\n}\n\nconst style = styler`\n  droids\n    padding : 0\n\n  droid\n    border-color : black\n    border-style : solid\n    border-width : 1px 1px 0 1px\n    cursor       : pointer\n    list-style   : none\n    padding      : 12px\n\n    :hover\n      background : #eee\n\n    \u0026first\n      border-radius : 12px 12px 0 0\n\n    \u0026last\n      border-radius : 0 0 12px 12px\n      border-width  : 1px\n`\n```\n\n### Performance\n\nIn the examples above, `react-styling` transforms style text into a JSON object every time a React component is instantiated and then it will reuse that JSON style object for all `.render()` calls. React component instantiation happens, for example, in a `for ... of` loop or when a user navigates a page. I guess the penalty on the performance is negligible in this scenario. Yet, if someone wants to play with Babel they can write a Babel plugin (similar to [the one](https://github.com/facebook/relay/blob/master/scripts/babel-relay-plugin/src/getBabelRelayPlugin.js#L105) they use in [Relay](https://facebook.github.io/relay/docs/guides-babel-plugin.html#content)) and submit a Pull Request.\n\n### Contributing\n\nAfter cloning this repo, ensure dependencies are installed by running:\n\n```sh\nnpm install\n```\n\nThis module is written in ES6 and uses [Babel](http://babeljs.io/) for ES5\ntranspilation. Widely consumable JavaScript can be produced by running:\n\n```sh\nnpm run build\n```\n\nOnce `npm run build` has run, you may `import` or `require()` directly from\nnode.\n\nAfter developing, the full test suite can be evaluated by running:\n\n```sh\nnpm test\n```\n\nWhile actively developing, one can use (personally I don't use it)\n\n```sh\nnpm run watch\n```\n\nin a terminal. This will watch the file system and run tests automatically \nwhenever you save a js file.\n\nWhen you're ready to test your new functionality on a real project, you can run\n\n```sh\nnpm pack\n```\n\nIt will `build`, `test` and then create a `.tgz` archive which you can then install in your project folder\n\n```sh\nnpm install [module name with version].tar.gz\n```\n\n## License\n\n[MIT](LICENSE)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcatamphetamine%2Freact-styling","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcatamphetamine%2Freact-styling","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcatamphetamine%2Freact-styling/lists"}