{"id":13437987,"url":"https://github.com/kodyl/stilr","last_synced_at":"2025-04-05T15:07:55.469Z","repository":{"id":32511348,"uuid":"36092377","full_name":"kodyl/stilr","owner":"kodyl","description":"Encapsulated styling for your javascript components with all the power of javascript and CSS combined.","archived":false,"fork":false,"pushed_at":"2023-01-05T04:56:16.000Z","size":913,"stargazers_count":236,"open_issues_count":15,"forks_count":13,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-29T14:11:19.067Z","etag":null,"topics":[],"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/kodyl.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}},"created_at":"2015-05-22T19:53:56.000Z","updated_at":"2025-03-20T12:51:06.000Z","dependencies_parsed_at":"2023-01-14T21:27:15.755Z","dependency_job_id":null,"html_url":"https://github.com/kodyl/stilr","commit_stats":null,"previous_names":["chriskjaer/stilr"],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kodyl%2Fstilr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kodyl%2Fstilr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kodyl%2Fstilr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kodyl%2Fstilr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kodyl","download_url":"https://codeload.github.com/kodyl/stilr/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247353746,"owners_count":20925329,"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":[],"created_at":"2024-07-31T03:01:01.963Z","updated_at":"2025-04-05T15:07:55.446Z","avatar_url":"https://github.com/kodyl.png","language":"JavaScript","funding_links":[],"categories":["Uncategorized","Code Design","JavaScript"],"sub_categories":["Uncategorized","CSS / Style"],"readme":"# Stilr [![Build Status](https://travis-ci.org/kodyl/stilr.svg)](https://travis-ci.org/kodyl/stilr) [![npm version](https://badge.fury.io/js/stilr.svg)](http://badge.fury.io/js/stilr)\n\nEncapsulated styling for your javascript components with all the power of\njavascript and CSS combined.\n\n- Unique class names (Content Hash Based)\n- Useable on the server\n- Allows nested pseudo selectors\n- Allows nested media queries\n- No namespacing / Class name collisions.\n- Plays nicely with React Hot Loader and autoprefixer.\n\n...oh, and did I mention you get duplicate style elimination for free?\n\n__Note__: This library fits really nice with [React](https://facebook.github.io/react/) but should work with other libraries like [Angular 2](https://angular.io/) or [Deku](https://github.com/dekujs/deku)\n\n## API\n\n#### `object StyleSheet.create(object spec)`\nStilr extracts the styles from the style object and returns an object with the\nsame keys mapped to class names.\n\n__Example__\n```javascript\nimport StyleSheet from 'stilr';\n\nconst palm = '@media screen and (max-width:600px)';\n\nconst styles = StyleSheet.create({\n  container: {\n    color: '#fff',\n    ':hover': {                 // Pseudo Selectors are allowed\n      color: '#000'\n    },\n    [palm]: {                   // Media Queries are allowed\n      fontSize: 16,\n      ':hover': {\n        color: 'blue'  \t\t// Pseudo selectors inside media queries.\n      }\n    }\n  }\n});\n\nconsole.log(styles.container);  // =\u003e '_xsrhhm' -- (The class name for this style.)\n```\n\n#### `string StyleSheet.render()`\nStilr outputs the contents of its internal stylesheet as a string of css\n\n__Example__\n```javascript\nimport StyleSheet from 'stilr';\n\nStyleSheet.create({\n  container: {\n    color: '#fff'\n  }\n});\n\nconst CSS = StyleSheet.render();\n\nconsole.log(CSS);             // =\u003e '._yiw79c{color:#fff;}'\n```\n\n#### `bool StyleSheet.clear()`\nClear Stilr internal stylesheet\n\n__Example__\n```javascript\nimport StyleSheet from 'stilr';\n\nconst styles = StyleSheet.create({\n  container: {\n    color: '#fff'\n  }\n});\n\nStyleSheet.clear();\n\nconst CSS = StyleSheet.render();\n\nconsole.log(CSS);             // =\u003e ''\n```\n\n\n## Examples\n\n#### Basic Button Component Example.\nLet's start of by creating our styles. If you have ever used React Native, this\nwill be familiar to you:\n\n```javascript\nimport StyleSheet from 'stilr';\nimport { palm } from './breakpoints';\nimport { color, font } from './theme';\n\nconst styles = StyleSheet.create({\n  base: {\n    transition: 'background-color .25s',\n    borderRadius: 2,\n    textAlign: 'center',\n    fontSize: 20,\n    padding: 6,\n    color: '#fff',\n    border: `${ color.border } 1px solid`,\n    [palm]: {\n      fontSize: 18\n    }\n  },\n  primary: {\n    backgroundColor: color.primary,\n    ':hover': {\n      color: 'tomato'\n    }\n  },\n  secondary: {\n    backgroundColor: 'tomato',\n    color: '#eee'\n  }\n});\n```\n\nStilr will now generate a set of class names based on the content of your styles\nand return an object with the same keys mapped to those classes.\n\nNote that you're able to use pseudo selectors and media queries.\nPseudo selectors are written like you normally would in CSS, e.g.: `:hover`, `:active`,\n`:before` etc.\nMedia queries are the same, e.g. `palm` in the example is just a string: `@media screen and (max-width:600px)`. Any valid media query is allowed.\n\nSince we just have a bunch of class names now, we can use these in our React\nComponent.\n\n```javascript\nimport React, { PropTypes } from 'react';\n\nclass Button extends React.Component {\n  static propTypes = {\n    type: PropTypes.oneOf(['primary', 'secondary'])\n  }\n\n  render() {\n    const { type, children } = this.props;\n    const buttonStyles = [\n      styles.base,\n      styles[ type ]\n    ].join(' ');\n\n    return (\n      \u003cbutton className={ buttonStyles }\u003e\n        { children }\n      \u003c/button\u003e\n    );\n}\n```\n\nNext up, let's render our css and mount our app:\n\n```javascript\nimport React from 'react';\nimport Button from './button';\nimport StyleSheet from 'stilr';\n\nReact.render(\n  \u003cButton type='primary' /\u003e,\n  document.getElementById('root')\n);\n\ndocument.getElementById('stylesheet').textContent = StyleSheet.render();\n```\n\nThis step could also have been done on the server. Since StyleSheet.render just\nreturns a string of css. In our case, it would look something like this in a\nprettified version:\n```css\n@media screen and (max-width:600px) {\n  ._82uwp6 {\n    font-size: 18px;\n  }\n}\n\n._82uwp6 {\n  transition: background-color .25s;\n  border-radius: 2px;\n  text-align: center;\n  font-size: 20px;\n  padding: 6px;\n  color: #fff;\n  border: #fff 1px solid;\n}\n\n._11jt6vs:hover {\n  color: tomato;\n}\n\n._11jt6vs {\n  background-color: red;\n}\n\n._1f4wq27 {\n  background-color: tomato;\n  color: #eee;\n}\n```\n\nIn case you were wondering: Yes, this would would be an ideal place to add something like autoprefixer, minification etc.\n\n\n## Duplicate Style Elimation\n```javascript\nimport StyleSheet from 'stilr';\n\nconst styles = StyleSheet.create({\n  same: {\n    fontSize: 18,\n    color: '#000'\n  },\n  sameSame: {\n    fontSize: 18,\n    color: '#000'\n  }\n});\n\nconsole.log( styles.same );        =\u003e '_1v3qejj'\nconsole.log( styles.sameSame );    =\u003e '_1v3qejj'\n```\n\n...magic.\n\nUnder the hood, stilr creates class names based on a content hash of your style object\nwhich means that when the content is the same, the same hash will always be\nreturned. \n\n\n## Extracting your styles.\n\n#### Server\nIf you do serverside rendering, you should be able to extract your styles right after you load your app.\n\n```javascript\nimport React from 'react';\nimport StyleSheet from 'stilr';\nimport App from '../your-app.js';\n\nconst css = StyleSheet.render();\nconst html = React.renderToStaticMarkup(\u003cApp /\u003e);\n\n// Extract css to a file or insert it in a file at the top of your html document\n```\nApply autoprefixer here, or other preprocess goodness here. \nIf you're really fancy, you only do the required autoprefixes based on the user agent.\n\n### Development\nWhen working with Stilr in development, the preferred way to extract styles would be the following way, just before you initialize your app.\n\n```javascript\nimport App from '../app';\nimport React from 'react';\nimport StyleSheet from 'stilr';\n\nlet stylesheet = document.createElement('style');\nstylesheet.textContent = StyleSheet.render();\ndocument.head.appendChild(stylesheet);\n\nReact.render(\u003cApp /\u003e, document.getElementById('root'));\n```\n\n### React Hot Loader + Autoprefixer\nIf you're using [React Hot Loader](https://github.com/gaearon/react-hot-loader). Use the following approach in development to get hot loading styles and autoprefixer awesomeness.\n\n```javascript\nimport React from 'react';\nimport StyleSheet from 'stilr';\nimport autoprefixer from 'autoprefixer';\nimport postcss from 'postcss';\n\n\n// Make sure you have a style element with the ID: 'stylesheet' in your html.\nconst stylesheet = document.getElementById('stylesheet');\n\nclass App extends React.Component {\n   render() {\n     if (process.env !== 'production') {\n       const prefixedCSS = postcss(autoprefixer()).process( StyleSheet.render() ).css;\n       stylesheet.textContent = prefixedCSS;\n     }\n     \n     return (\n        ...snip...\n     );\n   }\n}\n```\nIf you're using Webpack, you have to add `node: { fs: 'empty' }` to your config file. Otherwise autoprefixer will throw an error when trying to use it on the client.\n\n#### Production\n\n##### Makefile\nAdd this as a build step in your makefile.\n```Makefile\nextract-styles:\n\t@node -p \"require('babel/register')({ignore: false}); var s = require('stilr'); require('./your-app.js'); s.render()\" \u003e ./bundle.css\n```\n\nThe following snippet can also be executed anywhere to extract the styles.\nRemember to replace `./your-app.js` with the entry file of your app.\n`node -p \"require('babel/register')({ignore: false}); var s = require('stilr'); require('./your-app.js')`\n\n\n## TODO:\n- [ ] Remove React as a dependency\n- [ ] More examples\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkodyl%2Fstilr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkodyl%2Fstilr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkodyl%2Fstilr/lists"}