diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,15 @@
 Brick changelog
 ---------------
 
+0.40
+----
+
+New features:
+ * Brick.Widgets.Core: added new functions `hLimitPercent` and
+   `vLimitPercent`. These behave similarly to `hLimit` and `vLimit`
+   except that instead of taking absolute numbers of columns or rows,
+   they take percentages. (Thanks Roman Joost)
+
 0.39
 ----
 
diff --git a/brick.cabal b/brick.cabal
--- a/brick.cabal
+++ b/brick.cabal
@@ -1,5 +1,5 @@
 name:                brick
-version:             0.39
+version:             0.40
 synopsis:            A declarative terminal user interface library
 description:
   Write terminal applications painlessly with 'brick'! You write an
diff --git a/programs/FillDemo.hs b/programs/FillDemo.hs
--- a/programs/FillDemo.hs
+++ b/programs/FillDemo.hs
@@ -1,10 +1,13 @@
 module Main where
 
 import Brick
+import Brick.Widgets.Border
 
 ui :: Widget ()
-ui = vBox [ str "This text is at the top."
-          , fill ' '
+ui = vBox [ vLimitPercent 20 $ vBox [ str "This text is at the top."
+                                    , fill ' '
+                                    , hBorder
+                                    ]
           , str "This text is at the bottom."
           ]
 
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
@@ -38,7 +38,9 @@
 
   -- * Limits
   , hLimit
+  , hLimitPercent
   , vLimit
+  , vLimitPercent
   , setAvailableSize
 
   -- * Attribute management
@@ -757,16 +759,46 @@
 hLimit :: Int -> Widget n -> Widget n
 hLimit w p =
     Widget Fixed (vSize p) $
-      withReaderT (& availWidthL %~ (min w)) $ render $ cropToContext p
+      withReaderT (availWidthL %~ (min w)) $ render $ cropToContext p
 
 -- | Limit the space available to the specified widget to the specified
+-- percentage of available width, as a value between 0 and 100
+-- inclusive. Values outside the valid range will be clamped to the
+-- range endpoints. This is important for constraining the horizontal
+-- growth of otherwise-greedy widgets. This is non-greedy horizontally
+-- and defers to the limited widget vertically.
+hLimitPercent :: Int -> Widget n -> Widget n
+hLimitPercent w' p =
+    Widget Fixed (vSize p) $ do
+      let w = clamp 0 100 w'
+      ctx <- getContext
+      let usableWidth = ctx^.availWidthL
+          widgetWidth = round (toRational usableWidth * (toRational w / 100))
+      withReaderT (availWidthL %~ (min widgetWidth)) $ render $ cropToContext p
+
+-- | Limit the space available to the specified widget to the specified
 -- number of rows. This is important for constraining the vertical
 -- growth of otherwise-greedy widgets. This is non-greedy vertically and
 -- defers to the limited widget horizontally.
 vLimit :: Int -> Widget n -> Widget n
 vLimit h p =
     Widget (hSize p) Fixed $
-      withReaderT (& availHeightL %~ (min h)) $ render $ cropToContext p
+      withReaderT (availHeightL %~ (min h)) $ render $ cropToContext p
+
+-- | Limit the space available to the specified widget to the specified
+-- percentage of available height, as a value between 0 and 100
+-- inclusive. Values outside the valid range will be clamped to the
+-- range endpoints. This is important for constraining the vertical
+-- growth of otherwise-greedy widgets. This is non-greedy vertically and
+-- defers to the limited widget horizontally.
+vLimitPercent :: Int -> Widget n -> Widget n
+vLimitPercent h' p =
+    Widget (vSize p) Fixed $ do
+      let h = clamp 0 100 h'
+      ctx <- getContext
+      let usableHeight = ctx^.availHeightL
+          widgetHeight = round (toRational usableHeight * (toRational h / 100))
+      withReaderT (availHeightL %~ (min widgetHeight)) $ render $ cropToContext p
 
 -- | Set the rendering context height and width for this widget. This
 -- is useful for relaxing the rendering size constraints on e.g. layer
