diff --git a/index.js b/index.js
index 11d6767..5fd948a 100644
--- a/index.js
+++ b/index.js
@@ -75,7 +75,9 @@ module.exports = function (h, opts) {
             else cur[1][key] = concat(cur[1][key], parts[i][1])
           } else if (parts[i][0] === VAR
           && (parts[i][1] === ATTR_VALUE || parts[i][1] === ATTR_KEY)) {
-            if (!cur[1][key]) cur[1][key] = strfn(parts[i][2])
+            if (!cur[1][key])
+              if (parts[i][1] === ATTR_KEY) cur[1][key] = strfn(parts[i][2])
+              else cur[1][key] = parts[i][2]
             else cur[1][key] = concat(cur[1][key], parts[i][2])
           } else {
             if (key.length && !cur[1][key] && i === j
diff --git a/test/attr.js b/test/attr.js
index 2d55b12..bd2d1aa 100644
--- a/test/attr.js
+++ b/test/attr.js
@@ -1,5 +1,6 @@
 var test = require('tape')
 var vdom = require('virtual-dom')
+var hyperscript = require('hyperscript')
 var hyperx = require('../')
 var hx = hyperx(vdom.h)
 
@@ -9,6 +10,33 @@ test('class', function (t) {
   t.end()
 })
 
+test('undefined attribute value', function (t) {
+  var tree = hx`<div data-meh=${undefined}></div>`
+  t.equal(vdom.create(tree).toString(), '<div></div>')
+  t.end()
+})
+
+test('empty string attribute value', function (t) {
+  var tree = hx`<div data-meh=${''}></div>`
+  t.equal(vdom.create(tree).toString(), '<div data-meh=""></div>')
+  t.end()
+})
+
+// running this test with hyperscript because it
+// breaks with virtual-dom (with "str.replace is not a function")
+test('false attribute value', function (t) {
+  var hx = hyperx(hyperscript)
+  var tree = hx`<div data-meh=${false}></div>`
+  t.equal(tree.outerHTML, '<div data-meh=""></div>')
+  t.end()
+})
+
+test('null attribute value', function (t) {
+  var tree = hx`<div data-meh=${null}></div>`
+  t.equal(vdom.create(tree).toString(), '<div></div>')
+  t.end()
+})
+
 test('boolean attribute', function (t) {
   var tree = hx`<video autoplay></video>`
   t.equal(vdom.create(tree).toString(), '<video autoplay="autoplay"></video>')