KnitCSS CSS in your templates
Documentation / Complete guide

Knit, without
the mystery.

From the first declaration to custom directives, template boundaries and CLI workflows. The syntax stays close to CSS; Knit decides where that CSS belongs.

01 / Getting started

Start with !

A Knit declaration starts with an exclamation mark. Everything inside its braces is normal CSS, so existing CSS knowledge transfers directly.

Template
<div class="!{color:red}">
 Hello World
</div>

Selectors go between the marker and the declaration block. Direct CSS at-rules also work, while projects generated with knitcss --init get the recommended !at(...) breakpoint directive.

Template
<button class="!:hover{color:red}">Button</button>

<div class="!@media(min-width:768px){display:grid}">...</div>

<div class="!at(medium){display:grid}">...</div>

Minimal configuration

Knit reads a knitcss.ini file. A project needs an input directory, output directory and CSS output file, plus at least one template definition.

knitcss.ini
[knit]
in_directory = "src"
out_directory = "dist"
css_file = "public/knit.css"

[boundaries]
string1[] = "'","'"
string2[] = '"','"'

[template.html]
extensions[] = ".html"
boundaries[] = "string1","string2"

First commands

knitcss --initCreate a default configuration with the standard at breakpoint directive.
knitcssCompile the project once.
knitcss --watchCompile immediately, then watch for changes.
02 / Template syntax

Declarations stay CSS.

The basic form is !{property:value}. Put multiple properties in one declaration or split them into multiple declarations when that improves readability.

One declaration
!{color:red;background:black;font-weight:bold}
Several declarations
!{color:red} !{background:black}
Template
<button class="!{color:white;background:black;padding:10px 20px;border-radius:6px} !:hover{background:gray}">
 Button
</button>

For global and base element styles, KnitCSS recommends using vanilla CSS in a standard stylesheet or style tag. Use KnitCSS for styles that are closely coupled to the markup they belong to.

03 / Selectors

Use normal selectors.

Put a CSS selector after !. Pseudo-classes and normal combinators can be used directly.

!:hover{color:red}Pseudo-class
!>p{color:red}Direct child
! .icon{opacity:.5}Descendant
!+p{margin-top:0}Adjacent sibling
!~p{color:#666}General sibling
Template
<button class="!{opacity:1} !:hover{opacity:.8} !:active{opacity:.6}">
 Button
</button>

KnitCSS supports complex selectors, but styling each element directly keeps your code easier to read, change, and maintain.

04 / At-rules & breakpoints

Responsive without a new language.

Direct at-rules such as !@media(...), !@supports(...) and !@container(...) are supported when they contain declarations.

Template
<div class="!{display:block} !@media(min-width:768px){display:grid}">...</div>

<div class="!@supports(display:grid){display:grid}">...</div>

<div class="!@container(min-width:400px){font-size:20px}">...</div>

Recommended breakpoint syntax

The default config created by knitcss --init includes a custom at directive. Use its named cases for a shared responsive vocabulary.

Template
<div class="!{display:block} !at(medium){display:grid}">...</div>

<div class="!at(small-only){display:block}">...</div>
base-onlymax-width: 319px
xx-small / xx-small-only≥ 320px / 320–479px
x-small / x-small-only≥ 480px / 480–639px
small / small-only≥ 640px / 640–767px
medium / medium-only≥ 768px / 768–1023px
large / large-only≥ 1024px / 1024–1279px
x-large / x-large-only≥ 1280px / 1280–1535px
xx-large≥ 1536px
knitcss.ini
[directive.at]
at-rule[base-only]="@media(max-width:319px)"
at-rule[xx-small]="@media(min-width:320px)"
at-rule[xx-small-only]="@media(min-width:320px) and (max-width:479px)"
at-rule[x-small]="@media(min-width:480px)"
at-rule[x-small-only]="@media(min-width:480px) and (max-width:639px)"
at-rule[small]="@media(min-width:640px)"
at-rule[small-only]="@media(min-width:640px) and (max-width:767px)"
at-rule[medium]="@media(min-width:768px)"
at-rule[medium-only]="@media(min-width:768px) and (max-width:1023px)"
at-rule[large]="@media(min-width:1024px)"
at-rule[large-only]="@media(min-width:1024px) and (max-width:1279px)"
at-rule[x-large]="@media(min-width:1280px)"
at-rule[x-large-only]="@media(min-width:1280px) and (max-width:1535px)"
at-rule[xx-large]="@media(min-width:1536px)"

At-rule plus selector

With a raw at-rule, put & between the at-rule and selector. The default at directive does not require that separator.

Template
<button class="!@media(min-width:768px)&:hover{color:red}">Button</button>

<button class="!at(medium):hover{color:red}">Button</button>
05 / CSS nesting

Native nesting still works.

Inside a declaration block, & has its normal CSS nesting meaning. Separate Knit declarations are often shorter, but nesting remains available when it reads better.

Template
<button class="!{
 color:black;

 &:hover{
 color:red;
 }
}">
 Button
</button>

KnitCSS supports CSS nesting, but keeping declarations separate makes your code easier to read, change, and maintain.

06 / Built-in directives

Name it. Copy it.

Knit includes two built-ins: id gives a declaration a reusable name, and copy reuses one or more named declarations.

