Tecton: CSS in PureScript

Tecton is a domain-specific language for authoring CSS using PureScript. At a basic level, it could be compared to CSS preprocessors such as Sass and LESS. However, where these preprocessors aim to add expressivity to CSS, Tecton offers the full expressive power of its host language along with a high degree of type safety. It also unlocks a number of secondary benefits, such as reuse of existing PureScript knowledge and seamless colocation with related markup. If you're ready to write masterful CSS with Tecton, let's get started.

Installation

Local installation

The preferred installation method is Spago:

spago install tecton

Try PureScript

Alternatively, to evaluate Tecton without installing anything locally, you can use Try PureScript. Throughout the documentation, look for buttons like this one to launch the corresponding code example in the Try PureScript app:

Open with Try PureScript

You can give this a try now with the following example.

"Hello world" example

This example serves as a good starting point for experimenting with Tecton. Simply update the styleSheet function with your own rules to see Tecton's CSS output.

module Example.StyleSheet where

import Color (rgb)
import Data.Tuple.Nested ((/\))
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal &. ClassName "hello-world" ? Rule.do
    width := px 400
    height := px 200
    backgroundColor := rgb 0 5 56
    color := rgb 232 199 148
    display := flex
    alignItems := center
    justifyContent := center
    fontFamily := "Lexend" /\ sansSerif
    fontSize := px 32
    fontWeight := 700

Open with Try PureScript

API documentation

API documentation is available on Pursuit.

Troubleshooting

If you encounter an error that is difficult to understand, please try the following resources:

  • The test suite may offer an example of what you are trying to achieve.
  • The W3C publishes the CSS specifications that guide the design of this library.

Support

If you get stuck, help is available in the PureScript Discord chat or on the PureScript Discourse forum.

Contributing

Contributions are welcome. Please see the Contributing guide for more information.

Syntax

Declarations

The main building block of style sheets and inline styles alike is a declaration. A declaration consists of two parts: a property and a value. The property describes the aspect of the element you want to style, such as its font or color, and the value specifies what you want the property to be. Tecton uses the := operator to set the property on the left-hand side to the value on the right. For example, here is how to set the color of the text content within an HTML element to black:

module Example.InlineStyle where

import Color (black)
import Tecton

inlineStyle :: Declarations _
inlineStyle = color := black

Open with Try PureScript

Declaration blocks

A simple rule can consist of a single declaration. However, in many cases you will need to use qualified-do syntax to combine multiple declarations into a declaration block, as in the following:

module Example.InlineStyle where

import Color (black, white)
import Tecton
import Tecton.Rule as Rule

inlineStyle :: Declarations _
inlineStyle = Rule.do
  color := black
  backgroundColor := white

Open with Try PureScript

Rules

A rule consists of a prelude and either nested rules or a declaration block, joined together using the ? operator.

Note The ? operator is equivalent to the pair of curly braces surrounding a rule or declaration block in CSS.

The most common type of rule is a style rule, consisting of a selector to the left of the ? operator and a declaration block to the right, e.g.

module Example.StyleSheet where

import Color (black, white)
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal ? Rule.do
    backgroundColor := black
    color := white

Open with Try PureScript

Another type of rule is a media query, whose prelude specifies the conditions under which the nested rules apply. In the following example, the style rule applies to a printed page:

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  media print {} ? do
    body ? Rule.do
      margin := inch 1

Open with Try PureScript

Lists

Lists can be found throughout CSS, notably in selectors and many properties such as transitionProperty (which accepts a list of properties to animate). Tecton's list syntax uses the /\ operator (nested tuples). Here is how the syntax looks:

module Example.StyleSheet where

import Data.Tuple.Nested ((/\))
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do

  -- A selector list matching multiple HTML element types
  a /\ button /\ summary ? Rule.do

    -- A list of multiple properties to transition
    transitionProperty := color /\ backgroundColor

    -- A list of transition durations corresponding to each property
    transitionDuration := ms 150 /\ ms 75

Open with Try PureScript

Note The /\ operator is generally equivalent to , in CSS.

Note If you're just getting started with Tecton, you may wonder why nested tuples are used to represent lists, rather than the more "obvious" structures like Array or even List. The reason for this relates to Tecton's highly polymorphic API, which is designed to mimic the "flexible" nature of CSS itself, whose design takes full advantage of dynamic typing. Array and List are homogenous structures, while list items in Tecton frequently have various data types.

