diff --git a/HSP/Formlets.hs b/HSP/Formlets.hs
--- a/HSP/Formlets.hs
+++ b/HSP/Formlets.hs
@@ -21,7 +21,7 @@
 import Control.Arrow (first)
 import Control.Applicative (Applicative(pure),(<$>))
 import Control.Applicative.Error (Failing(Success), maybeRead')
-import Data.Maybe (catMaybes)
+import Data.Maybe (catMaybes, isNothing)
 import Data.Monoid (Monoid)
 import Data.Traversable (sequenceA)
 import HSP
@@ -60,39 +60,39 @@
 password :: (Monad v, HSX.XMLGenerator x) => Maybe String -> Form [XMLGenT x (HSX.XML x)] v String
 password = input' (\n v -> [<input type="password" name=n value=v />])
 
-checkboxes :: (XMLGenerator x, Monad v, Applicative v, Read a, Show a) => [(a, String)] -> Form [XMLGenT x (HSX.XML x)] v [a]
-checkboxes items = checkboxes' (map (first show) items) `check` (\strs -> sequenceA $ map (flip maybeRead' "Could not parse checkbox data") strs)
+checkboxes :: (XMLGenerator x, Monad v, Applicative v, Read a, Show a) => [(a, String)] -> [a] -> Form [XMLGenT x (HSX.XML x)] v [a]
+checkboxes items checked = 
+    (checkboxes' (map (first show) items) (map show checked))
+    `check` 
+    (\strs -> sequenceA $ map (flip maybeRead' "Could not parse checkbox data") strs)
 
-{-
-Normally checkboxes all have the same 'name' element, and you get an
-array of results back. But we don't want to parse the array, so we use
-a trick and just give each checkbox a unique name.
--}
-checkboxes' :: (XMLGenerator x, Monad v, Applicative v) => [(String, String)] -> Form [XMLGenT x (HSX.XML x)] v [String]
-checkboxes' items =
-    plug (\listItems -> [<ul class="checkboxes"><% listItems %></ul>]) (catMaybes <$> (sequenceA $ map mkCheckbox items))
-    where 
-      mkCheckbox (val, labelText) =
-          generalInput (\n mv ->
-                      if mv == (Just val)
-                      then [<li><input type="checkbox" name=n value=val checked="checked"/><% labelText %></li>]
-                      else [<li><input type="checkbox" name=n value=val />                 <% labelText %></li>])
+checkboxes' :: (XMLGenerator x, Monad v, Applicative v) => [(String, String)] -> [String] -> Form [XMLGenT x (HSX.XML x)] v [String]
+checkboxes' items checked =
+    generalInputMulti $ \name selectedValues ->
+        [<ul class="checkboxes">
+          <% mapM (mkOption name selectedValues) items %>
+        </ul>]
+    where
+      mkOption n selectedValues (value, label)
+          | value `elem` (if not (null selectedValues) then selectedValues else checked) =
+              [<li><span><input type="checkbox" name=n value=value checked="checked"/><% label %></span></li>]
+          | otherwise =
+              [<li><span><input type="checkbox" name=n value=value /><%                  label %></span></li>]
 
--- todo: make the label be any valid markup, not just a string
-radio :: (XMLGenerator x, Monad v, Applicative v, Read a, Show a) => [(a, String)] -> Form [XMLGenT x (HSX.XML x)] v (Maybe a)
-radio items = radio'' (map (first show) items) `check` checkItem
+radio :: (XMLGenerator x, Monad v, Applicative v, Read a, Show a) => [(a, String)] -> Maybe a -> Form [XMLGenT x (HSX.XML x)] v (Maybe a)
+radio items checked = radio'' (map (first show) items) (fmap show checked) `check` checkItem
     where
       checkItem Nothing = Success Nothing
       checkItem (Just str) = Just <$> maybeRead' str ("Could not parse radio data: " ++ str)
 
-radio'' :: (XMLGenerator x, Applicative v, Monad v) => [(String, String)] -> Form [XMLGenT x (HSX.XML x)] v (Maybe String)
-radio'' items = generalInput (\n mv -> [<ul class="radios"><% concatMap (radioItem n mv) items %></ul>])
+radio'' :: (XMLGenerator x, Applicative v, Monad v) => [(String, String)] -> Maybe String -> Form [XMLGenT x (HSX.XML x)] v (Maybe String)
+radio'' items checked = generalInput (\n mv -> [<ul class="radios"><% concatMap (radioItem n mv checked) items %></ul>])
 
-radioItem :: (XMLGenerator x) => String -> Maybe String -> (String, String) -> [XMLGenT x (HSX.XML x)]
-radioItem n mv (val, labelText) =
-    if mv == (Just val)
-       then [<li><p><input type="radio" name=n value=val checked="checked"/><% labelText %></p></li>]
-       else [<li><p><input type="radio" name=n value=val />                 <% labelText %></p></li>]
+radioItem :: (XMLGenerator x) => String -> Maybe String -> Maybe String -> (String, String) -> [XMLGenT x (HSX.XML x)]
+radioItem n mv mc (val, labelText) =
+    if ((isNothing mv && (mc == Just val)) || (mv == Just val))
+       then [<li><span><input type="radio" name=n value=val checked="checked"/><% labelText %></span></li>]
+       else [<li><span><input type="radio" name=n value=val />                 <% labelText %></span></li>]
 
 -- |drop down box
 select :: (XMLGenerator x, Monad v, Applicative v, Read a, Show a) => Maybe a -> [(a, String)] -> Form [XMLGenT x (HSX.XML x)] v (Maybe a)
diff --git a/formlets-hsp.cabal b/formlets-hsp.cabal
--- a/formlets-hsp.cabal
+++ b/formlets-hsp.cabal
@@ -1,5 +1,5 @@
 Name:            formlets-hsp
-Version:         2.2.3
+Version:         2.3.1
 Synopsis:        HSP support for Formlets
 Description:     A modular way to build forms based on applicative functors, as
                  described in:
