diff --git a/benchmarks/Main.hs b/benchmarks/Main.hs
--- a/benchmarks/Main.hs
+++ b/benchmarks/Main.hs
@@ -2,6 +2,8 @@
 -- renderers available.
 --
 
+import qualified Blaze.ByteString.Builder as Blaze
+import qualified Blaze.ByteString.Builder.Char.Utf8 as Blaze
 import           Criterion.Main
 import qualified Data.ByteString.Lazy as LB
 import qualified Data.Text.Lazy as LT
diff --git a/lucid.cabal b/lucid.cabal
--- a/lucid.cabal
+++ b/lucid.cabal
@@ -1,5 +1,5 @@
 name:                lucid
-version:             2.7.0
+version:             2.8.0
 synopsis:            Clear to write, read and edit DSL for HTML
 description:         Clear to write, read and edit DSL for HTML. See the 'Lucid' module
                      for description and documentation.
@@ -22,7 +22,8 @@
                      Lucid.Html5
                      Lucid.Bootstrap
   build-depends:     base >= 4 && <5
-                   , bytestring >= 0.10.4
+                   , blaze-builder
+                   , bytestring
                    , containers
                    , mtl
                    , text
@@ -50,6 +51,7 @@
   build-depends:    base,
                     deepseq,
                     criterion,
+                    blaze-builder,
                     text,
                     bytestring,
                     lucid
