{"id":13393529,"url":"https://github.com/lukejacksonn/oceanwind","last_synced_at":"2025-04-06T12:07:52.294Z","repository":{"id":48197453,"uuid":"292090409","full_name":"lukejacksonn/oceanwind","owner":"lukejacksonn","description":"Compiles tailwind shorthand into css at runtime. Succeeded by Twind.","archived":false,"fork":false,"pushed_at":"2021-08-05T11:46:01.000Z","size":390,"stargazers_count":265,"open_issues_count":9,"forks_count":12,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-01T18:58:05.038Z","etag":null,"topics":["css","css-in-js","otion","shorthand-syntax","tailwind-compiler"],"latest_commit_sha":null,"homepage":"https://twind.dev","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lukejacksonn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-09-01T19:34:49.000Z","updated_at":"2024-10-27T21:19:14.000Z","dependencies_parsed_at":"2022-09-20T23:10:56.986Z","dependency_job_id":null,"html_url":"https://github.com/lukejacksonn/oceanwind","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukejacksonn%2Foceanwind","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukejacksonn%2Foceanwind/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukejacksonn%2Foceanwind/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukejacksonn%2Foceanwind/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lukejacksonn","download_url":"https://codeload.github.com/lukejacksonn/oceanwind/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247478320,"owners_count":20945266,"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","css-in-js","otion","shorthand-syntax","tailwind-compiler"],"created_at":"2024-07-30T17:00:55.296Z","updated_at":"2025-04-06T12:07:52.270Z","avatar_url":"https://github.com/lukejacksonn.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# Oceanwind\n\n\u003e compiles tailwind like shorthand syntax into css at runtime\n\nThis library takes inspiration from [Tailwind](https://github.com/tailwindlabs/tailwindcss) and utilizes [Otion](https://github.com/kripod/otion) to provide means of efficiently generating atomic styles from shorthand syntax and appending them to the DOM at runtime.\n\nServer side rendering and static extraction is also supported.\n\n\u003e ⚡️ Check out the [live and interactive demo](https://esm.codes/#Ly8gT2NlYW53aW5kIGRlbW8gYnkgQGx1a2VqYWNrc29ubgovLyAtLS0tLS0tLS0tLS0tLS0tCiAgICAKaW1wb3J0IHsgcmVuZGVyLCBodG1sIH0gZnJvbSAnaHR0cHM6Ly9ucG0ucmV2ZXJzZWh0dHAuY29tL3ByZWFjdCxwcmVhY3QvaG9va3MsaHRtL3ByZWFjdCc7CmltcG9ydCB7IHRoZW1lZCB9IGZyb20gJ2h0dHBzOi8vdW5wa2cuY29tL29jZWFud2luZCc7Cgpjb25zdCBvdyA9IHRoZW1lZCh7CiAgLy8gRXhhbXBsZSBvZiBleHRlbmRpbmcgdGhlIGRlZmF1bHQgdGhlbWUKICByb3RhdGU6IHsgNTogJzVkZWcnIH0KfSkKCmNvbnN0IHN0eWxlID0gewogIC8vIEV4YW1wbGUgb2YgYWJzdHJhY3RlZCBzdHlsZQogIGNvbnRhaW5lcjogb3dgCiAgICBoLWZ1bGwKICAgIGJnLXB1cnBsZS01MDAKICAgIGZsZXgKICAgIGl0ZW1zLWNlbnRlcgogICAganVzdGlmeS1jZW50ZXIKICBgCn0KCnJlbmRlcigKICBodG1sYAogICAgPGRpdiBjbGFzc05hbWU9JHtzdHlsZS5jb250YWluZXJ9PgogICAgICA8aDEgY2xhc3NOYW1lPSR7CiAgICAgICAgLy8gRXhhbXBsZSBvZiBhbiBpbmxpbmUgc3R5bGUKICAgICAgICBvd2AKICAgICAgICAgIHRleHQtd2hpdGUKICAgICAgICAgIGZvbnQtYm9sZAogICAgICAgICAgZm9udC1zYW5zCiAgICAgICAgICBob3ZlcjooCiAgICAgICAgICAgIHJvdGF0ZS01CiAgICAgICAgICAgIHNjYWxlLTE1MAogICAgICAgICAgICBjdXJzb3ItcG9pbnRlcgogICAgICAgICAgKQogICAgICAgIGAKICAgICAgfT5IZWxsbyBXb3JsZDwvaDE+CiAgICA8L2Rpdj4KICBgLAogIGRvY3VtZW50LmJvZHkKKTs=)\n\n\u003cimg width=\"100%\" src=\"https://user-images.githubusercontent.com/1457604/91981751-32310b00-ed21-11ea-8a89-f30f1437f9a2.gif\"\u003e\n\n\u003cbr\u003e\n\nThe aim here was to create a compiler that:\n\n- 📖 Supports all existing Tailwind shorthand syntax outlined [in the docs](https://tailwindcss.com/docs)\n- 💡 Generates only the styles required without building or purging\n- 🗜 Is smaller than the average purged css file output from the Tailwind compiler\n- ⏱ Has desirable perf characteristics at runtime\n- ⚠️ Warns the developer when unrecognized or duplicate shorthand is used\n\nThe library currently weighs under 10kb and supports the vast majority of Tailwind directives and variants.\n\n## Usage\n\nTo use the library, first import the module then invoke the default export using tagged template syntax:\n\n```js\nimport ow from 'https://unpkg.com/oceanwind';\ndocument.body.className = ow`h-full bg-purple-500 rotate-3 scale-95`;\n```\n\nRunning the above code will result in the following happening:\n\n1. Shorthand syntax will be translated into CSS (e.g. `h-screen -\u003e { height: 100vh }`).\n2. All resultant CSS will be merged into a single CSS-in-JS object\n3. Each style will be assigned a unique class and appended to a stylesheet\n4. A string is returned representing all the classes that were created\n\nIt is recommended to import the following css files which help normalize styles across browsers:\n\n- The Tailwind reset [available here](https://unpkg.com/tailwindcss/dist/base.min.css)\n- The Tailwind prose helper [available here](https://unpkg.com/@tailwindcss/typography/dist/typography.min.css)\n\n### Extending the default theme\n\nImporting and invoking oceanwind directly will cause it to use [default theme](https://github.com/lukejacksonn/oceanwind/blob/master/core/theme.js) for directives that require themed values (like `bg-red-500` for example). To customize the theme, use the `themed` export instead of the default export.\n\n```js\nimport { themed } from 'https://unpkg.com/oceanwind';\n\nconst ow = themed({\n  colors: {\n    red: {\n      500: 'hotpink',\n    },\n  },\n});\n\now`bg-red-500`; // will result in a hotpink background-color\n```\n\nAny custom theme provided to the `themed` function will be deep merged with the default theme.\n\n### Function Signature\n\nIt is possible to invoke oceanwind in a multitude of different ways. For example:\n\n```js\n// Function call passing a string\now('bg-red-500 rounded');\n\n// Tag Template Literal (falsey interpolations will be omitted)\now`bg-red-500 rounded`;\now`bg-red-500 ${false \u0026\u0026 'rounded'}`;\n\n// Function call passing an array (falsey items will be omitted)\now(['bg-red-500', 'rounded']);\now(['bg-red-500', false \u0026\u0026 'rounded']);\n\n// Function call passing an object (keys with falsey values will be omitted)\now({ 'bg-red-500': true, rounded: true });\now({ 'bg-red-500': true, rounded: false });\n```\n\n### Variant Grouping\n\nDirectives with the same variants can be grouped using parenthesis. Oceanwind will expand the nested directives; applying the variant to each directive in the group before translation. For example:\n\n\u003e Notice any directives within tagged template literals can span multiple lines\n\n```js\now`\n  sm:hover:(\n    bg-black\n    text-white\n  )\n  md:(bg-white hover:text-black)\n`;\n```\n\nIt is possible to nest groupings too, for example:\n\n```js\now`\n  sm:(\n    bg-black\n    text-white\n    hover:(bg-white text-black)\n  )\n`;\n```\n\nTwo things to note here is that the outermost variant should always be a responsive variant (just like in tailwind `hover:sm:` is not supported) and that nesting responsive variants doesn't make sense either, for example `sm:md:` is not supported.\n\n### Catching Errors\n\nBy default warnings about missing or duplicate translations will be written to the console:\n\n![image](https://user-images.githubusercontent.com/1457604/95141411-04e4dc00-0769-11eb-9245-d4cc37c8b58f.png)\n\nClicking on the file path in dev tools will _jump to_ the line in the file in the sources panel.\n\nIt is possible to make oceanwind throw an error rather just warning by opting into _strict_ mode:\n\n```js\nthemed({ strict: true });\n```\n\n![image](https://user-images.githubusercontent.com/1457604/95245344-e9caa880-080a-11eb-9741-576f7b2ff6b0.png)\n\n## Example\n\nMost of the time developers will be using a front end framework to render DOM elements. Oceanwind is framework agnostic but here is an example of how you might use it with preact and no build step.\n\n\u003e ⚡️ Check out the [live and interactive demo](https://esm.codes/#Ly8gT2NlYW53aW5kIGRlbW8gYnkgQGx1a2VqYWNrc29ubgovLyAtLS0tLS0tLS0tLS0tLS0tCiAgICAKaW1wb3J0IHsgcmVuZGVyLCBodG1sIH0gZnJvbSAnaHR0cHM6Ly9ucG0ucmV2ZXJzZWh0dHAuY29tL3ByZWFjdCxwcmVhY3QvaG9va3MsaHRtL3ByZWFjdCc7CmltcG9ydCB7IHRoZW1lZCB9IGZyb20gJ2h0dHBzOi8vdW5wa2cuY29tL29jZWFud2luZCc7Cgpjb25zdCBvdyA9IHRoZW1lZCh7CiAgLy8gRXhhbXBsZSBvZiBleHRlbmRpbmcgdGhlIGRlZmF1bHQgdGhlbWUKICByb3RhdGU6IHsgNTogJzVkZWcnIH0KfSkKCmNvbnN0IHN0eWxlID0gewogIC8vIEV4YW1wbGUgb2YgYWJzdHJhY3RlZCBzdHlsZQogIGNvbnRhaW5lcjogb3dgCiAgICBoLWZ1bGwKICAgIGJnLXB1cnBsZS01MDAKICAgIGZsZXgKICAgIGl0ZW1zLWNlbnRlcgogICAganVzdGlmeS1jZW50ZXIKICBgCn0KCnJlbmRlcigKICBodG1sYAogICAgPGRpdiBjbGFzc05hbWU9JHtzdHlsZS5jb250YWluZXJ9PgogICAgICA8aDEgY2xhc3NOYW1lPSR7CiAgICAgICAgLy8gRXhhbXBsZSBvZiBhbiBpbmxpbmUgc3R5bGUKICAgICAgICBvd2AKICAgICAgICAgIHRleHQtd2hpdGUKICAgICAgICAgIGZvbnQtYm9sZAogICAgICAgICAgZm9udC1zYW5zCiAgICAgICAgICBob3ZlcjooCiAgICAgICAgICAgIHJvdGF0ZS01CiAgICAgICAgICAgIHNjYWxlLTE1MAogICAgICAgICAgICBjdXJzb3ItcG9pbnRlcgogICAgICAgICAgKQogICAgICAgIGAKICAgICAgfT5IZWxsbyBXb3JsZDwvaDE+CiAgICA8L2Rpdj4KICBgLAogIGRvY3VtZW50LmJvZHkKKTs=)\n\n```js\nimport { render, h } from 'https://unpkg.com/preact?module';\n\nimport htm from 'https://unpkg.com/htm?module';\nimport ow from 'https://unpkg.com/oceanwind';\n\nconst html = htm.bind(h);\n\nrender(\n  html`\n    \u003cdiv className=${ow`h-full bg-purple-500`}\u003e\n      \u003ch1 className=${ow`text-white font-bold`}\u003eHello World\u003c/h1\u003e\n    \u003c/div\u003e\n  `,\n  document.body\n);\n```\n\n## Server-side rendering (SSR)\n\nOceanwind supports SSR through Otion. Consider the following example:\n\n```js\nimport { h } from 'preact';\nimport render from 'preact-render-to-string';\nimport htm from 'htm';\nimport { getStyleTag, VirtualInjector } from 'otion/server';\nimport { setup, themed } from 'oceanwind';\n\nconst injector = VirtualInjector();\nsetup({ injector });\n\nconst html = htm.bind(h);\nconst ow = themed({});\nconst style = {\n  main: ow`clearfix`,\n};\n\nconst app = html`\u003cmain className=${style.main}\u003ehello oceanwind\u003c/main\u003e`;\nconst appHtml = render(app);\nconst styleTag = getStyleTag(injector);\n\n// Inject styleTag to your HTML now.\n```\n\nOceanwind also exposes `hydrate` from Otion for client-side hydration. [See Otion documentation](https://www.npmjs.com/package/otion#server-side-rendering) for further configuration options and usage instructions.\n\n## Acknowledgements\n\nI'd like to thank both [Adam Wathan](https://github.com/adamwathan) and [Kristóf Poduszló](https://github.com/kripod) for their amazing work with Tailwind and Otion respectively, which made making this library somewhat a breeze. Also [Phil Pluckthun](https://github.com/kitten) who helped me deduce the initial grammar.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukejacksonn%2Foceanwind","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flukejacksonn%2Foceanwind","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukejacksonn%2Foceanwind/lists"}