diff --git a/haphviz.cabal b/haphviz.cabal
--- a/haphviz.cabal
+++ b/haphviz.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                haphviz
-version:             0.1.2.0
+version:             0.1.2.1
 synopsis:            Graphviz code generation with Haskell
 description:
   There are multiple ways to describe this package:
diff --git a/src/Text/Dot/Gen.hs b/src/Text/Dot/Gen.hs
--- a/src/Text/Dot/Gen.hs
+++ b/src/Text/Dot/Gen.hs
@@ -14,8 +14,10 @@
     , RankdirType
     ) where
 
-import           Control.Monad.State     (StateT, execStateT, get, modify)
-import           Control.Monad.Writer    (WriterT, execWriterT, tell)
+import           Control.Monad.State     (StateT, execStateT, get, modify, put,
+                                          runStateT)
+import           Control.Monad.Writer    (WriterT, execWriterT, runWriterT,
+                                          tell)
 
 import           Text.Dot.Attributes
 import           Text.Dot.Types.Internal
@@ -58,8 +60,11 @@
 
 -- | Utility function to generate a graph with nameless nodes starting from a given starting number.
 genSubDot :: Int -> DotGen a -> Dot
-genSubDot n func = runIdentity $ execWriterT $ execStateT func n
+genSubDot n func = snd $ genSubDot' n func
 
+genSubDot' :: Int -> DotGen a -> ((a, State), Dot)
+genSubDot' n func = runIdentity $ runWriterT $ runStateT func n
+
 -- * Graph types
 
 -- | Directed graph
@@ -236,8 +241,9 @@
 subgraph :: Text -> DotGen () -> DotGen GraphName
 subgraph name content = do
     n <- get
-    let c = genSubDot n content
-    tell $ Subgraph name c
+    let (((), newn), dot) = genSubDot' n content
+    tell $ Subgraph name dot
+    put newn
     return name
 
 -- * Miscelaneous
@@ -289,6 +295,20 @@
      -> NodeId
 (UserId t) .: p = UserId $ t <> ":" <> p
 (Nameless i) .: p = UserId $ T.pack (show i) <> ":" <> p
+
+-- * Ranks
+
+-- | {rank=same ... } declaration
+--
+-- >>> ranksame $ node [shape =: none]
+-- > node [shape=none];
+ranksame :: DotGen a -> DotGen a
+ranksame content = do
+    n <- get
+    let ((a, state), dot) = genSubDot' n content
+    put state
+    tell $ Ranksame dot
+    return a
 
 -- * Internals
 -- | Generation monad
diff --git a/src/Text/Dot/Render.hs b/src/Text/Dot/Render.hs
--- a/src/Text/Dot/Render.hs
+++ b/src/Text/Dot/Render.hs
@@ -49,10 +49,14 @@
 renderDot :: Dot -> Render ()
 
 renderDot (Node nid ats) = do
+    indent
     renderId nid
     renderAttributes ats
+    finishCommand
+    newline
 
 renderDot (Edge from to ats) = do
+    indent
     renderId from
     tell " "
     t <- ask
@@ -62,57 +66,60 @@
     tell " "
     renderId to
     renderAttributes ats
+    finishCommand
+    newline
 
 renderDot (Declaration t ats) = do
+    indent
     renderDecType t
     renderAttributes ats
+    finishCommand
+    newline
 
 renderDot (Subgraph name content) = do
+    indent
     tell "subgraph"
     tell " "
     tell name
     tell " "
     tell "{"
-    tell "\n"
+    newline
     indented $ renderDot content
     indent
     tell "}"
+    newline
 
 renderDot (RawDot t) = tell t
 
 renderDot (Rankdir t) = do
+    indent
     tell "rankdir"
     tell " = "
     renderRankDirType t
+    finishCommand
+    newline
 
 renderDot (Label t) = do
+    indent
     tell "label"
     tell " = "
     tell $ quoted t
+    finishCommand
+    newline
 
+renderDot (Ranksame d) = do
+    indent
+    braced $ do
+        tell " rank=same"
+        newline
+        indented $ renderDot d
+        indent
+    newline
+
 renderDot (DotSeq d1 d2) = do
-    ind d1
     renderDot d1
-    nl d1
-    ind d2
     renderDot d2
-    nl d2
-  where
-    nl :: Dot -> Render ()
-    nl (DotSeq _ _) = return ()
-    nl DotEmpty = return ()
-    nl _ = do
-        tell ";"
-        tell "\n"
 
-    ind :: Dot -> Render ()
-    ind (DotSeq _ _) = return ()
-    ind DotEmpty = return ()
-    ind _ = do
-        level <- get
-        tell $ T.pack $ replicate (level * 2) ' '
-
-
 renderDot DotEmpty = return ()
 
 renderAttributes :: [Attribute] -> Render ()
@@ -149,6 +156,18 @@
 renderRankDirType BT = tell "BT"
 renderRankDirType RL = tell "RL"
 renderRankDirType LR = tell "LR"
+
+newline :: Render ()
+newline = tell "\n"
+
+finishCommand :: Render ()
+finishCommand = tell ";"
+
+braced :: Render () -> Render ()
+braced content = do
+    tell "{"
+    content
+    tell "}"
 
 indent :: Render ()
 indent = do
diff --git a/src/Text/Dot/Types/Internal.hs b/src/Text/Dot/Types/Internal.hs
--- a/src/Text/Dot/Types/Internal.hs
+++ b/src/Text/Dot/Types/Internal.hs
@@ -70,6 +70,7 @@
 data Dot = Node NodeId [Attribute]
          | Edge NodeId NodeId [Attribute]
          | Declaration DecType [Attribute]
+         | Ranksame Dot
          | Subgraph Text Dot
          | RawDot Text
          | Label Text
