{"id":17720201,"url":"https://github.com/AccentDesign/gcss","last_synced_at":"2025-03-14T03:33:42.422Z","repository":{"id":235889283,"uuid":"791359044","full_name":"AccentDesign/gcss","owner":"AccentDesign","description":"CSS written in Go","archived":false,"fork":false,"pushed_at":"2024-05-19T14:21:35.000Z","size":104,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-05-19T14:35:23.072Z","etag":null,"topics":["css","golang"],"latest_commit_sha":null,"homepage":"https://accentdesign.github.io/gcss","language":"Go","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/AccentDesign.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":"2024-04-24T15:18:56.000Z","updated_at":"2024-05-29T19:41:28.346Z","dependencies_parsed_at":"2024-05-19T14:34:50.225Z","dependency_job_id":null,"html_url":"https://github.com/AccentDesign/gcss","commit_stats":null,"previous_names":["accentdesign/gostyle","accentdesign/gcss"],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AccentDesign%2Fgcss","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AccentDesign%2Fgcss/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AccentDesign%2Fgcss/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AccentDesign%2Fgcss/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AccentDesign","download_url":"https://codeload.github.com/AccentDesign/gcss/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243520737,"owners_count":20304173,"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","golang"],"created_at":"2024-10-25T15:26:30.501Z","updated_at":"2025-03-14T03:33:42.119Z","avatar_url":"https://github.com/AccentDesign.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"[![Test](https://github.com/AccentDesign/gcss/actions/workflows/go-test.yml/badge.svg)](https://github.com/AccentDesign/gcss/actions/workflows/go-test.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/AccentDesign/gcss)](https://goreportcard.com/report/github.com/AccentDesign/gcss)\n\u003ca href=\"https://pkg.go.dev/github.com/AccentDesign/gcss\"\u003e\u003cimg src=\"https://img.shields.io/badge/Documentation%20on-pkg.go.dev-blue.svg\"/\u003e\u003c/a\u003e\n\n\u003cimg src=\"banner.jpg\" alt=\"banner\" style=\"width: 100%; height: auto;\"\u003e\n\n# gcss\n\nCSS written in Pure Go.\n\n## Motivation\n\nThis is really just a bit of fun and a way to write CSS in Go. I wanted to see if it was possible and what would it look like.\nI wanted to find a way to easily control the CSS from the server side and not have to worry about pre-building the css to take variables and stuff.\nI didnt want to use UI libraries that are written for JS frameworks and I didn't want to use preprocessors or linters that add more steps to the build process.\n\nCould I just use CSS? Yes of course and I will, but I wanted to see if I could write CSS in Go as this is what is compiling the rest of the project.\n\n## Gopher\n\nNo it looks nothing like the Go gopher, but it's a gopher and I like it. It's the best I could get from the LM without giving up, [ideogram.ai (1400097641)](https://ideogram.ai/g/E-5MQp7QTPO4uyF9PvERzw/3).\n## Next steps\n\nThe next steps for this project are to add more features to the CSS package.\nThis includes adding support for more CSS properties when the need arises.\nWhat I don't want to do is to add support for all CSS functionality as some things are better in CSS, but I do want to be able to create \na few UI components that are configurable using Go.\n\n## Installation\n\n```bash\ngo get github.com/AccentDesign/gcss\n```\n\n## Quickstart\n\nThere is a separate repo with the full example [here](https://github.com/AccentDesign/gcss-starter) which will evolve over time.\n\n```bash\ngit clone https://github.com/AccentDesign/gcss-starter.git\n```\n\ninstall the dependencies:\n\n```bash\n# for hot reloading\ngo install github.com/cosmtrek/air@latest\n```\n\n```bash\ngo mod tidy\n```\n\nrun the server:\n\n```bash\nair\n```\n\n## Usage\n\n### Basic usage\n\n`gcss` defines a `Style` type that can be used to hold the properties for a specific css selector, eg:\n\n```go\nstyle := gcss.Style{\n    Selector: \"body\",\n    Props: gcss.Props{\n        BackgroundColor: props.ColorRGBA(0, 0, 0, 128),\n    },\n}\n```\n\nThe `CSS` function on the `Style` is used to write the style to a `io.Writer`:\n\n```go\nstyle.CSS(os.Stdout)\n```\n\nwhich gives you:\n\n```css\nbody{background-color:rgba(0,0,0,0.50);}\n```\n\nThat's all there is to it. But it's not very useful on it's own I hear you say.\n\n### Multiple styles\n\nWell you can then use that to define a `Styles` type that can be used to hold multiple `Style` types:\n\n```go\ntype Styles []gcss.Style\n\nfunc (s Styles) CSS(w io.Writer) error {\n    // handle your errors\n    for _, style := range s {\n        style.CSS(w)\n    }\n    return nil\n}\n\nstyles := Styles{\n    {\n        Selector: \"body\",\n        Props: gcss.Props{\n            BackgroundColor: props.ColorRGBA(0, 0, 0, 128),\n        },\n    },\n    {\n        Selector: \"main\",\n        Props: gcss.Props{\n            Padding: props.UnitRem(8.5),\n        },\n    },\n}\n\nstyles.CSS(os.Stdout)\n```\n\nwhich gives you:\n\n```css\n/* formatted for visibility */\nbody{\n    background-color:rgba(0,0,0,0.50);\n}\nmain{\n    padding:8.500rem;\n}\n```\n\n### Need a bit more? what about a dark and light theme? keep the last example in mind and read on.\n\nDefine a `Theme` type that can be used to hold attributes for a specific theme, eg:\n\n```go\ntype Theme struct {\n    MediaQuery string\n    Background props.Color\n}\n\nfunc (t *Theme) CSS(w io.Writer) error {\n    // handle your errors\n    fmt.Fprintf(w, \"%s{\", t.MediaQuery)\n    for _, style := range t.Styles() {\n        style.CSS(w)\n    }\n    fmt.Fprint(w, \"}\")\n}\n\n// Styles returns the styles for the theme.\n// Can be any number of styles you want and any number of functions\n// you just need them in the CSS function to loop over.\nfunc (t *Theme) Styles() Styles {\n    return Styles{\n        {\n            Selector: \"body\",\n            Props: gcss.Props{\n                BackgroundColor: t.Background,\n            },\n        },\n    }\n}\n```\n\nThen you can define a `Stylesheet` type that can be used to hold multiple `Theme` types:\n\n```go\ntype Stylesheet struct {\n    Dark  *Theme\n    Light *Theme\n}\n\nfunc (s *Stylesheet) CSS(w io.Writer) error {\n    // handle your errors\n    s.Dark.CSS(w)\n    s.Light.CSS(w)\n    return nil\n}\n```\n\nFinally, you can use the `Stylesheet` type to write the css to a `io.Writer`:\n\n```go\nstyles := Stylesheet{\n    Dark: \u0026Theme{\n        MediaQuery: \"@media (prefers-color-scheme: dark)\",\n        Background: props.ColorRGBA(0, 0, 0, 255),\n    },\n    Light: \u0026Theme{\n        MediaQuery: \"@media (prefers-color-scheme: light)\",\n        Background: props.ColorRGBA(255, 255, 255, 255),\n    },\n}\n\nstyles.CSS(os.Stdout)\n```\n\ngives you:\n\n```css\n/* formatted for visibility */\n@media (prefers-color-scheme: dark) {\n    body{\n        background-color:rgba(0,0,0,1.00);\n    }\n}\n@media (prefers-color-scheme: light) {\n    body{\n        background-color:rgba(255,255,255,1.00);\n    }\n}\n```\n\nHopefully this will get you going. The rest is up to you.\n\n* Maybe create a button function that takes a `props.Color` and returns a Style.\n* Or add extra `Styles` to the `Stylesheet` to additionally include non themed styles.\n* It's all about how you construct the `Stylesheet` and use the `gcss.Style` type.\n* If I could have created a `Stylesheet` type that fits well any use case at all I would have, but there is a world of possibility, so I left it up to you.\n\n## The benefits\n\n* Total control of the CSS from the server side.\n* CSS doesn't have mixins, but you can create a function that returns a `Style` type and reuse it.\n* Keeps the css free of variables.\n* Keeps html free of classes like `bg-gray-50 text-black dark:bg-slate-800 dark:text-white` and eliminates the need to remember to add the dark variant.\n* I recently saw a button component on an html page 10 times with over 1800 characters in the class attribute of each. This is not maintainable nor debuggable.\n* Keeps the css clean and easy to debug with no overrides like the above.\n\n## Examples\n\nFor example usage see the [examples](./examples) directory that include:\n\n* [Full example](./examples/full) - A full example including base, media and themed styles with a `sync.Mutex` for caching the css in a `http.HandleFunc`.\n* [CSS resets](./examples/css-resets) - A simple example collection of css resets.\n* [Templ integration](./examples/integration-templ) - An example of how to load styles from gcss with the [templ](https://templ.guide) package.\n* [Media queries](./examples/media-queries) - An example of how to use media queries.\n* [Template function](./examples/template-function) - An example of how to write css to the template directly via `template.FuncMap` and `template.CSS`.\n* [Write to a file](./examples/to-file) - An example of how to write to a file.\n* [Write to an HTTP handler](./examples/to-http-handler) - An example of how to write to an http handler.\n* [Write to stdout](./examples/to-stdout) - An example of how to write to stdout.\n\n## Contributing\n\nIf you would like to contribute to this project, please open an issue or a pull request. We welcome all contributions and ideas.\n\n## Mix it up with other CSS frameworks\n\nYou can mix `gcss` with other CSS frameworks like `tailwindcss` for example:\n\nseparate the css files into base and utils:\n\n```css\n/* base.css */\n@tailwind base;\n```\n\n```css\n/* utils.css */\n@tailwind utilities;\n```\n\nThen add the `gcss` styles in between in your html:\n\n```html\n\u003clink rel=\"stylesheet\" href=\"base.css\"\u003e\n\u003clink rel=\"stylesheet\" href=\"gcss-styles.css\"\u003e\n\u003clink rel=\"stylesheet\" href=\"utils.css\"\u003e\n```\n\nTry to keep the specificity of the `gcss` styles to 1 by using single classes this will ensure any `tailwindcss` utilities\nwill be able to overwrite your styles where required.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAccentDesign%2Fgcss","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FAccentDesign%2Fgcss","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAccentDesign%2Fgcss/lists"}