node package manager
Share your code. npm Orgs help your team discover, share, and reuse code. Create a free org »



Expressive syntax for Virtual DOM and CSS.

How to use

DOM markup:

import dom from 'vd';
let div = dom('div.main',
  dom('p', 'This is a paragraph'),
  dom('<img src="test.png">'),
    'Expressive but without ',
    dom('b', 'bloat')

CSS declarations:

let css =;
css.add('div > p', {
  'font-weight': 'bold',
  'text-decoration': 'underline'


  • Tiny size (3kb gzip+minified)

  • Expresiveness and versatility

    • Jade style dom('div.main.left')

    • jQuery style dom('<a href="#">')

    • Attribute objects dom('div', { title: 'Help' })

    • Inline text nodes dom('div', 'Some text')

    • Array children dom('div', [dom('div'), dom('div')])

    • ...children dom('div', dom('div'), dom('div'))

  • First-class CSS syntax support

  • Node.JS compliance for server rendering


The main module exports the following:

  • vd (default)
  • style
  • Node
  • Text
  • Element

vd(str[, props[, … children]])

The default function that's imported when you run require('vd') allows you to seamlessly create Element objects.

The signature is versatile. The first parameter is always the tag definition.

The following styles are supported:

  • div
  • div.class
  • div.multiple.classes
  • div title=hello
  • div title=hello accesskey=k
  • div title="hello there"
  • <div title="hello there">

Optionally, you can specify an attributes key pair as the second parameter.

dom('img', { src: 'image.jpg' })

Two attributes behave especially when using vd() to create an element:

  • class: if defining classes in the first parameter, it appends instead of replacing

    // <div class="a b"> 
    dom('div.a', { class: 'b' });
  • classes: accepts an object with classes and keys that only get added if the value is truthy:

    // <div class="a b"> 
    dom('div.a', { classes: { b: true, c: false }});

The rest of the parameters can be 0 or more children elements or text nodes.

Strings and numbers turn into Text nodes.

Arrays can be used to specify children. If arrays within arrays are found, they're flattened. If null is found, it's ignored. That results in extra expressiveness:

dom('div', [
  loggedIn ? dom('<a href="#">', 'Log out') : null, => dom('span', name))

See below for the Element API.


Initializes a new Style element, which inherits from Element but adds convenience methods for defining the style content of the element.

The CSS API is provided by x-css.

Element(String tag[, isVoid])

Initializes a new Element with the tag tag.

If isVoid is provided, it's a Boolean representing whether the element is "self-closing" (like img). Otherwise it will be automatically determined based on a list of known void tags.

Extends Node.

Element.add(Node child[,… Node child2[, …]])

Adds one or more Node objects as children. Commonly Text nodes or other Element objects.

Any parameter can also be an Array of Node objects.

Returns itself for chaining.

Element.set(Object props)

Returns itself for chaining.

Element.set(String prop, String value)

Sets the property prop to value.

  • If the property is text, it appends a new Text node as a child.
  • If the property is style and is an Object, it gets serialized as CSS and stored.

Returns itself for chaining.

Element.remove(Node child)

Removes the child node referenced by child.

Returns itself for chaining.


Returns a String HTML5 serialization of the Element and its children.

A String representing the tag name.


Returns an Object of attributes associated with this element.


a Boolean representing if the element is void (self-closing).


An Array of nodes.

Text(String value)

Initiales a new text node with the given value.

Extends Node.


Returns the text value of the node.


Initializes a new style element that exposes the expressive x-css Sheet API.

Extends Element.

Style.add(String sel, Object props)

let css =;
css.add('div', {
  border: '3px solid red'

Creates and appends a Ruleset for the selector sel and declarations decs.

Returns the Style element for chaining.

Style.anim(Object frames)

let fade = css.anim({
  from: { opacity: 0 },
  to: { opacity: 1 }
css.add('div', {
  animation: `${fade} 1s ease-in`

Creates a new Animation scope with the given frames, and appends it.

Returns a random animation name as a String. params)

let iphone ='(min-device-width: 768px)');
iphone.add('.menu', {
  display: 'none'

Creates a new Media scope with the given frames, and appends it to the current scope.

Returns the created scope.


Basic interface implemented by Text and Element