An excerpt from the repository, fetched Nov 13, 2026.
Read the project’s introduction
Enlive
Enlive is a selector-based (à la CSS) templating library for Clojure.
David Nolen wrote a nice tutorial.
Another tutorial is by Brian Marick.
There's a quickstart section in Clojure Cookbook.
Where do I get support?
On the Enlive Google Group
Artifact
All artifacts are published to clojars. Latest version is 1.1.6:
[enlive "1.1.6"]
What's new in Enlive?
(most recent first)
1.1.6:
ADD: exception message when html-resource not found.
FIX: auto-reload on windows (also works with chestnut).
Auto-reloading (1.1.2)
(net.cgrand.reload/auto-reload *ns*)
Each time a resource or file used by a template/snippet is updated the
namespace is reloaded (as per (require ... :reload)).
Misc
Perf improvements
Fixes to ${vars} substitutions
Pluggable parsers! (1.1.1)
The *parser* dynamic var controls the parser to be used by html-resource at
runtime. (or you can pass {:parser XXX} as an additional arg).
For templates and snippets whose sources are not read dynamically, you
can opt for another parser either locally:
(deftemplate ugh {:parser xml-parser}
(java.io.StringReader. "<a><div>hello</div></a>")
[])
or globally for the declaring ns:
(set-ns-parser! xml-parser)
A parser is a function from InputStream to nodes. xml-parser,
net.cgrand.tagsoup/parser and net.cgrand.jsoup/parser are the three
builtin ones.
${vars} substitutions (1.1.1)
The following selector + function is going to replace any ${var} in
text and attributes by the value found in the map (or any function).
[:#container any-node] (replace-vars {:name "world" :class "hello"})
hiccup-style helper (1.1.0)
(content (html [:h3#hello "Hello worls"]))
older stuff
By default selector-transformation pairs are run sequentially. When you know
that several transformations are independent, you can now specify (as an
optimization) to process them in lockstep. Note that this doesn't work with
fragments selectors.
Example:
[:a :selector] a-transformation
[:another :selector] another-transformation
[:a :dependent :selector] yet-another-transformation
If the first two transformations are independent you can rewrite this code as:
:lockstep
{[:a :selector] a-transformation
[:another :selector] another-transformation}
[:a :dependent :selector] yet-another-transformation
Transformations are now slightly restricted in their return values: a node or
a collection of nodes (instead of freely nested collections of nodes).
Dynamic selectors: selectors aren't compiled anymore. It means that you don't
need to wrap them in (selector ...) forms anymore nor to eval them in the most
dynamic cases.
Fragment selectors allow to select adjacent nodes. They are denoted by a map of
two node selectors (eg {[:h1] [:p]}), bounds are inclusive and they select
the smallest matching fragments.
Transformations (the right-hand parts of rules) are now plain old closures.
These functions take one arg (the selected node) and return nil, another node
or a collection of nodes.
Rules are applied top-down: the first rule transforms the whole tree and the
resulting tree is passed to the next rules.
Nodes are transformed deep-first, that is: if a selector selects several nodes,
descendants are transformed first. Hence, when the transformation is applied to
an ancestor, you can "see" the transformed descendants (but you can not see
your transformed siblings).
/B /(T B)
A if A and B are selected and transformed by T the the resulting tree is (T A )
\C \C
Concepts
snippet is a unit of your page. It may be logical or visual entry,
such as header, footer, page element. Snippet is usually a part of a
template, and may serve as a container for other snippets. For
example, for navigation on the web page. For that, let’s first define an
html template for the navigation. Snippets are created by using
net.cgrand.enlive-html/defsnippet function and, same as templates,
they require a corresponding HTML template file to be availble in a
classpath.
So, snippet function returns a seq of nodes, it can be used as a
building block for more complex templates.
templates combine snippets together, they serve like a basement for
the snippets. In order to create a template, you can use
net.cgrand.enlive-html/deftemplate function. deftemplate is used as
something what you would call layout in some other templating
systems. In essence, it’s either a self-contained page (rarely true in
bigger applications), or a container for snippets.
That said, a template is a returns a seq of string -- basically it's a
snippet whose output is serialized. Templates return a seq of strings to avoid
building the whole string.
Templates and snippets transform a source (specified as a path (to access
resources on the classpath), a File, a Reader, an InputStream, a URI, a URL,
an element or a seq of nodes).
Next concept is selectors, which are used within snippets and
templates to identify the block of HTML code the transformation would be
applied to. They’re very similar to CSS selectors, but also allow more
sophisticated, predicate-based selections, for example, you can select a
tag based on some part of content, or an attribute. Transformations are
functions that triggered on the elements found by selectors. They
receive content obtained selector, and modify it in some way.
Quickstart tutorial
Template
If you want to go see the compiled version of the following steps all in
one place, you can check out
an example Ring application.
First thing you need to start, is to define your first template:
(require '[net.cgrand.enlive-html :as html])
(html/deftemplate main-template "templates/application.html"
[])
Now, you can start writing selectors and transformations for the given
selectors. Let's add a title to the template. Given that your template
already has <head> and <title> tags, let's insert a title.
Content of templates/application.html:
<!DO
Read the full README on GitHub