/violetear

A minimalist CSS generator

Primary LanguageCSSMIT LicenseMIT

violetear

PyPI PyPI - Python Version PyPI - License Tests Documentation

violetear is a minimalist CSS generator in Python. You write Python code and obtain a CSS definition, that you can either render to a file and serve statically, inject dynamically into your HTML, or use as inline styles directly in your markup.

Why?

For fun, mostly... but also, because CSS is boring and repetitive. As a style language, CSS is great at describing the most varied designs. However, in terms of productivity, CSS lacks three core features that make programming languages useful: abstraction, encapsulation, and reusability.

Using a general-purpose programming language to generate CSS we can obtain the best of both worlds: the expresivity of a declarative language like CSS with the productivity of an imperative language like Python.

What?

violetear is a bridge between Python and CSS. It gives you a fluent API to generate CSS styles, full with code completion, documentation, and shorthand methods for the most common CSS rule sets. Some of the things you can do with violetear easily are:

And much more... When you combine a full-flegded programming language with powerful abstractions and carefully designed APIs, your imagination is the only limit.

How?

violetear is a pure Python package with zero dependencies. Install it with:

pip install violetear

Next, create a stylesheet:

from violetear import StyleSheet

sheet = StyleSheet()

Then you add your styles using common CSS selectors and a fluid API to quickly build complex rule sets:

title = sheet.select("#title").font(14, weight="lighter").margin(5, top=0)
subtitle = sheet.select(".subtitle").apply(title).font(12)

You can add conditional (media query) styles with a simple API:

with sheet.media(min_width=768):
    sheet.redefine(title).display("inline")

You can style specific states and add animations easily:

title.transition(timing="ease-in-out").on("hover").font(weight="bolder")

You can add custom rules for rare cases when violetear doesn't have a shorthand method:

subtitle.rule("hyphens", "auto")

Or a bunch of them all at once (_ are converted to - automatically):

subtitle.rules(
    text_decoration_color=Colors.SandyBrown,
    text_decoration_style="dashed",
)

And finally violetear has a few ready-made collection of styles for some of the most common design patterns. Here's a 12-column grid system made with flexbox with varying screen sizes that is completely customizable in just 5 lines of code:

from violetear.presets import FlexGrid

sheet.extend(FlexGrid(
    columns=12,        # 12 columns by default
    breakpoints=dict(
        lg=(1600, 8),  # Add several breakpoints at different
        md=(1200, 6),  # screen sizes changing the
        sm=(800, 4),   # number of columns and adding custom
        xs=(400, 1)    # classes for extra responsiveness
    )
))

And here's a semantic design with typography and button styles like .text.md.normal and .btn.lg.primary that is also completely customizable:

from violetear.presets import SemanticDesign

sheet.extend(SemanticDesign(
    button_class="btn",
    sizes=dict(sm=1.0, md=1.5, lg=2.0),  # Custom sizes
    colors=dict(
        normal=Colors.White.lit(0.8),    # Custom colors for different
        primary=Colors.Blue.lit(0.4),    # semantic classes
        success=Colors.Green.lit(0.4),   # applied to buttons
        error=Colors.Red.lit(0.4),       # and text
    )
).all())

Once your stylesheet is complete, you have a few options to deliver the styles to your frontend.

You can render the stylesheet into a static file:

sheet.render("static/css/main.css")

You can embed it into your HTML (e.g, using Jinja):

<style>
    {{ style.render() }}
</style>

You can use inline styles:

<h2 {{ style.subtitle.inline() }}>Subtitle</h2>

Or you can automatically add the corresponding selector attributes to a given tag:

<h2 {{ style.subtitle.markup() }}>Subtitle</h2>
<!-- Becomes -->
<h2 class="subtitle">Subtitle</h2>

The cherry on the top is a simple but expressive fluent API for generating HTML that is fully compatible with violetear's styling API. You can use it to create quick prototypes, style demo pages, etc.

from violetear.markup import Document

doc = Document(title="Example")

doc.body.create("div", "container") \
.style(Style().margin("auto").width(max=768)) \
.create("ul") \
.style(Style().padding(5, bottom=10)) \
.spawn(5, "li")
.each(
    lambda i, item: item.text(f"The {i+1}th element")
    .style(Style().color(Colors.Blue.shade(i / 5)))
)

doc.render("page.html")

Documentation

To learn more, you can:

  • Read the introductory user guide that showcases the main functionalities of the library.
  • Browse the examples to see concrete and detailed use cases.
  • Read the fully annotated API to understand the inner workings of the library.

Contribution

License is MIT, so all contributions are welcome!

The easiest way to contribute is simply by installing the library, using it to build some style you want, and then open an issue telling me what was hard or impossible for you to do. This will help me decide what to prioritize, since CSS is damn huge!

Likewise, if you're feeling adventurous, go ahead and add some fluid methods to the violetear.style.Style class to cover new CSS rules, and then open a PR.

Roadmap

Right now violetear is in pre-release mode, which means the API is completely unstable. When it reaches a reasonable level of maturity, we will release a v1.0 and stabilize the API.

v1.0 milestone checklist

  • Fluent methods for most relevant CSS rules
  • Fully documented API
  • Examples for all relevant use cases
  • Fully typed method signatures
  • Full check of argument values and rule attributes
  • Dynamic generation of CSS based on HTML parsing as well as attribute lookup
  • Parameterized presets for relevant design systems
  • Transitions and animations with helper methods to create timing curves
  • Generate simple HTML markups with a fluent API
  • Grid and flexbox styles
  • Definitions for all CSS colors
  • Creating and manipulating color palettes
  • Creating scales in any unit
  • States
  • Media queries

v.0.12.3

  • Refactor utility system.

v.0.12.2

  • Refactor markup classes.

v.0.12.1

  • Add Component class to create customizable markup elements.

v0.12.0

  • Support for generating HTML in the violetear.markup namespace.

v0.11.1

  • Tiny bug fixes

v0.11.0

  • Access colors by name, and get the name of existing colors.
  • Improve color interpolation.
  • Add utility system preset.
  • Improve documentation.
  • Improve testing.

v0.10.4

  • Support attribute syntax in CSS selectors.

v0.10.3

  • Add semantic design preset.

v0.10.2

  • Support multiple animations in a single element.

v0.10.1

  • Add support for CSS animations.

v0.10.0

  • Basic support for transitions and transforms.

v0.9.0

  • Add StyleSheet.extend to extend stylesheets with presets
  • Add FlexGrid to create flexbox grids easily

v0.8.1

  • Add color palettes with generator methods to Colors.
  • Add example with color functionality.

v0.8.0

  • Improved color space conversion in the Color class
  • Refactor a bunch of color methods
  • Added methods to tweak colors
  • Added all CSS colors to violetear.color.Colors.

v0.7.0

  • Support for grid layouts with helper methods

v0.6

  • Changed Color.palette method name
  • Support for visibility: hidden

v0.5.1

  • Improved support for flexbox

v0.5

  • Support for color palettes
  • Basic flexbox layout

v0.4.1

  • Add min/max width and height
  • Create scales of a given unit (e.g., font sizes)
  • Better support for sub-styles (e.g, :hover)
  • Support for text-align: center

v0.4

  • Support for custom states with the on method.

v0.3

  • Support for media queries via context managers

v0.2

  • Refactored style API
  • Added support for basic CSS selectors

v0.1

  • Basic API