Values and units

Component values

Component values include keywords and various data types. A property value usually consists of a single component. In many cases, however, you may combine multiple components to form a complete property value. In CSS, these would typically be separated by spaces. With Tecton, you can use the ~ operator to join them together. For example:

module Example.InlineStyle where

import Tecton
import Tecton.Rule as Rule

inlineStyle :: Declarations _
inlineStyle = Rule.do

  -- Setting top, x, and bottom padding in a single declaration
  padding := px 4 ~ px 8 ~ px 16

  -- Combining two keywords
  alignSelf := safe ~ center

Open with Try PureScript

CSS-wide keywords

A few global keywords can be assigned to any property. In Tecton, these are

  • initial, which resets the property to its default value defined in the CSS specification;
  • inherit, which uses the property value inherited from the parent element; and
  • unset, which either inherits the value of an inheritable property or reverts to the initial value.

Notice how inherit, for example, is compatible with each property:

module Example.InlineStyle where

import Tecton
import Tecton.Rule as Rule

inlineStyle :: Declarations _
inlineStyle = Rule.do
  backgroundColor := inherit
  color := inherit
  fontSize := inherit
  margin := inherit
  outlineStyle := inherit

Open with Try PureScript

URLs

A URL is a pointer to a resource, such as an image, font, or custom cursor. To construct a URL value, simply apply the url function to a URL string. The following example uses the url function to create a reference to a background image:

module Example.InlineStyle where

import Tecton

inlineStyle :: Declarations _
inlineStyle = backgroundImage := url "./bg.gif"

Open with Try PureScript

Measures

The Measure type provides a common interface for many types of values, such as lengths, angles, and durations, allowing them to be calculated and/or combined via calc expressions. It is a phantom type, meaning that each value is tagged as a Length, Percentage, Time, etc. This tag ensures that incompatible values can't be combined (such as a Measure Time with a Measure Length). It also prevents the wrong kind of value from being assigned to a given property, e.g. a percentage value to a property that only supports a length.

You can construct a measure by applying the appropriate function (named for the corresponding CSS unit), followed by a number or integer, e.g. px 100 (rendered as 100px). The following table lists the various types of measures along with the functions that can be used to construct their values.

Measure typeConstructors
Lengthch, em, ex, rem, vh, vw, vmin, vmax, px, cm, mm, pc, pt, inch
Percentagepct
Angledeg, rad, turn
Timems, sec
LengthPercentagevia calc expressions
Nilnil

In some cases, measures of different types can be used interchangeably. For example, nil produces a value that can be used as a length, percentage, angle, or time. Similarly, values of type Measure Length or Measure Percentage can be used wherever a Measure LengthPercentage is expected (although the reverse is not true).

Colors

Tecton is compatible with the Color type from the colors package, along with the following CSS-specific color keywords:

  • transparent
  • currentColor

Images

Images can be used for backgrounds, custom list markers, and more. An image consists of either a URL value or a gradient.

Gradients

Linear gradients

A linear gradient can be constructed using the linearGradient function, parameterized by an angle and a color stop list.

For example, the following declaration creates a background image that transitions top to bottom from black to white:

module Example.InlineStyle where

import Color (black, white)
import Data.Tuple.Nested ((/\))
import Tecton

inlineStyle :: Declarations _
inlineStyle = backgroundImage := linearGradient (deg 180) (black /\ white)

Open with Try PureScript

Radial gradients

You can create a radial gradient using the radialGradient function.

The first parameter accepts any of the following:

  • A shape and extent (e.g. circle ~ closestSide or ellipse ~ farthestCorner)
  • A length (e.g. px 100), representing a circle radius
  • A pair of length-percentage values, representing the horizontal and vertical radii of an ellipse

The second parameter accepts the position of the center point of the gradient.

The third parameter accepts a color stop list.

Color stop lists

A color stop list defines the colors and their respective positions within a gradient. Each color stop consists of a color and an optional length-percentage position, e.g. rgb 255 0 0 or black ~ pct 50. A length-percentage transition hint may optionally be inserted between two color stops to set the midpoint in the color transition.

The following gradient demonstrates all of these options:

