gcss

package module
v0.0.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 27, 2024 License: MIT Imports: 4 Imported by: 1

README

Test Go Report Card

gcss

CSS written in Pure Go.

No JS builders, no preprocessors, no linters, no frameworks, no classes, no variables, no overrides, no plugins, no dependencies, no javascript, no templates, no bs, no nothing.

Just Go.

Motivation

The gcss project is a unique approach to writing CSS using Go. The motivation behind this project is not to replace CSS entirely, but to provide a way to write CSS in Go. This allows developers to leverage Go's features to generate CSS. For instance, Go's text/template or templ package can be used to generate CSS based on some data. This opens up new possibilities for dynamic and data-driven styling in web development.

Next steps

The next steps for this project are to add more features to the CSS package. This includes adding support for more CSS properties and maybe mixins. What 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 a few UI components that are configurable using Go.

What I don't need

  • I don't need UI libs that are written for the purpose of JS frameworks.
  • I don't need linters when I have Go's static typing.
  • I don't need javascript to generate CSS.
  • I don't need templates with 400 css classes in them.
  • I don't need css with more variables in them than actual css properties.

What I do need

  • Go, HTMX and maybe a few manual css styles.

Installation

go get github.com/AccentDesign/gcss

Usage

There are multiple ways you can use gcss in your project. For examples of property values, see the style_test.go file.

File

write to a file:

var styles = []gcss.Style{
    {
        Selector: ".button",
        Props: gcss.Props{
            BackgroundColor: props.ColorRGBA(17, 24, 39, 255),
        },
    },
}

f, err := os.Create("styles.css")
if err != nil {
    panic(err)
}

for _, style := range styles {
    if err := style.CSS(f); err != nil {
        panic(err)
    }
}
Http handler

write using an http handler:

var styles = []gcss.Style{
    {
        Selector: ".button",
        Props: gcss.Props{
            BackgroundColor: props.ColorRGBA(17, 24, 39, 255),
        },
    },
}

http.HandleFunc("/styles.css", func(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/css")
    for _, style := range styles {
        if err := style.CSS(w); err != nil {
            panic(err)
        }
    }
})
Theming

Example of theming using gcss, the below could write to 2 separate css files or route handlers for dark and light themes.

// Theme is a struct that holds the theme properties.
type Theme struct {
    Background            props.Color
}

// WriteCSS writes the css for the theme to the writer.
func (t *Theme) WriteCSS(w io.Writer) {
    for _, e := range t.styles() {
        if err := e.CSS(w); err != nil {
            panic(err)
        }
    }
}

// styles returns the styles for the theme.
func (t *Theme) styles() []gcss.Style {
    return []gcss.Style{
        {
            Selector: "body",
                Props: gcss.Props{
                BackgroundColor: t.Background,
            },
        },
    }
}

// DarkTheme is a struct that holds the dark theme properties.
type DarkTheme struct {
    Theme
}

// LightTheme is a struct that holds the light theme properties.
type LightTheme struct {
    Theme
}

// NewDarkTheme creates a new dark theme.
func NewDarkTheme() *DarkTheme {
    return &DarkTheme{
        Theme: Theme{
            Background: props.ColorRGBA(38, 40, 46, 255),
        },
    }
}

// NewLightTheme creates a new light theme.
func NewLightTheme() *LightTheme {
    return &LightTheme{
        Theme: Theme{
            Background: props.ColorRGBA(255, 255, 255, 255),
        },
    }
}

Then switch between them using media queries in your HTML.

<!-- Light theme -->
<link rel="stylesheet" href="light.css" media="(prefers-color-scheme: light)" />

<!-- Dark theme -->
<link rel="stylesheet" href="dark.css" media="(prefers-color-scheme: dark)" />

The benefit of this:

  • Keeps the css free of variables
  • 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
  • Keeps the css clean and easy to debug with no overrides like the above
  • Allows for easy theming based on server side logic

Mix it up with other CSS frameworks

You can mix gcss with other CSS frameworks like tailwindcss for example:

separate the css files into base and utils:

/* base.css */
@tailwind base;
/* utils.css */
@tailwind utilities;

Then add the gcss styles in between in your html:

<link rel="stylesheet" href="base.css" />
<link rel="stylesheet" href="gcss-styles.css" />
<link rel="stylesheet" href="utils.css" />

Try to keep the specificity of the gcss styles to 1 by using single classes this will ensure any tailwindcss utilities will be able to overwrite your styles where required.

Examples

CSS:

go run examples/styles/cli/main.go export -directory "examples/static/css"

Hugo:

cd examples
hugo server -D

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CustomProp added in v0.0.5

type CustomProp struct {
	Attr, Value string
}

CustomProp represents an additional CSS property that is not covered by the Props struct.

type Props

