7: CSS

Phlo uses a compact, semicolon-free CSS syntax inside <style> blocks. You write rules with colons as separators:

Rules:

7.1: `<style>` block

<style>
html: height: 100dvh
body {
  background: #947b6c
  font-family: Sans-serif
  p: line-height: 2em
}
</style>

Output (conceptually):

html { height: 100dvh; }
body { background: #947b6c; font-family: Sans-serif; }
body p { line-height: 2em; }

A <style> block can target one or more bundle namespaces with ns=: <style ns=docs> compiles into www/docs.css, <style ns=app,docs> into both bundles, and a block without ns= into the defaultNS from data/app.json. See chapter 2 for the namespace model. The same attribute works on <script> blocks.

7.2: Chains & groups

Chain with colons; group with commas, and the full context is applied to each item.

<style>
body: h1, p: \:first-letter: color: green
</style>

Output:

body h1:first-letter,
body p:first-letter { color: green; }

7.3: Media queries inside a selector

You may write @media (…) inside the selector block; Phlo moves it to the right place and keeps the selector context:

<style>
h1 {
  color: white
  @media (max-width: 768px): color: black
}
</style>

Output:

h1 { color: white; }
@media (max-width: 768px){
  h1 { color: black; }
}

7.4: Variables

Phlo supports CSS variables via $names. You can define variables in :root, or at any other level, but :root is the usual place for global theming.

<style>
:root {
  $background: #0d0d0d
  $surface: #1a1a1a
  $text: #ffffff
  $accent: #ff4a00
}

body {
  background: $background
  color: $text
}

button {
  background: $accent
  color: $text
}
</style>

Output

:root {
  --background: #0d0d0d;
  --surface: #1a1a1a;
  --text: #ffffff;
  --accent: #ff4a00;
}

body {
  background: var(--background);
  color: var(--text);
}

button {
  background: var(--accent);
  color: var(--text);
}

👉 Phlo automatically converts $variables to --custom-properties and uses var(--...) where they are referenced. You can reuse variables anywhere, including inside media queries and nested selectors.

7.5: Dynamic variables

Phlo's frontend engine includes the DOM/CSS.var library, which lets you read and update defined $variables in CSS directly from JavaScript, via the global app.var object.

Every $variable in your CSS automatically becomes available as app.var.<name>.

Example

<style>
:root {
  $background: #0d0d0d
  $text: #ffffff
}
</style>

<script>
app.var.background = '#000000'
const textColor = app.var.text
</script>

👉 These updates work in real time in the browser and immediately affect all elements that use the variable.

You can use this for, among other things:

How it works

7.6: Full example

Input

html: height: 100dvh
body {
  background: #947b6c
  font-family: Sans-serif
  p: line-height: 2em
}
body: h1, p: \:first-letter: color: green
h1 {
  color: white
  @media (max-width: 768px): color: black
}
p {
  color: navy
  \:last-child: color: yellow
}

Output

body {
  background: #947b6c;
  font-family: Sans-serif;
}
body h1:first-letter,
body p:first-letter {
  color: green;
}
body p {
  line-height: 2em;
}
h1 {
  color: white;
}
html {
  height: 100dvh;
}
p {
  color: navy;
}
p:last-child {
  color: yellow;
}
@media (max-width: 768px){
  h1 {
    color: black;
  }
}

7.7: Best practices

7.8: Icon sprites

Point icons in data/app.json at one or more folders of PNG files and the build composes them into a single www/icons.png sprite plus the CSS to use them:

{
    "icons": "%app/icons/",
    "iconNS": "app"
}

Naming convention: save.png becomes class .icon.save; save.dark.png becomes the same class scoped to body.dark, so one icon name can have per-context variants (themes, states). Usage in a view:

<i.icon.save/>

The generated CSS lands in the iconNS bundle (default app) and view() preloads the sprite automatically.

We use essential cookies to make this site work. With your permission we also use analytics to improve the site.