module Example.InlineStyle where

import Color (rgb)
import Data.Tuple.Nested ((/\))
import Tecton

inlineStyle :: Declarations _
inlineStyle =
  backgroundImage :=
    linearGradient nil $
      rgb 0 160 0 /\ rgb 0 100 0 ~ pct 75 /\ pct 80 /\ rgb 135 206 235

Open with Try PureScript

Repeating gradients

To create a repeating linear or radial gradient, simply apply the repeating function to the gradient, e.g.

module Example.InlineStyle where

import Color (black, white)
import Data.Tuple.Nested ((/\))
import Tecton

inlineStyle :: Declarations _
inlineStyle = backgroundImage := repeating $ linearGradient nil $ black /\ white

Open with Try PureScript

Positions

Position values are used in background positioning, transforms, and gradients. A position consists of one of the following:

  • center
  • top
  • right
  • bottom
  • left
  • X/Y keyword positions, e.g. left ~ top
  • single length-percentage value, e.g. px 25 or pct 50
  • X/Y length-percentage values, e.g. pct 10 ~ px 25

Selectors

A selector is a pattern that describes the scope of a rule, i.e. the set of HTML elements to which it should apply. Tecton supports several types of selectors, including element, class, ID, attribute, and pseudo-class selectors. You can combine these to form more advanced selectors or even a selector list.

Element selectors

An element selector targets all HTML elements of a particular type, such as div, p, a, or img. In its most basic form, an element selector simply consists of the target element type, e.g.

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  a ? Rule.do -- Applies to HTML `a` (anchor) elements.
    textDecorationLine := none

Open with Try PureScript

Universal selector

The universal selector is a special type of element selector that applies to any element. In CSS, it is denoted by the * symbol. In Tecton, it is called universal. Any selector that does not target another type of element must begin with the universal selector.

Note If you have written CSS before, you have almost certainly used the universal selector, perhaps without realizing: It is implicitly included in other types of selectors; for example, .foo is actually the same as *.foo. For more information, see Selectors Level 3 (W3C).

The following rule uses the universal selector to remove the margin from every element in the webpage:

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal ? Rule.do
    margin := nil

Open with Try PureScript

Class selectors

A class selector matches any element whose class attribute contains the specified class name. The &. operator appends the target class to a selector. For example, the following selector targets all elements with the class name container:

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal &. ClassName "container" ? Rule.do
    width := auto

Open with Try PureScript

ID selectors

An ID selector targets the element whose id attribute is exactly the specified value. The &# operator appends the element ID to another selector. The selector in the following example matches the element with ID appBar:

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal &# ElementId "appBar" ? Rule.do
    height := px 64

Open with Try PureScript

Attribute selectors

An attribute selector targets elements based on their attributes or attribute values. It can match on the presence of any HTML attribute such as href, src, or alt. A number of operators can further limit matches to specific attribute values.

Presence

To match elements based on the presence of an attribute, the attribute is used by itself without any additional operator. For example, the following selector applies to an input element with a required attribute:

module Example.StyleSheet where

import Color (rgb)
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  input &@ required ? Rule.do
    backgroundColor := rgb 255 153 0

Open with Try PureScript

Exact value

The @= operator can be used to target an element whose attribute value exactly matches the specified value. For example, the following selector matches elements with the attribute role="button":

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal &@ role @= "button" ? Rule.do
    fontWeight := bold

Open with Try PureScript

Value within list

The ~= operator can be used to find a matching value within a whitespace-delimited list of words. In the following example, the selector will match an element with an attribute class="foo bar baz". (This is, of course, equivalent to a class selector.)

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal &@ class' ~= "bar" ? Rule.do
    display := none

Open with Try PureScript

Code/subcode

Intended primarily for locale tags, the |= operator matches when an attribute value

  • exactly matches the specified value or
  • begins with the specified value followed by a hyphen.

The selector in the following example will match an a element whose hreflang attribute is equal to "en" or "en-US", but not "end":

module Example.StyleSheet where

import Color (rgb)
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  a &@ hreflang |= "en" ? Rule.do
    color := rgb 255 0 196

Open with Try PureScript

Prefix

You can use the ^= operator to represent an element whose attribute value begins with the specified value. The following example targets insecure links based on their http:// prefix:

module Example.StyleSheet where

import Color (rgb)
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  a &@ href ^= "http://" ? Rule.do
    color := rgb 255 0 0

Open with Try PureScript

Suffix

The $= operator matches an element with an attribute value ending in the specified value. This can be used to target a link to a PDF, for instance:

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  a &@ href $= ".pdf" ? Rule.do
    fontWeight := bold

Open with Try PureScript

Substring

To target an element whose attribute value simply contains a given substring, use the *= operator. The following selector matches any image sourced from Wikimedia:

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  img &@ src *= "wikimedia.org" ? Rule.do
    display := initial

Open with Try PureScript

Pseudo-classes

A pseudo-class can be used to style elements based on their state or position in the DOM tree. You can append a pseudo-class to the end of a selector using the &: operator. For instance, the focus pseudo-class applies a style conditionally when the element has focus:

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal &: focus ? Rule.do
    outlineStyle := solid

Open with Try PureScript

Basic pseudo-classes

The most common pseudo-classes usually consist of a single keyword, such as the following:

  • link targets an unvisited link, i.e. an a element that the user has not yet clicked or visited.
  • visited targets a visited link, i.e. an a element that the user has clicked or visited in the past.
  • hover matches an element while the user's mouse cursor hovers over it.
  • focus matches an element when it has keyboard focus. An element typically receives focus through user interaction, such as clicking on an input field.
  • focusWithin targets an element containing a descendant element that has keyboard focus.
  • active matches an element while it is being clicked, pressed, or activated.
  • target targets an element whose ID matches the current location hash. This is often useful with deep-linking in order to draw the user's attention to the requested section of the page.
  • enabled targets an interactive element (e.g. input, select, or button) that is enabled.
  • disabled targets an interactive element (e.g. input, select, or button) that is disabled.
  • checked matches a radio button, checkbox, or option element that is checked or selected.
  • indeterminate matches a checkbox element in an indeterminate state, i.e. neither checked nor unchecked.
  • root targets the highest-level element in the document, typically an html element.
  • firstChild targets an element with no preceding siblings.
  • lastChild targets an element with no subsequent siblings.
  • firstOfType matches an element with no preceding siblings of the same type.
  • lastOfType matches an element with no subsequent siblings of the same type.
  • onlyChild matches an element with no siblings.
  • onlyOfType matches an element with no siblings of the same type.
  • empty matches an element with no children or that contains only empty text nodes.

The lang pseudo-class

The lang pseudo-class can be used to target an element based on the value of its lang attribute (or the value inherited from an ancestor). The lang pseudo-class is parameterized by a one- or two-part language tag consisting of an ISO 639-1 language code, optionally followed by a hyphen and an ISO 3166-1 alpha-2 country code. To construct the pseudo-class, apply the lang function to the language tag string. For example:

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal &: lang "en-US" ? Rule.do
    display := none

Open with Try PureScript

The not pseudo-class

The not pseudo-class targets an element that does not match the specified selector. You can pass any selector to the not function to construct the pseudo-class. For example, the following selector will match any input element lacking a type attribute:

module Example.StyleSheet where

