diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,14 @@
 Brick changelog
 ---------------
 
+0.69.1
+------
+
+Bug fixes:
+ * `table` can now deal properly with empty cells that are in left- and
+   top-aligned settings. Previously, empty cells in those settings would
+   break table rendering. (#369)
+
 0.69
 ----
 
diff --git a/brick.cabal b/brick.cabal
--- a/brick.cabal
+++ b/brick.cabal
@@ -1,5 +1,5 @@
 name:                brick
-version:             0.69
+version:             0.69.1
 synopsis:            A declarative terminal user interface library
 description:
   Write terminal user interfaces (TUIs) painlessly with 'brick'! You
diff --git a/programs/LayerDemo.hs b/programs/LayerDemo.hs
--- a/programs/LayerDemo.hs
+++ b/programs/LayerDemo.hs
@@ -1,7 +1,11 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE TemplateHaskell #-}
 module Main where
 
+#if !(MIN_VERSION_base(4,11,0))
+import Data.Monoid ((<>))
+#endif
 import Lens.Micro ((^.), (&), (%~))
 import Lens.Micro.TH (makeLenses)
 import Control.Monad (void)
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
@@ -1033,11 +1033,22 @@
 
 -- | Given a widget, translate it to position it relative to the
 -- upper-left coordinates of a reported extent with the specified
--- positioning offset. This is useful for positioning something in a
--- higher layer relative to a reported extent in a lower layer. If the
--- specified name has no reported extent, this just draws the specified
--- widget with no special positioning.
-relativeTo :: (Show n, Ord n) => n -> Location -> Widget n -> Widget n
+-- positioning offset. If the specified name has no reported extent,
+-- this just draws the specified widget with no special positioning.
+--
+-- This is only useful for positioning something in a higher layer
+-- relative to a reported extent in a lower layer. Any other use is
+-- likely to result in the specified widget being rendered as-is with
+-- no translation. This is because this function relies on information
+-- about lower layer renderings in order to work; using it with a
+-- resource name that wasn't rendered in a lower layer will result in
+-- this being equivalent to @id@.
+--
+-- For example, if you have two layers @topLayer@ and @bottomLayer@,
+-- then a widget drawn in @bottomLayer@ with @reportExtent Foo@ can be
+-- used to relatively position a widget in @topLayer@ with @topLayer =
+-- relativeTo Foo ...@.
+relativeTo :: (Ord n) => n -> Location -> Widget n -> Widget n
 relativeTo n off w =
     Widget (hSize w) (vSize w) $ do
         mExt <- lookupReportedExtent 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
@@ -34,7 +34,8 @@
 import qualified Control.Exception as E
 import Data.List (transpose, intersperse, nub)
 import qualified Data.Map as M
-import Graphics.Vty (imageHeight, imageWidth)
+import Graphics.Vty (imageHeight, imageWidth, charFill)
+import Lens.Micro ((^.))
 
 import Brick.Types
 import Brick.Widgets.Core
@@ -106,7 +107,9 @@
 -- 'TableException'.
 --
 -- All rows must have the same number of cells. If not, this will raise
--- a 'TableException'.
+-- 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.
 table :: [[Widget n]] -> Table n
 table rows =
     if not allFixed
@@ -204,6 +207,7 @@
     joinBorders $
     (if drawSurroundingBorder t then border else id) $
     Widget Fixed Fixed $ do
+        ctx <- getContext
         let rows = tableRows t
         cellResults <- forM rows $ mapM render
         let rowHeights = rowHeight <$> cellResults
@@ -221,20 +225,25 @@
                 Widget Fixed Fixed $ do
                     result <- render w
                     case align of
-                        AlignLeft -> return result
+                        AlignLeft -> render $ hLimit width $ padRight Max $ toW result
                         AlignCenter -> render $ hLimit width $ hCenter $ toW result
                         AlignRight -> render $
                                           padLeft (Pad (width - imageWidth (image result))) $
                                           toW result
             applyRowAlignment rHeight align result =
                 case align of
-                 AlignTop -> toW result
+                 AlignTop -> vLimit rHeight $ padBottom Max $ toW result
                  AlignMiddle -> vLimit rHeight $ vCenter $ toW result
                  AlignBottom -> vLimit rHeight $ padTop Max $ toW result
+            fixEmtpyCell w h result =
+                if imageWidth (image result) == 0 && imageHeight (image result) == 0
+                then result { image = charFill (ctx^.attrL) ' ' w h }
+                else result
             mkColumn (hAlign, width, colCells) = do
                 let paddedCells = flip map (zip3 allRowAligns rowHeights colCells) $ \(vAlign, rHeight, cell) ->
                         applyColAlignment hAlign width $
-                        applyRowAlignment rHeight vAlign cell
+                        applyRowAlignment rHeight vAlign $
+                        fixEmtpyCell width rHeight cell
                     maybeRowBorders = if drawRowBorders t
                                       then intersperse (hLimit width hBorder)
                                       else id