Template
<div class="!id(card){padding:20px;border-radius:8px}">
 First card
</div>

<div class="!copy(card){background:white}">
 Second card
</div>

Local properties override copied ones. IDs may contain letters, numbers, hyphens and underscores; each ID must be unique in the template.

Multiple IDs

Template
<div class="!copy(layout,surface,text){padding:24px}">...</div>

Copied declarations are combined in listed order, then the local declaration is applied.

Partial copy

cardCopy everything.
card.at-ruleCopy only the at-rule portion.
card.selectorCopy only the selector portion.
card.declarationCopy only the declarations.
Template
<div class="!copy(card.declaration){background:black}">...</div>
07 / Custom directives

Add project vocabulary.

Custom directives live in knitcss.ini. A directive can contribute an at-rule, selector or CSS declarations, and can have named or argument-count cases.

At-rule directive

knitcss.ini
[directive.at]
at-rule[medium] = "@media(min-width:768px)"
at-rule[medium-only] = "@media(min-width:768px) and (max-width:1023px)"
Template
<div class="!at(medium){display:grid}">...</div>

Selector directive

knitcss.ini
[directive.state]
selector[hover] = ":hover"
selector[focus] = ":focus"
Template
<button class="!state(hover){color:red}">Button</button>

Declaration directive

knitcss.ini
[directive.stack]
declaration = "display:flex;flex-direction:column"
Template
<div class="!stack{gap:10px}">...</div>

Directive arguments

A numeric case matches the number of arguments. Use \1, \2, \3 and so on inside the configured action.

Template
[directive.range]
at-rule[2] = "@media(min-width:\1) and (max-width:\2)"

<div class="!range(640px,1024px){display:grid}">...</div>
08 / Configuration

Explicit project wiring.

Configuration is organized into INI sections. Strings can use single or double quotes, booleans are unquoted, lists use [], and named entries use bracket keys.

knitcss.ini
[knit]
in_directory = "src"
out_directory = "dist"
css_file = "public/knit.css"
cache_file = "dist/.knitcss"
exclude_paths[] = "vendor","generated"
signal_file = "dist/.changed"
signal_content = "KNIT_TIME\nKNIT_PATHS"
in_directoryDirectory containing source templates. Required.
out_directoryDirectory where compiled templates are written. Required.
css_fileGenerated stylesheet path. Required.
cache_fileOptional cache location. Defaults to .knitcss inside the output directory.
exclude_paths[]Exclude files or directories relative to the input directory.
signal_fileOptional file Knit updates when the project changes.
signal_contentCustomize signal content with KNIT_TIME and KNIT_PATHS.

Replacements

The [replacements] section performs simple text replacements in compiled templates. 1790928721 is also available as a built-in replacement.

knitcss.ini
[replacements]
ASSET_ROOT = "/assets"
API_VERSION = "v2"

<img src="ASSET_ROOT/logo.svg">
09 / Boundaries & templates

Tell Knit where syntax is legal.

Boundaries limit where Knit syntax is scanned. In this example, for HTML templates, a class-attribute boundary keeps Knit from interpreting unrelated text elsewhere in the file.

knitcss.ini
[boundaries]
class[] = '\sclass\s[0:]=\s[0:]"', '"'

[template.html]
extensions[] = ".html"
boundaries[] = "class"

Boundary matchers

\cAny character
\sWhitespace
\vNon-whitespace
\n / \r / \tNewline, carriage return, tab
\Backslash
\s[3]Exactly three repetitions
\s[1:3]From one to three
\s[:3]Up to three
\s[1:]One or more
\s[0:]Zero or more

Templates

Template sections are named [template.<name>]. They choose file extensions, active boundaries and whitespace behavior. Full suffixes such as .blade.php are supported.

knitcss.ini
[template.markup]
extensions[] = ".html", ".blade.php"
boundaries[] = "class"
optimize_whitespaces = true
keep_indentation = true
keep_new_lines = true

Set optimize_whitespaces = false when you want Knit to leave template formatting unchanged.

Child templates

A boundary region can be delegated to another configured template, for example, a script region inside an HTML template.

knitcss.ini
[template.html]
templates[script] = "javascript"

templates[script][] = "javascript", "embedded"

An empty child template templates[<boundary>] = '' is treated as a comment and stripped away.

10 / CLI

A small, complete toolbelt.

Running knitcss without options compiles once using knitcss.ini from the current working directory.

knitcssCompile once.
knitcss --watchWatch and recompile. Default check interval: one second.
knitcss --watch 2Watch with a two-second check interval.
knitcss --select index.html pages/about.htmlProcess only selected paths relative to in_directory.
knitcss --config config/dev.iniUse another configuration file.
knitcss --config config/dev.ini --watchCombine a custom config with normal compile options.
knitcss --initCreate a default knitcss.ini with the standard breakpoint directive.
knitcss --resetClear the configured output directory.
knitcss --reset --config config/dev.iniReset using another config.
knitcss --log path countShow additional compilation information.
knitcss --watch --log time pathCombine logging with watch mode.
knitcss --versionPrint the installed version.
knitcss --helpPrint command help.

Logging fields

path, time, count, filesystem and task can be requested with --log.

--init, --reset, --version and --help are separate commands; only one of those command flags is used at a time.

That is the surface.

Now keep the CSS close.

Install →