diff --git a/happstack-yui.cabal b/happstack-yui.cabal
--- a/happstack-yui.cabal
+++ b/happstack-yui.cabal
@@ -1,5 +1,5 @@
 Name          : happstack-yui
-Version       : 7351.1.0
+Version       : 7351.2.0
 Category      : Web, Happstack
 Synopsis      : Utilities for using YUI3 with Happstack.
 Homepage      : https://github.com/dag/happstack-yui
@@ -10,12 +10,12 @@
 Build-Type    : Simple
 
 Description :
-  Bundles YUI 3.5.1 and includes a \"combo handler\" for use in Happstack
-  which concatenates YUI modules server-side to send in a single HTTP
-  request.  The YUI bundle is embedded in the library with Template Haskell
-  which means the files are served directly from memory, and also that you
-  can compile and deploy a single executable without having to worry about
-  deploying the YUI files as well.
+  Bundles YUI 3.5.1 and includes a \"combo handler\" for use in
+  Happstack which concatenates YUI modules server-side to send in a single
+  HTTP request.  The YUI bundle is embedded in the library with Template
+  Haskell which means the files are served directly from memory, and also
+  that you can compile and deploy a single executable without having to
+  worry about deploying the YUI files as well.
   .
   The benefits of using this over the Yahoo! CDN is that you can work
   offline and that you can host YUI yourself without sacrificing the
@@ -2837,6 +2837,7 @@
   HS-Source-Dirs   : src
   Default-Language : Haskell2010
   GHC-Options      : -Wall
+  CPP-Options      : -DYUI_VERSION=3.5.1 -DYUI_VERSION_STR="3.5.1"
   Exposed-Modules  :
     Happstack.Server.YUI
   Other-Modules    :
diff --git a/src/Happstack/Server/YUI.hs b/src/Happstack/Server/YUI.hs
--- a/src/Happstack/Server/YUI.hs
+++ b/src/Happstack/Server/YUI.hs
@@ -12,10 +12,10 @@
 import qualified Data.Text       as T
 
 import Control.Category             (Category((.)))
-import Control.Monad                (void, mzero)
+import Control.Monad                (liftM, void, mzero)
 import Data.List                    (intercalate)
 import Data.Text.Encoding           (encodeUtf8)
-import Happstack.Server             (ServerPartT, Response, neverExpires, setHeaderM, ok, toResponse, guessContentTypeM, mimeTypes, lookPairs)
+import Happstack.Server             (ServerPartT, Response, neverExpires, setHeaderM, badRequest, ok, toResponse, guessContentTypeM, mimeTypes, lookPairs)
 import Happstack.Server.Compression (compressedResponseFilter)
 import Happstack.Server.JMacro      ()
 import Happstack.Server.YUI.Bundle  (bundle)
@@ -34,14 +34,16 @@
     = ComboHandlerURL
     | BundleURL [String]
     | ConfigURL
+    | CSSComboURL
     | SeedURL
 
 derivePrinterParsers ''Sitemap
 
 sitemap :: Router Sitemap
 sitemap =
-    "3.5.1" </>                                                                 -- TODO: pass in YUI version via CPP from makefile?
+    YUI_VERSION_STR </>
        ( rComboHandlerURL . "combo"
+      <> rCSSComboURL . "css"
       <> rBundleURL . "bundle" </> rList (anyString . eos)
       <> rConfigURL . "config"
       <> rSeedURL
@@ -54,17 +56,24 @@
 --
 -- The handler responds to these routes:
 --
--- [@\/3.5.1\/@]
+-- [@\/YUI_VERSION\/@]
 --   The YUI seed file plus the configuration for using our own
 --   combo loader.
 --
--- [@\/3.5.1\/combo@]
+-- [@\/YUI_VERSION\/combo@]
 --   The combo loader.
 --
--- [@\/3.5.1\/bundle\/\<filename\>@]
+-- [@\/YUI_VERSION\/css@]
+--   A specialized combo loader for CSS modules, for use in @\<link\/\>@
+--   tags.  Simply list the CSS modules in the query string by name rather
+--   than file path, for example
+--   @\"\/YUI_VERSION\/css?reset&base&fonts&grids\"@.  Order matters;
+--   you'll usually want reset first if you use it.
+--
+-- [@\/YUI_VERSION\/bundle\/\<filename\>@]
 --   Get an individual file without combo loading.
 --
--- [@\/3.5.1\/config@]
+-- [@\/YUI_VERSION\/config@]
 --   The code for configuring YUI to use our own combo loader.  Not needed
 --   if you use the seed file mentioned above.
 --
@@ -87,7 +96,6 @@
 route url = do
     neverExpires
     void compressedResponseFilter
-    setHeaderM "Content-Type" "application/javascript"                          -- TODO: guess content type from first file for combohandler
     case url of
       BundleURL paths ->
         do let filepath = intercalate "/" paths
@@ -95,18 +103,27 @@
            setHeaderM "Content-Type" mime
            maybe mzero (ok . toResponse) $ Map.lookup filepath bundle
       ComboHandlerURL ->
-        do qs <- lookPairs
-           let combo = [ bundle Map.! q | (q,_) <- qs, Map.member q bundle ]    -- TODO: use Map.lookup instead of Map.member + Map.!
-           if null combo                                                        -- TODO: maybe mzero also if a requested file isn't found
-             then mzero                                                         --       (actually research how other combohandlers do error handling)
-             else ok $ toResponse $ B.concat combo
+        do qs <- liftM (map fst) lookPairs
+           if null qs || any (`Map.notMember` bundle) qs
+             then badRequest $ toResponse ()
+             else do mime <- guessContentTypeM mimeTypes $ head qs
+                     setHeaderM "Content-Type" mime
+                     ok $ toResponse $ B.concat $ map (bundle Map.!) qs
+      CSSComboURL ->
+        do qs <- liftM (map (css . fst)) lookPairs
+           if null qs || any (`Map.notMember` bundle) qs
+             then badRequest $ toResponse ()
+             else do setHeaderM "Content-Type" "text/css"
+                     ok $ toResponse $ B.concat $ map (bundle Map.!) qs
       ConfigURL ->
         do config <- mkConfig
            ok $ toResponse config
       SeedURL ->
         do config <- mkConfig
+           setHeaderM "Content-Type" "application/javascript"
            ok $ toResponse $ seed `B.append` (encode . render) config
   where
     seed   = bundle Map.! "yui/yui-min.js"
     render = renderStyle (style { mode = OneLineMode }) . renderJs
     encode = encodeUtf8 . T.pack
+    css fn = "css" ++ fn ++ "/css" ++ fn ++ "-min.css"