type Props struct {
	AlignItems              props.AlignItems          `css:"align-items"`
	Appearance              props.Appearance          `css:"appearance"`
	BackgroundColor         props.Color               `css:"background-color"`
	BackgroundImage         props.BackgroundImage     `css:"background-image"`
	BackgroundPosition      props.BackgroundPosition  `css:"background-position"`
	BackgroundRepeat        props.BackgroundRepeat    `css:"background-repeat"`
	BackgroundSize          props.BackgroundSize      `css:"background-size"`
	BorderColor             props.Color               `css:"border-color"`
	Border                  props.Border              `css:"border"`
	BorderBottom            props.Border              `css:"border-bottom"`
	BorderBottomLeftRadius  props.Unit                `css:"border-bottom-left-radius"`
	BorderBottomRightRadius props.Unit                `css:"border-bottom-right-radius"`
	BorderLeft              props.Border              `css:"border-left"`
	BorderRadius            props.Unit                `css:"border-radius"`
	BorderRight             props.Border              `css:"border-right"`
	BorderStyle             props.BorderStyle         `css:"border-style"`
	BorderTop               props.Border              `css:"border-top"`
	BorderTopLeftRadius     props.Unit                `css:"border-top-left-radius"`
	BorderTopRightRadius    props.Unit                `css:"border-top-right-radius"`
	BorderWidth             props.Unit                `css:"border-width"`
	Bottom                  props.Unit                `css:"bottom"`
	BoxSizing               props.BoxSizing           `css:"box-sizing"`
	CaptionSide             props.CaptionSide         `css:"caption-side"`
	Color                   props.Color               `css:"color"`
	ColumnGap               props.Unit                `css:"column-gap"`
	Cursor                  props.Cursor              `css:"cursor"`
	Display                 props.Display             `css:"display"`
	FlexBasis               props.Unit                `css:"flex-basis"`
	FlexDirection           props.FlexDirection       `css:"flex-direction"`
	FlexGrow                props.Unit                `css:"flex-grow"`
	FlexShrink              props.Unit                `css:"flex-shrink"`
	FlexWrap                props.FlexWrap            `css:"flex-wrap"`
	Float                   props.Float               `css:"float"`
	FontFamily              props.FontFamily          `css:"font-family"`
	FontSize                props.Unit                `css:"font-size"`
	FontStyle               props.FontStyle           `css:"font-style"`
	FontWeight              props.FontWeight          `css:"font-weight"`
	Gap                     props.Unit                `css:"gap"`
	Height                  props.Unit                `css:"height"`
	JustifyContent          props.JustifyContent      `css:"justify-content"`
	JustifyItems            props.JustifyItems        `css:"justify-items"`
	JustifySelf             props.JustifySelf         `css:"justify-self"`
	Left                    props.Unit                `css:"left"`
	LineHeight              props.Unit                `css:"line-height"`
	ListStylePosition       props.ListStylePosition   `css:"list-style-position"`
	ListStyleType           props.ListStyleType       `css:"list-style-type"`
	Margin                  props.Unit                `css:"margin"`
	MarginBottom            props.Unit                `css:"margin-bottom"`
	MarginLeft              props.Unit                `css:"margin-left"`
	MarginRight             props.Unit                `css:"margin-right"`
	MarginTop               props.Unit                `css:"margin-top"`
	MaxWidth                props.Unit                `css:"max-width"`
	MinWidth                props.Unit                `css:"min-width"`
	Opacity                 props.Unit                `css:"opacity"`
	Overflow                props.Overflow            `css:"overflow"`
	OverflowX               props.Overflow            `css:"overflow-x"`
	OverflowY               props.Overflow            `css:"overflow-y"`
	Padding                 props.Unit                `css:"padding"`
	PaddingBottom           props.Unit                `css:"padding-bottom"`
	PaddingLeft             props.Unit                `css:"padding-left"`
	PaddingRight            props.Unit                `css:"padding-right"`
	PaddingTop              props.Unit                `css:"padding-top"`
	Position                props.Position            `css:"position"`
	PrintColorAdjust        props.PrintColorAdjust    `css:"print-color-adjust"`
	Right                   props.Unit                `css:"right"`
	RowGap                  props.Unit                `css:"row-gap"`
	TextAlign               props.TextAlign           `css:"text-align"`
	TextDecorationColor     props.Color               `css:"text-decoration-color"`
	TextDecorationLine      props.TextDecorationLine  `css:"text-decoration-line"`
	TextDecorationStyle     props.TextDecorationStyle `css:"text-decoration-style"`
	TextDecorationThickness props.Unit                `css:"text-decoration-thickness"`
	TextIndent              props.Unit                `css:"text-indent"`
	TextOverflow            props.TextOverflow        `css:"text-overflow"`
	TextTransform           props.TextTransform       `css:"text-transform"`
	TextUnderlineOffset     props.Unit                `css:"text-underline-offset"`
	TextWrap                props.TextWrap            `css:"text-wrap"`
	Top                     props.Unit                `css:"top"`
	VerticalAlign           props.VerticalAlign       `css:"vertical-align"`
	WhiteSpace              props.WhiteSpace          `css:"white-space"`
	Width                   props.Unit                `css:"width"`
	Visibility              props.Visibility          `css:"visibility"`
	ZIndex                  props.Unit                `css:"z-index"`
}

Props represents the standard CSS properties that can be applied to a CSS rule.

type Style

type Style struct {
	// Selector is the CSS selector to which the properties will be applied.
	// It can be any valid CSS selector like class, id, element type, etc.
	Selector string

	// Props contains the standard CSS properties that will be applied to the selector.
	// These properties are represented by the Props struct and are strongly typed.
	Props Props

	// CustomProps contains any additional CSS properties that are not covered by the Props struct.
	// These properties are directly added to the CSS rule as is.
	CustomProps []CustomProp
}

Style represents a CSS style rule.

func (*Style) CSS

func (s *Style) CSS(w io.Writer) error

CSS writes the CSS representation of the style to the writer.

Directories

Path Synopsis
examples
styles/cli command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL