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:
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
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
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
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
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
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
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 evenList
. 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
andList
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
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; andunset
, 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
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"
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 type | Constructors |
---|---|
Length | ch , em , ex , rem , vh , vw , vmin , vmax , px , cm , mm , pc , pt , inch |
Percentage | pct |
Angle | deg , rad , turn |
Time | ms , sec |
LengthPercentage | via calc expressions |
Nil | nil |
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)
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
orellipse ~ 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
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
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
orpct 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
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
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
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
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
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
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
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
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
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
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
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
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. ana
element that the user has not yet clicked or visited.visited
targets a visited link, i.e. ana
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
, orbutton
) that is enabled.disabled
targets an interactive element (e.g.input
,select
, orbutton
) 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 anhtml
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
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
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 ofnthChild
, counting from the last child element within a container;nthOfType
, which is like a version ofnthChild
that ignores sibling elements of a different type when evaluating the an+b formula; andnthLastOfType
, which reverses the direction ofnthOfType
, 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
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
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
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
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
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
, oreaseOut
).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 thenormal
orreverse
directions, or shouldalternate
(oralternateReverse
).animationFillMode
specifies how the element should be styled before and after the animation (e.g.none
,forwards
,backwards
orboth
).
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
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
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>"
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:
pretty
prints the CSS output in a human-readable format.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>"