diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,18 @@
 Brick changelog
 ---------------
 
+0.70
+----
+
+Enhancements:
+ * The table widget now behaves much better when some or all cells are
+   empty.
+
+Bug fixes:
+ * BorderMaps got fixed to ensure that smart borders connect even in the
+   presence of empty widgets (#370). Thanks to Daniel Wagner for this
+   fix!
+
 0.69.1
 ------
 
diff --git a/brick.cabal b/brick.cabal
--- a/brick.cabal
+++ b/brick.cabal
@@ -1,5 +1,5 @@
 name:                brick
-version:             0.69.1
+version:             0.70
 synopsis:            A declarative terminal user interface library
 description:
   Write terminal user interfaces (TUIs) painlessly with 'brick'! You
diff --git a/src/Brick/BorderMap.hs b/src/Brick/BorderMap.hs
--- a/src/Brick/BorderMap.hs
+++ b/src/Brick/BorderMap.hs
@@ -7,7 +7,7 @@
     ( BorderMap
     , Edges(..)
     , eTopL, eBottomL, eRightL, eLeftL
-    , empty, emptyCoordinates, singleton
+    , empty, clear, emptyCoordinates, singleton
     , insertH, insertV, insert
     , unsafeUnion
     , coordinates, bounds
@@ -54,14 +54,23 @@
 emptyCoordinates :: Edges Int -> BorderMap a
 emptyCoordinates cs = BorderMap { _coordinates = cs, _values = pure IM.empty }
 
--- | An empty 'BorderMap' that only tracks the point (0,0).
+-- | An empty 'BorderMap' that tracks the same points as the input.
+clear :: BorderMap a -> BorderMap b
+clear = emptyCoordinates . coordinates
+
+-- | An empty 'BorderMap' that does not track any points.
 empty :: BorderMap a
-empty = emptyCoordinates (pure 0)
+empty = emptyCoordinates Edges
+    { eTop = 0
+    , eBottom = -1
+    , eLeft = 0
+    , eRight = -1
+    }
 
 -- | A 'BorderMap' that tracks only the given the point (and initially maps it
 -- to the given value).
 singleton :: Location -> a -> BorderMap a
-singleton l v = translate l . insert origin v $ empty
+singleton l v = translate l . insert origin v . emptyCoordinates $ pure 0
 
 {-# INLINE coordinates #-}
 -- | The positions of the edges of the rectangle whose border is retained in a
diff --git a/src/Brick/Types/Internal.hs b/src/Brick/Types/Internal.hs
--- a/src/Brick/Types/Internal.hs
+++ b/src/Brick/Types/Internal.hs
@@ -338,7 +338,13 @@
            deriving (Show, Read, Generic, NFData)
 
 emptyResult :: Result n
-emptyResult = Result emptyImage [] [] [] BM.empty
+emptyResult =
+    Result { image = emptyImage
+           , cursors = []
+           , visibilityRequests = []
+           , extents = []
+           , borders = BM.empty
+           }
 
 -- | The type of events.
 data BrickEvent n e = VtyEvent Event
diff --git a/src/Brick/Widgets/Core.hs b/src/Brick/Widgets/Core.hs
--- a/src/Brick/Widgets/Core.hs
+++ b/src/Brick/Widgets/Core.hs
@@ -194,7 +194,7 @@
 --
 -- Frozen borders cannot be thawed.
 freezeBorders :: Widget n -> Widget n
-freezeBorders p = Widget (hSize p) (vSize p) $ (bordersL .~ BM.empty) <$> render p
+freezeBorders p = Widget (hSize p) (vSize p) $ (bordersL %~ BM.clear) <$> render p
 
 -- | The empty widget.
 emptyWidget :: Widget n
diff --git a/src/Brick/Widgets/Table.hs b/src/Brick/Widgets/Table.hs
--- a/src/Brick/Widgets/Table.hs
+++ b/src/Brick/Widgets/Table.hs
@@ -107,9 +107,7 @@
 -- 'TableException'.
 --
 -- All rows must have the same number of cells. If not, this will raise
--- a 'TableException'. In addition, all rows and columns must provide at
--- least one non-empty cell respectively, or the final result may not
--- look as desired.
+-- a 'TableException'.
 table :: [[Widget n]] -> Table n
 table rows =
     if not allFixed
@@ -205,7 +203,6 @@
 renderTable :: Table n -> Widget n
 renderTable t =
     joinBorders $
-    (if drawSurroundingBorder t then border else id) $
     Widget Fixed Fixed $ do
         ctx <- getContext
         let rows = tableRows t
@@ -220,7 +217,6 @@
             colWidth = maximum . fmap (imageWidth . image)
             byColumn = transpose cellResults
             toW = Widget Fixed Fixed . return
-            totalHeight = sum rowHeights
             applyColAlignment align width w =
                 Widget Fixed Fixed $ do
                     result <- render w
@@ -249,11 +245,37 @@
                                       else id
                 render $ vBox $ maybeRowBorders paddedCells
         columns <- mapM mkColumn $ zip3 allColAligns colWidths byColumn
-        let maybeColumnBorders =
-                if drawColumnBorders t
-                then let rowBorderHeight = if drawRowBorders t
-                                           then length rows - 1
-                                           else 0
-                     in intersperse (vLimit (totalHeight + rowBorderHeight) vBorder)
-                else id
-        render $ hBox $ maybeColumnBorders $ toW <$> columns
+
+        let tl = joinableBorder (Edges False True False True)
+            tr = joinableBorder (Edges False True True False)
+            bl = joinableBorder (Edges True False False True)
+            br = joinableBorder (Edges True False True False)
+            cross = joinableBorder (Edges True True True True)
+            leftT = joinableBorder (Edges True True False True)
+            rightT = joinableBorder (Edges True True True False)
+            topT = joinableBorder (Edges False True True True)
+            bottomT = joinableBorder (Edges True False True True)
+            vBorders = mkVBorder <$> rowHeights
+            hBorders = mkHBorder <$> colWidths
+            mkHBorder w = hLimit w hBorder
+            mkVBorder h = vLimit h vBorder
+            topBorder = hBox $ (if drawColumnBorders t then intersperse topT else id) hBorders
+            bottomBorder = hBox $ (if drawColumnBorders t then intersperse bottomT else id) hBorders
+            leftBorder = vBox $ tl : (if drawRowBorders t then intersperse leftT else id) vBorders <> [bl]
+            rightBorder = vBox $ tr : (if drawRowBorders t then intersperse rightT else id) vBorders <> [br]
+            maybeAddSurroundingBorder body =
+                if not $ drawSurroundingBorder t
+                then body
+                else leftBorder <+> (topBorder <=> body <=> bottomBorder) <+> rightBorder
+            maybeAddColumnBorders =
+                if not $ drawColumnBorders t
+                then id
+                else let maybeAddCrosses = if drawRowBorders t
+                                           then intersperse cross
+                                           else id
+                         columnBorder = vBox $ maybeAddCrosses vBorders
+                     in intersperse columnBorder
+
+        render $ maybeAddSurroundingBorder $
+                 hBox $
+                 maybeAddColumnBorders $ toW <$> columns
