Styling Elements
Mint includes CSS support for styling HTML elements.
Within a component, you define styles with a style block named with an identifier:
component Test {
style base {
font-family: sans;
font-weight: bold;
color: red;
}
fun render : Html {
<div::base>
Hello
</div>
}
}
Then you apply the styles to an HTML element by specifying it after the tag of the element
<div::style/>
You can have CSS definitions, sub rules, media queries,
if
and
case
expressions inside a
style
block.
You can even apply multiple styles to an HTML element:
component Main {
style a {
color: red;
}
style b {
background: blue;
}
fun render : Html {
<div::a::b/>
}
}
Interpolation
Expressions can be interpolated in the value of a property using the
interpolation syntax
#{...}
:
component Test {
style base {
color: #{color};
}
get color : String {
"red"
}
fun render : Html {
<div::base>
Hello
</div>
}
}
Here the color of the text evaluates to
"red"
Arguments
A style block can take many arguments just like a function:
component Main {
style base(color : String) {
color: #{color};
}
fun render : Html {
<div>
<div::base("red")>
"I am red!"
</div>
<div::base("blue")>
"I am blue!"
</div>
</div>
}
}
Sub rules
Additional rules that match the element can be defined in the same block:
component Test {
style base {
color: cyan;
/* The ampersand character references the rule it resides in. */
&:focus {
color: red;
}
/* This is a sub rule which uses the descendant selector. */
a {
color: blue;
}
}
fun render : Html {
<div::base tabindex="0">
<{ "Hello " }>
<a>
<{ "world" }>
</a>
</div>
}
}
This is useful for styling pseudo elements and states or styling child elements.
@media
Media queries can be defined for a style or sub rule. When matched, their contents apply to all elements that match them.
component Test {
style base {
color: red;
@media (min-width: 600px) {
color: blue;
}
}
fun render : Html {
<div::base>
<{ "Hello " }>
</div>
}
}
@supports
@supports can be defined for a style or sub rule. When matched, their contents apply to all elements that match them.
component Test {
style base {
color: red;
@supports (display: grid) {
display: grid;
}
}
fun render : Html {
<div::base>
<{ "Hello!!" }>
</div>
}
}
@font-face
@font-face rules can be defined in a style block. The declaration will be global; meaning that any other component can reference that font.
component Test {
style base {
@font-face {
font-family: "Open Sans";
src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2"),
url("/fonts/OpenSans-Regular-webfont.woff") format("woff");
}
font-family: "Open Sans";
}
fun render : Html {
<div::base>
<{ "Hello!!" }>
</div>
}
}
@keyframes
@keyframes rules can be defined in a style block. The declaration will be global; meaning that any other component can reference that animation.
component Test {
style base {
@keyframes slidein {
from {
transform: translateX(0%);
}
to {
transform: translateX(100%);
}
}
animation: slidein 3s;
}
fun render : Html {
<div::base>
<{ "Hello!!" }>
</div>
}
}
Nesting
Sub rules
,
@media
and
@supports
rules can be nested in each other infinitely:
style base {
color: red;
div {
color: blue;
@supports (display: grid) {
display: grid;
b {
font-weight: normal;
}
}
span {
color: yellow;
@media (max-width: 500px) {
font-weight: bold;
}
}
}
}
If and Case
A special version of
if
and
case
expressions can be used inside
style
blocks:
style base {
if (loading) {
pointer-events: none;
opacity: 0.5;
}
case (status) {
Status::Ok => color: blue;
Status::Err =>
border: 1px solid red;
color: red;
}
}
Style cases have some unique rules:
- one expression rule does not apply
- you can have one or more CSS definitions in each branch
-
the
else
and empty case branch can be omitted
Inline Styles
You can use inline styles just like in HTML in two different ways:
component Main {
fun render : Html {
<div>
/* As a String */
<div style="color: red;">
"I am red!"
</div>
/* As a Map(String, String) */
try {
style =
Map.empty()
|> Map.set("color", "red")
<div style={style}>
"I am red!"
</div>
}
</div>
}
}
Behind the scenes
The compiler separates properties that have interpolations from the ones
that don't. The properties with interpolations are converted to use CSS
variables (
--test-base-color
).
During compiling the dynamic properties are converted to use a
style
object that contains the appropriate variables with their expressions.
The defined styles are static and added to the
head
of the document at runtime.