{"id":19514867,"url":"https://github.com/ndp/csster","last_synced_at":"2025-04-26T06:30:40.921Z","repository":{"id":500801,"uuid":"902859","full_name":"ndp/csster","owner":"ndp","description":"The original CSS in Javascript library","archived":false,"fork":false,"pushed_at":"2023-01-20T09:40:06.000Z","size":7405,"stargazers_count":46,"open_issues_count":14,"forks_count":6,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-25T12:03:17.875Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ndp.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGE-LOG.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":"2010-09-11T02:59:40.000Z","updated_at":"2024-11-05T12:50:01.000Z","dependencies_parsed_at":"2023-02-12T01:15:25.935Z","dependency_job_id":null,"html_url":"https://github.com/ndp/csster","commit_stats":null,"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ndp%2Fcsster","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ndp%2Fcsster/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ndp%2Fcsster/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ndp%2Fcsster/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ndp","download_url":"https://codeload.github.com/ndp/csster/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250943897,"owners_count":21511648,"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-11-10T23:37:53.435Z","updated_at":"2025-04-26T06:30:40.155Z","avatar_url":"https://github.com/ndp.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Csster\n\n\u003ca href=\"https://travis-ci.org/ndp/csster\" id=\"status-image-popup\" title=\"build status image\" name=\"status-images\" class=\"open-popup\"\u003e\n            \u003cimg src=\"https://travis-ci.org/ndp/csster.svg\" \u003e\n          \u003c/a\u003e\n\nConcisely generate CSS style rules within Javascript.  Features:\n\n* \"object literal\" format with excellent editor support\n* nesting to DRY up stylesheets\n* color functions like `darken` and `saturate`\n* built-in macros for common CSS idioms like *clearfix*, *rounded corners*, *drop shadows*.\n* extension points for custom behavior or cross-browser support.\n* no new syntax to learn (and fight)\n* and all the plain old Javascript behavior: functions, data structures, looping, Math operations, etc.\n\nSlideshow introduction: https://docs.google.com/present/view?id=dfm357b6_49c4d3fpdm\u0026interval=15\n\n## Installation\n\n### Bundler (Rails) Installation\n\nAdd this line to your application's Gemfile:\n\n    gem 'csster'\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install csster\n\nFor Rails, within your `application.js`, add\n\n    //= require csster\n\n\n### Node NPM Install\n\n    npm install csster\n\n## Usage\n\n### Creating Stylesheets (Brower/Client Side)\n\nAll code is packaged into a single Javascript file download, [csster.js](http://ndpsoftware.com/csster/csster.js). There are no external dependencies.\n\n```javascript\nrequire('csster.js'); // however you manage dependencies\n\nCsster.style({\n  h1: {\n    fontSize: 18,\n    color: 'red'\n  }\n});\n```\n\nThe result is inserted in DOM automatically at the bottom of the \u0026lt;head\u0026gt; element:\n\n```html\n...\n\u003cstyle type=\"text/stylesheet\"\u003e\nh1 {\nfont-size: 18px;\ncolor: red;\n}\n\u003c/style\u003e\n\u003c/head\u003e\n...\n```\n\n### Node Usage\n\n`Csster.buildCss` accepts arrays or hashes of rules and returns a text string of the Css rules.\nThe caller is responsible for writing to the browser.\n\n\n### Building CSS Rules\n\nThe `Csster.style` method accepts CSS rules passed either as arrays or hashes, arrays just being\na way to order the hashes. For example:\n\n```javascript\nCsster.style({\n  ul: {\n    margin: 5,\n    padding: 0,\n  },\n  'ul li:first': {\n    paddingLeft: '20px'\n  }\n}\n```\n\nNote that\n\n* property names are automatically converted to hyphenated format from camelCase, so in many cases you can omit the quotation marks. (`float` needs to quoted since it's a reserved word.)\n* most raw numbers are assumed to be \"pixels\" (or \"px\"), and rendered as such. A heuristic helps in this, skipping `opacity`, `z-index`, etc.\n* any sort of selectors are allowed... they are just passed through to the stylesheet.\n\n#### Nesting\nCsster supports nesting of rules to keep things more concise:\n\n```javascript\n{\n  ul: {\n    margin: 5,\n    li: {\n      paddingLeft: 20,\n      '\u0026:hover': {\n        color: 'red'\n      }\n    }\n  }\n}\n```\n\nThe \"li\" property in this case might be a selector or might be a property name. A list of valid\nproperty names is used to identify properties right now, and otherwise it's considered a sub-selector.\n\nCsster supports SASS's `\u0026` operator, to indicate that the selector should be combined with the parent selector.\nInstead of the default \"any descendent\" space character being inserted, no space is inserted.\n\nCombined rules (with commas) are expanded as expected, so nested rules with commas have their parents expanded.\n\n\n#### Functions\nMost manipulations you'll want don't require any special syntax. They will fall into\nJavascript's language support, as far as any math or looping.\nUse Javascript to write necessary functions! Include them directly in the\nCSS rule definitions.\n\n\n#### Colors\n\nColors can be particularly brittle in CSS, so color conversion functions are included.\nThe easiest way to enable this is to call:\n\n    Csster.colorizeString()\n\nNow the `String` prototype will include SASS-like color functions:\n\n*  `\"#ab342c\".darken(%)` -- make color darker by given percent\n*  `\"#ab342c\".lighten(%)` -- make color lighter by given percent\n*  `\"#ab342c\".saturate(%)`  -- make color more saturated by given percent. To *desaturate*, use negative values for the percent. Note that `\"#ab342c\".saturate(-100)` renders in grayscale.\n\nThere are also color conversion routines if you want to build your own manipulation.\n\n*  `\"#ab342c\".toRGB()`\n*  `\"#ab342c\".toHSL()`\n*  `Csster.hslToHexColor(h,s,l)`\n\nOpacity is currently not supported by the color model.\n\n### Macros\n\nAlthough the Javascript language probably offers enough flexibility for most of what you\nwant, macros are also a core part of Csster.\n\n#### Pre-build Macros\n\nThere are a host of pre-made macros that may be useful:\n\n* `Csster.macros.roundedCorners(radius)` -- add rounded corners on all sides\n* `Csster.macros.roundedCorners(side, radius)` -- add rounded corners on specified side: `'top'`, `'left'`, `'bottom'` or `'right'`\n* `Csster.macros.roundedCorners(corner, radius)` -- add rounded corners to a specified corner: `'tl'`, `'tr'`, `'bl'` or `'br'`\n* `Csster.macros.imageReplacement(width, height, img, imgXPosition=0, imgYPosition=0)` -- phark image replacement with optional background image offset.\n* `Csster.macros.boxShadow([xoffset, yoffset], radius, color)`\n* `Csster.macros.verticalCentering(height)` and `horizontalCentering(width)` -- center using the top 50% / margin-top -width/2 technique. See http://stackoverflow.com/questions/148251/css-centering-tricks\n* `Csster.macros.clearfix()` -- standard clearfix\n* `Csster.browserInfo()` -- basic information about the current browser, if available. Useful for generating alternative rules.\n\n#### Using macros with the \"has\" or \"mixin\" key\n\nTo \"mix these in\", use the `has`, `mixin` or `mixins` key:\n\n    {\n        'div#featured_box': {\n          backgroundColor: '#394c89',\n          has: roundedCorner(5)\n        }\n    }\n\nMultiple macros can be included by making that a list, eg. `has: [roundedCorners(5), dropShadow()]`.\n\n#### Using macros with fake property names\n\nYou can also make these _pseudo properties_ using the `Csster.setMacro` method. For example,\n\n```javascript\nCsster.setMacro('roundedCorners', (px) =\u003e {\n  return { borderRadius: px }\n})\n```\n\nAs you might expect, this defines a property that is rendered with the given function. Therefore:\n\n```javascript\n...\nCsster.style({ div: roundedCorners: 5 })\n```\n\n#### Writing Macros\n\nIt's all Javascript, so macros and more complex functions are easy to write.\nTo mix in a set of values, create a function that returns a hash of values, for example:\n\n```javascript\nfunction roundedCorners(radius) {\n  return {\n    '-webkit-border-radius': radius,\n    '-moz-border-radius': radius,\n    'border-radius': radius\n  }\n}\n```\n\nA macro's properties will be overwritten  similar to how the cascade takes the last defined value: later ones override earlier ones.\n\n\n## Verification\n\nBy default, property names are validated against recent HTML specs.\nThe build-in tool rejects non-standard property names,\nalthough by default popular \"-moz\" and \"-webkit\" properties are added.\nUse `Csster.addPropertyNames` to supplement property names it might not\nconsider valid.\n\nAt this time of history, though, validation is not necessarily what you want.\nTo turn this off, use:\n\n```javascript\nCsster.propertyNameValidator.setConfig('strictNames', false)\n```\n\nBy default, any browser extension property (such as `-moz-boo`) is allowed. To\nrestrict this, turn on the validation:\n\n```javascript\nCsster.propertyNameValidator.setConfig('anyBrowserExtension', false)\n```\n\n## jQuery Integration\n\nIf jQuery is loaded before Csster, it provides a \"csster\" plugin:\n\n```javascript\n$('.sidebar').csster({ border: '5px solid green', padding: 10 });\n```\n\nAs expected, this adds a rule to the document with the \".sidebar\" selector.\nIn general, this can be called identically to the `css()` function.\nThis is useful is the DOM on the page is dynamic and when a rule is more efficient than applying\na style repeatedly to all the DOM nodes.\n\nThere are a few limitations: Currently a \"context\" is not supported.\nAnd be careful, since not all jQuery selectors are valid CSS selectors--\nnothing is done to convert or report unsupported selectors (just like regular CSS).\n\n## Extending Csster\n\n### Inserting into the DOM\nFunction that outputs a set of rules into the DOM is `Csster.insertCss` and can be replaced if desired.\n\n## V2.0 Changes\n\n### To upgrade from 1.0 or before\n\n* Change `Csster.browser` to call `Csster.browserInfo()`, which returns the same thing.\n* Change `has:` macro implementations to `mixin:`.\n\n### Other changes:\n\n* use ES6 for implementation and provide a more compressed and clean script.\n* fake-property-based macros\n* add ability to turn off property name validation.\n* add ability to warn about unknown browser extensions for property names.\n\n\n## Links\n\n* [Demo of the color functions and macros](http://ndpsoftware.com/csster/demo.html)\n* [Demo of using to build a chart](http://ndpsoftware.com/csster/demo_chart.html)\n* [Blog post](http://ndpsoft.blogspot.com/2010/09/introducing-csster.html)\n\n\n## Development\n\n### Contributing\n\n1. Fork it\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create new Pull Request\n\n### Like it or have ideas?\n\nIf you like this and would like me to do more intereactions like this, send me an email... or money https://venmo.com/ndpsoft or  https://www.gofundme.com/ndp-software\n\n\n## Releasing\n\n1. Make changes\n2. Update `bin/build.sh#2` `VERSION=` code.\n3. `bin/build.sh`\n4. `rake build`\n5. `git checkin...`\n6. `git push...`\n7. `rake release` # Ruby Gem\n8. `npm publish`  # Node module\n\n\n### TDD\n\nThe design was driven by the specs.\n\nThere are now two sets of tests. The first are unit and out-of-browser functional tests run with jasmine. If your npm paths are set up correctly, `jasmine` should do it.\n\nThere's also an (older) in-browser test, in `demo/functional_runner.html`. Opening this in a browser should do it.\n\nFinally, there are a couple manual \"demo\" files that need to be examined in a browser, to make sure they are working. These are in the demo folder.\n\n### Building\n\n`./bin/build.sh`\n\n\n\n## Todo\n\n* decompile existing stylesheets\n\n\n\n## Motivation\n\nThis project comes from my frustration of trying to build standalone Javascript widgets. Web\nprojects always involve the combination of HTML DOM, CSS and Javascript. It's often simpler to\ngenerate the necessary DOM within your Javascript, removing any coupling (and a simpler calling\nconvention) to a specific web page. But most widgets have certain style rules. To avoid\nany coupling with the CSS at all, styles can be included inline, but these gets bulky\nand hard to read. The \"rule\" nature of CSS is nice. So widgets then have a Javascript\nand CSS component. Wouldn't it be nice, though, to remove that CSS component.\n\nWith the advent of SASS, the coupling is even more complicated, as now there's some other\ntool completely unrelated to your component, written in some other language. Wouldn't\na unified approach be nice?\n\n\n## Similar projects\n\nhttp://revnode.com/oss/css/\n\n## Legal\n\nCopyright (c) 2010-2020 Andrew J. Peterson\n[Apache License](https://github.com/ndp/csster/raw/master/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fndp%2Fcsster","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fndp%2Fcsster","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fndp%2Fcsster/lists"}