diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 2.9.12
+
+* Add MonadFix instance
+
 ## 2.9.11
 
 * Add GHC-8.6 support
diff --git a/lucid.cabal b/lucid.cabal
--- a/lucid.cabal
+++ b/lucid.cabal
@@ -1,5 +1,5 @@
 name:                lucid
-version:             2.9.11
+version:             2.9.12
 synopsis:            Clear to write, read and edit DSL for HTML
 description:
   Clear to write, read and edit DSL for HTML.
@@ -21,7 +21,7 @@
 build-type:          Simple
 cabal-version:       >=1.8
 extra-source-files:  README.md, CHANGELOG.md
-tested-with:         GHC==7.10.3,GHC==8.0.2,GHC==8.2.2,GHC==8.4.4,GHC==8.6.1
+tested-with:         GHC==7.10.3,GHC==8.0.2,GHC==8.2.2,GHC==8.4.4,GHC==8.6.5, GHC==8.8.1
 
 library
   hs-source-dirs:    src/
@@ -32,7 +32,7 @@
                      Lucid.Bootstrap
 
   -- GHC boot libraries
-  build-depends:     base                   >=4.8      && <4.13
+  build-depends:     base                   >=4.8      && <4.14
                    , bytestring             >=0.10.6.0
                    , containers             >=0.5.6.2
                    , transformers           >=0.4.2.0
diff --git a/src/Lucid/Base.hs b/src/Lucid/Base.hs
--- a/src/Lucid/Base.hs
+++ b/src/Lucid/Base.hs
@@ -161,6 +161,9 @@
     HtmlT (do a <- m
               return (\_ -> mempty,a))
 
+instance MonadFix m => MonadFix (HtmlT m) where
+  mfix m = HtmlT $ mfix $ \ ~(_, a) -> runHtmlT $ m a
+
 -- MonadReader, MonadState etc instances need UndecidableInstances,
 -- because they do not satisfy the coverage condition.
 
@@ -338,7 +341,7 @@
 -- | For the contentless elements: 'Lucid.Html5.br_'
 instance (Functor m) => With (HtmlT m a) where
   with f = \attr -> HtmlT (mk attr <$> runHtmlT f)
-    where 
+    where
       mk attr ~(f',a) = (\attr' -> f' (unionArgs (M.fromListWith (<>) (map toPair attr)) attr')
                         ,a)
       toPair (Attribute x y) = (x,y)
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -1,5 +1,6 @@
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecursiveDo #-}
 {-# LANGUAGE ExtendedDefaultRules #-}
 
 -- | Test suite for Lucid.
@@ -13,6 +14,8 @@
 import Control.Applicative
 import Control.Monad.State.Strict
 
+import qualified Data.Text as T
+
 import Example1
 
 import Test.HUnit
@@ -33,6 +36,7 @@
   describe "special-elements" testSpecials
   describe "self-closing" testSelfClosing
   describe "commuteHtmlT" testCommuteHtmlT
+  describe "monadFix" testMonadFix
 
 -- | Test text/unicode.
 testText :: Spec
@@ -219,3 +223,27 @@
       li_ "3"
       li_ "4"
       li_ "5"
+
+testMonadFix :: Spec
+testMonadFix =
+  do it "mdo" (renderText example == renderText expected)
+  where
+   toSectionId i = T.pack $ "section_" ++ show i
+
+   toSectionTitle i = T.pack $ "Section " ++ show i
+
+   example = mdo
+     forM_ sections $ \(sectionName, sectionId) ->
+       a_ [href_ sectionId] $ toHtml sectionName
+     sections <- forM [1 .. 2] $ \sectionNum -> do
+       let sectionId = toSectionId sectionNum
+           sectionTitle = toSectionTitle sectionNum
+       h1_ [id_ sectionId] $ toHtml sectionTitle
+       return (sectionTitle, sectionId)
+     return ()
+
+   expected = do
+     forM_ [1 .. 2] $ \sectionNum ->
+       a_ [href_ $ toSectionId sectionNum] $ toHtml $ toSectionTitle sectionNum
+     forM_ [1 .. 2] $ \sectionNum ->
+       h1_ [id_ $ toSectionId sectionNum] $ toHtml $ toSectionTitle sectionNum