import Color (rgb)
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  input &: not (universal &@ type') ? Rule.do
    backgroundColor := rgb 255 0 0

Open with Try PureScript

Nth pseudo-classes

A special group of pseudo-classes allows you to select an element by its position within the parent element. These use a formula of the form an+b where:

  • a determines the frequency of matches. For example, 3n can be interpreted as every third element.
  • b represents an offset, i.e. the index of the first matching element (one-indexed). For example, 2 will match the second element, before the pattern repeats.

These pseudo-classes are

  • nthChild, which selects elements matching the an+b formula within their parent;
  • nthLastChild, which reverses the direction of nthChild, counting from the last child element within a container;
  • nthOfType, which is like a version of nthChild that ignores sibling elements of a different type when evaluating the an+b formula; and
  • nthLastOfType, which reverses the direction of nthOfType, counting from the last child element within a container.

The :nth Tester (CSS-Tricks) offers an interactive way to learn how these pseudo-classes and the an+b formula work.

Constructing these pseudo-classes in Tecton begins with the formula:

  • The even function will select even-numbered elements, equivalent to 2n.
  • The odd function will select odd-numbered elements, equivalent to 2n+1.
  • The #+ operator has two parameters a and b, used to create an an+b formula, e.g. 2 #+ 1.
  • The #- operator has two parameters a and b, used to create an an-b formula, e.g. 2 #- 1.

Apply one of the nth* functions listed above to the result to create the pseudo class.

Here is how nthChild, for instance, can be used to add zebra-striping to a table:

module Example.StyleSheet where

import Color (rgb)
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  tr &: nthChild even ? Rule.do
    backgroundColor := rgb 240 240 240

Open with Try PureScript

Pseudo-elements

Pseudo-elements are virtual elements that can be styled using CSS but exist outside of the DOM. These offer control and flexibility in design without modifying HTML structure. You can append a pseudo-element to a selector using the &:: operator. For example, the following adds a red asterisk symbol to a required form field label using the after pseudo-element:

module Example.StyleSheet where

import Color (rgb)
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal &. ClassName "required" &:: after ? Rule.do
    content := " *"
    color := rgb 255 0 0

Open with Try PureScript

Note that, once a pseudo-element has been appended to selector, the selector can no longer be modified; otherwise, the resulting CSS would be invalid.

Selector list

A common CSS pattern is a ruleset that targets elements matching any of a number of selectors. This is useful as a performance optimization as well to avoid duplication.

Throughout the library, lists are modeled using nested tuples via the /\ operator. Selector lists are no exception.

Here is an example of a ruleset the applies to buttons as well as hyperlinks (a elements) masquerading as buttons:

module Example.StyleSheet where

import Data.Tuple.Nested ((/\))
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  button /\ a &. ClassName "button" ? Rule.do
    fontWeight := bold

Open with Try PureScript

See also

Animations

CSS animations are a powerful tool for adding motion and interactivity to a webpage. They allow you to animate various properties of HTML elements, such as position, size, color, and opacity.

Defining keyframes

Animations are defined using keyframes, which specify the intermediate states of an element during the animation. Keyframe rules define the stages of an animation in terms of percent progress. Each rule indicates the value of a given CSS property at that point in the animation.

For example, the following keyframes transition the background and foreground colors between black and white:

module Example.StyleSheet where

import Color (black, white)
import Data.Tuple.Nested ((/\))
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  keyframes (KeyframesName "black-and-white") ? do
    pct 0 /\ pct 100 ? Rule.do
      backgroundColor := black
      color := white
    pct 50 ? Rule.do
      backgroundColor := white
      color := black

Open with Try PureScript

Creating animation

Animating elements requires at minimum a keyframe animation name and duration, for example:

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  universal ? Rule.do
    animationName := KeyframesName "black-and-white"
    animationDuration := ms 150

Open with Try PureScript

A range of properties can be used to control animations:

  • animationName specifies the name of the keyframe animation to apply.
  • animationDuration sets the duration of the animation.
  • animationTimingFunction defines the timing curve for the animation (e.g. linear, easeIn, or easeOut).
  • animationDelay adds a delay before the animation starts.
  • animationIterationCount sets the number of times the animation should repeat.
  • animationDirection controls whether the animation should play in the normal or reverse directions, or should alternate (or alternateReverse).
  • animationFillMode specifies how the element should be styled before and after the animation (e.g. none, forwards, backwards or both).

Each of these properties also supports a list of animations by using Tecton's list syntax based on nested tuples, e.g. animationDuration := ms 150 /\ ms 250 /\ ms 75.

Transitions

Keyframe animations provide flexibility and control for complex, multi-step animations. For basic, one-off property changes triggered by events, transitions offer a lightweight approach with no need for a keyframes at-rule. Instead, you simply leverage the following properties:

  • transitionProperty specifies the property to be transitioned.
  • transitionDuration specifies the length of time over which the transition should occur.
  • transitionTimingFunction defines the timing function used for the transition. It determines how intermediate property values are calculated over time.
  • transitionDelay sets a delay before the transition starts.

Like animation properties, each of the transition properties supports a list of values, e.g. transitionProperty := width /\ height /\ padding.

For example, the following rulesets transition the background and foreground colors over a 150-millisecond period on hover:

module Example.StyleSheet where

import Color (black, white)
import Data.Tuple.Nested ((/\))
import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  let transitionDemo = ClassName "transition-demo"
  universal &. transitionDemo ? Rule.do
    transitionProperty := backgroundColor /\ color
    transitionDuration := ms 150
    transitionTimingFunction := ease
    backgroundColor := white
    color := black
  universal &. transitionDemo &: hover ? Rule.do
    backgroundColor := black
    color := white

Open with Try PureScript

See also

Calc expressions

Calc expressions allow you to perform calculations within CSS property values, supporting a wide range of use cases such as responsive design, grid systems, and fluid typography.

Several calc operators are supported:

  • @+@ adds two operands, e.g. pct 90 @+@ px 16.
  • @-@ subtracts the second operand from the first, e.g. pct 100 - px 32.
  • @* multiplies the first operand by the second, e.g. px 16 @* 2.
  • *@ multiplies the first operand by the second, e.g. 2 *@ px 16.
  • @/ divides the first operand by the second, e.g. pct 100 @/ 6.

Notice that each operator includes one or more @ symbols. An operand that is adjacent to this symbol is a measure; otherwise, it is a number or integer.

Here is an example of how the @-@ and @* operators can be used to make a div element span the width of the viewport, but leaving a 32-pixel "margin" on each side:

module Example.StyleSheet where

import Tecton
import Tecton.Rule as Rule

styleSheet :: CSS
styleSheet = do
  body ? margin := nil
  div ? Rule.do
    margin := nil ~ auto -- horizontal centering
    width := vw 100 @-@ px 32 @* 2

Open with Try PureScript

Rendering

Just as PureScript code must be compiled to JavaScript to run in the web browser, CSS rules written using Tecton must be rendered to plain CSS strings. Tecton provides two rendering functions depending on your use case, as well as options for pretty-printing or compact output.

Inline styles

To render a group of declarations, use the renderInline function. As the name suggests, the output is appropriate for inline styles, i.e. for use in the style attribute of an HTML element. For example:

module Example where

import Prelude (Unit, ($), (<>))
import Effect (Effect)
import TryPureScript (render) as TryPureScript
import Unsafe.Coerce (unsafeCoerce)

import Color (rgb)
import Tecton
import Tecton.Rule as Rule

renderedInlineStyle :: String
renderedInlineStyle =
  renderInline Rule.do
    width := px 400
    height := px 200
    backgroundColor := rgb 0 5 56
    color := rgb 232 199 148
    display := flex
    alignItems := center
    justifyContent := center
    fontFamily := sansSerif
    fontSize := px 32
    fontWeight := 700

main :: Effect Unit
main =
  TryPureScript.render
    $ unsafeCoerce
    $ "<div style=\"" <> renderedInlineStyle <> "\">Hello world!</div>"

Open with Try PureScript

Style sheets

For a style sheet, which contains statements (e.g. selectors and at-rules) instead of "top-level" declarations, use the renderSheet function. This function accepts a configuration argument followed by the CSS parameter. For configuration, choose between the following options:

  1. pretty prints the CSS output in a human-readable format.
  2. compact optimizes the output for performance, for example removing unnecessary whitespace and using short hex strings for colors.

The following example demonstrates how to render a style sheet with each configuration. Open it in Try PureScript to compare the output.

module Example where

import Prelude (Unit, ($), (<>))
import Effect (Effect)
import TryPureScript (render) as TryPureScript
import Unsafe.Coerce (unsafeCoerce)

import Color (rgb)
import Tecton
import Tecton.Rule as Rule

containerClass = ClassName "container" :: ClassName

css :: CSS
css =
  universal &. containerClass ? Rule.do
    width := px 400
    height := px 200
    backgroundColor := rgb 0 5 56
    color := rgb 232 199 148
    display := flex
    alignItems := center
    justifyContent := center
    fontFamily := sansSerif
    fontSize := px 32
    fontWeight := 700

main :: Effect Unit
main =
  TryPureScript.render
    $ unsafeCoerce
    $ "<style>" <> renderSheet compact css <> "</style>" <>
      "<div class=\"" <> (\(ClassName c) -> c) containerClass <> "\">Hello world!</div>" <>
      "<pre><code>\npretty:\n\n" <>
      renderSheet pretty css <>
      "\n\ncompact:\n" <>
      renderSheet compact css <>
      "</pre></code>"

Open with Try PureScript