diff --git a/src/Lucid/Base.hs b/src/Lucid/Base.hs
--- a/src/Lucid/Base.hs
+++ b/src/Lucid/Base.hs
@@ -1,11 +1,11 @@
-{-# LANGUAGE ExtendedDefaultRules   #-}
-{-# LANGUAGE FlexibleInstances      #-}
 {-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE GADTs                  #-}
-{-# LANGUAGE KindSignatures         #-}
-{-# LANGUAGE MultiParamTypeClasses  #-}
-{-# LANGUAGE OverloadedStrings      #-}
-{-# LANGUAGE TypeFamilies           #-}
+{-# LANGUAGE ExtendedDefaultRules #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE KindSignatures #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FlexibleInstances #-}
 
 -- | Base types and combinators.
 
@@ -28,7 +28,7 @@
    -- * Types
   ,Html
   ,HtmlT
-  ,Attribute(..)
+  ,Attribute
    -- * Classes
   ,Term(..)
   ,TermRaw(..)
@@ -36,25 +36,23 @@
   ,With(..))
   where
 
+import           Blaze.ByteString.Builder (Builder)
+import qualified Blaze.ByteString.Builder as Blaze
+import qualified Blaze.ByteString.Builder.Html.Utf8 as Blaze
 import           Control.Applicative
 import           Control.Monad
 import           Control.Monad.Reader
-import           Data.ByteString.Builder
-import           Data.ByteString.Builder.Prim as BP
-import           Data.ByteString.Lazy         (ByteString)
-import qualified Data.ByteString.Lazy         as L
-import           Data.Char                    (ord)
+import           Data.ByteString.Lazy (ByteString)
+import qualified Data.ByteString.Lazy as L
 import           Data.Functor.Identity
-import           Data.HashMap.Strict          (HashMap)
-import qualified Data.HashMap.Strict          as M
+import           Data.HashMap.Strict (HashMap)
+import qualified Data.HashMap.Strict as M
 import           Data.Monoid
 import           Data.String
-import           Data.Text                    (Text)
-import qualified Data.Text                    as T
-import qualified Data.Text.Encoding           as T
-import qualified Data.Text.Lazy               as LT
-import qualified Data.Text.Lazy.Encoding      as LT
-import           Data.Word                    (Word8)
+import           Data.Text (Text)
+import qualified Data.Text as T
+import qualified Data.Text.Lazy as LT
+import qualified Data.Text.Lazy.Encoding as LT
 
 --------------------------------------------------------------------------------
 -- Types
@@ -139,15 +137,15 @@
 
 instance ToHtml String where
   toHtml = fromString
-  toHtmlRaw m = HtmlT (return ((\_ _ -> fromString m),()))
+  toHtmlRaw m = HtmlT (return ((\_ _ -> Blaze.fromString m),()))
 
 instance ToHtml Text where
   toHtml m = HtmlT (return ((\_ _ -> encode m),()))
-  toHtmlRaw m = HtmlT (return ((\_ _ -> T.encodeUtf8Builder m),()))
+  toHtmlRaw m = HtmlT (return ((\_ _ -> Blaze.fromText m),()))
 
 instance ToHtml LT.Text where
   toHtml m = HtmlT (return ((\_ _ -> encodeLazy m),()))
-  toHtmlRaw m = HtmlT (return ((\_ _ -> LT.encodeUtf8Builder m),()))
+  toHtmlRaw m = HtmlT (return ((\_ _ -> Blaze.fromLazyText m),()))
 
 -- | Used to construct HTML terms.
 --
@@ -263,48 +261,48 @@
 -- | Render the HTML to a lazy 'ByteString'.
 --
 -- This is a convenience function defined in terms of 'execHtmlT',
--- 'runIdentity' and 'toLazyByteString'. Check the source if
+-- 'runIdentity' and 'Blaze.toLazyByteString'. Check the source if
 -- you're interested in the lower-level behaviour.
 --
 renderToFile :: FilePath -> Html a -> IO ()
-renderToFile fp = L.writeFile fp . toLazyByteString . runIdentity . execHtmlT
+renderToFile fp = L.writeFile fp . Blaze.toLazyByteString . runIdentity . execHtmlT
 
 -- | Render the HTML to a lazy 'ByteString'.
 --
 -- This is a convenience function defined in terms of 'execHtmlT',
--- 'runIdentity' and 'toLazyByteString'. Check the source if
+-- 'runIdentity' and 'Blaze.toLazyByteString'. Check the source if
 -- you're interested in the lower-level behaviour.
 --
 renderBS :: Html a -> ByteString
-renderBS = toLazyByteString . runIdentity . execHtmlT
+renderBS = Blaze.toLazyByteString . runIdentity . execHtmlT
 
 -- | Render the HTML to a lazy 'Text'.
 --
 -- This is a convenience function defined in terms of 'execHtmlT',
--- 'runIdentity' and 'toLazyByteString', and
+-- 'runIdentity' and 'Blaze.toLazyByteString', and
 -- 'LT.decodeUtf8'. Check the source if you're interested in the
 -- lower-level behaviour.
 --
 renderText :: Html a -> LT.Text
-renderText = LT.decodeUtf8 . toLazyByteString . runIdentity . execHtmlT
+renderText = LT.decodeUtf8 . Blaze.toLazyByteString . runIdentity . execHtmlT
 
 -- | Render the HTML to a lazy 'ByteString', but in a monad.
 --
 -- This is a convenience function defined in terms of 'execHtmlT' and
--- 'toLazyByteString'. Check the source if you're interested in
+-- 'Blaze.toLazyByteString'. Check the source if you're interested in
 -- the lower-level behaviour.
 --
 renderBST :: Monad m => HtmlT m a -> m ByteString
-renderBST = liftM toLazyByteString . execHtmlT
+renderBST = liftM Blaze.toLazyByteString . execHtmlT
 
 -- | Render the HTML to a lazy 'Text', but in a monad.
 --
 -- This is a convenience function defined in terms of 'execHtmlT' and
--- 'toLazyByteString', and 'LT.decodeUtf8'. Check the source if
+-- 'Blaze.toLazyByteString', and 'LT.decodeUtf8'. Check the source if
 -- you're interested in the lower-level behaviour.
 --
 renderTextT :: Monad m => HtmlT m a -> m LT.Text
-renderTextT = liftM (LT.decodeUtf8 . toLazyByteString) . execHtmlT
+renderTextT = liftM (LT.decodeUtf8 . Blaze.toLazyByteString) . execHtmlT
 
 --------------------------------------------------------------------------------
 -- Running, transformer versions
@@ -355,10 +353,10 @@
 makeElement name =
   \m' ->
     HtmlT (do ~(f,a) <- runHtmlT m'
-              return (\attr m -> s "<" <> T.encodeUtf8Builder name
+              return (\attr m -> s "<" <> Blaze.fromText name
                               <> foldlMapWithKey buildAttr attr <> s ">"
                               <> m <> f mempty mempty
-                              <> s "</" <> T.encodeUtf8Builder name <> s ">",
+                              <> s "</" <> Blaze.fromText name <> s ">",
                       a))
 
 -- | Make an HTML builder for elements which have no ending tag.
@@ -366,7 +364,7 @@
                  => Text       -- ^ Name.
                  -> HtmlT m () -- ^ A parent element.
 makeElementNoEnd name =
-  HtmlT (return (\attr _ -> s "<" <> T.encodeUtf8Builder name
+  HtmlT (return (\attr _ -> s "<" <> Blaze.fromText name
                             <> foldlMapWithKey buildAttr attr <> s ">",
                  ()))
 
@@ -375,7 +373,7 @@
                     => Text       -- ^ Name.
                     -> HtmlT m () -- ^ A parent element.
 makeXmlElementNoEnd name =
-  HtmlT (return (\attr _ -> s "<" <> T.encodeUtf8Builder name
+  HtmlT (return (\attr _ -> s "<" <> Blaze.fromText name
                             <> foldlMapWithKey buildAttr attr <> s "/>",
                  ()))
 
@@ -383,7 +381,7 @@
 buildAttr :: Text -> Text -> Builder
 buildAttr key val =
   s " " <>
-  T.encodeUtf8Builder key <>
+  Blaze.fromText key <>
   if val == mempty
      then mempty
      else s "=\"" <> encode val <> s "\""
@@ -394,7 +392,7 @@
 
 -- | Convenience function for constructing builders.
 s :: String -> Builder
-s = fromString
+s = Blaze.fromString
 {-# INLINE s #-}
 
 --------------------------------------------------------------------------------
@@ -402,28 +400,8 @@
 
 -- | Encode the given strict plain text to an encoded HTML builder.
 encode :: Text -> Builder
-encode = T.encodeUtf8BuilderEscaped charUtf8HtmlEscaped
+encode = Blaze.fromHtmlEscapedText
 
 -- | Encode the given strict plain text to an encoded HTML builder.
 encodeLazy :: LT.Text -> Builder
-encodeLazy = LT.encodeUtf8BuilderEscaped charUtf8HtmlEscaped
-
-{-# INLINE charUtf8HtmlEscaped #-}
-charUtf8HtmlEscaped :: BP.BoundedPrim Word8
-charUtf8HtmlEscaped =
-    condB (== c2w '<' ) (fixed4 ('&',('l',('t',';')))) $        -- &lt;
-    condB (== c2w '>' ) (fixed4 ('&',('g',('t',';')))) $        -- &gt;
-    condB (== c2w '&' ) (fixed5 ('&',('a',('m',('p',';'))))) $  -- &amp;
-    condB (== c2w '"' ) (fixed5 ('&',('#',('3',('4',';'))))) $  -- &#34;
-    condB (== c2w '\'') (fixed5 ('&',('#',('3',('9',';'))))) $  -- &#39;
-    (liftFixedToBounded BP.word8)  -- fallback for Chars smaller than '>'
-  where
-    {-# INLINE fixed4 #-}
-    fixed4 x = liftFixedToBounded $ const x >$<
-      BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7
-
-    {-# INLINE fixed5 #-}
-    fixed5 x = liftFixedToBounded $ const x >$<
-      BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7
-
-    c2w = fromIntegral . ord
+encodeLazy = Blaze.fromHtmlEscapedLazyText
