Units & Arithmetic - noprompt/garden GitHub Wiki

Units

So far we've got all the core pieces to start building basic stylesheets. But it would be useful to have something for working with one of CSS's most fundamental data types: units!

Fortunately, Garden has built in support for working with all the major CSS units. This includes creation, conversion, and arithmetic. To start using units use/require the garden.units namespace.

user=> (require '[garden.units :as u :refer [px pt]])
nil

For demonstration purposes we're only refering the px and pt units but Garden supports all of the usual suspects. Also we'll use the css macro to render the units as strings but note this is not necessary when authoring a stylesheet.

Unit creation is straightforward:

user=> (px 16)
#garden.types.CSSUnit{:unit :px, :magnitude 16}

Unit functions take a number n and construct a new garden.types.CSSUnit record with n as the magnitude. Unit functions also accept other units as values returning their conversion if possible. This makes working with unit values very flexible.

user=> (px (px 16))
16px
user=> (px (pt 1))
1.3333333333px

Unit arithmetic is available via the - spoiler alert- unit arithmetic functions.

user=> (require '[garden.units :refer (px+ px* px- px-div)])
nil
user=> (px+ 1 2 3 4 6)
16px
user=> (px-div 2 4)
0.5px
user=> (px* 2 2)
4px

Since the arithmetic functions use the primary unit functions in their definitions, conversion occurs seamlessly (when possible):

user=> (px* 2 (pt 1))
2.6666666666px

You might be wondering, which units can be converted to another? This depends on the type of unit you are working with. The CSS spec outlines a few categories of units but only absolute (px, pt, pc, in, cm, and mm), angle (deg, grad, rad, turn), time (s, ms), and frequency (Hz, kHz) units may be freely converted and only between their respective groups. This means you cannot, for example, convert px to rad or Hz to cm. Doing so will raise an error.

In the future, some exceptions to this rule might apply for working with ems since it's technically possible to compute their contextual value.

Arithmetic

Now that we have a solid understanding of how units and colors operate, we can talk about Garden's generic arithmetic operators. While working with functions like px+, color+, etc. have their advantages, sometimes they can get in the way. To get around this you can use the operators in the garden.arithmetic namespace.

(ns user
  ;; Unless you want to see a bunch of warnings add this line.
  (:refer-clojure :exclude [+ - * /])
  (:require [garden.arithmetic :refer [+ - * /]]))

This will allow you to perform operations like this:

user> (+ 20 (color/hsl 0 0 0) 1 (color/rgb 255 0 0))
#ff1515
user> (- 20 (px 1) 5 (pt 5))
7.333333333500001px