diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Revision history for brick-list-search
 
+## 0.1.1.0 -- 2023-02-21
+
+* Added `listSearchBy` and `listSearchByPages`.
+
 ## 0.1.0.0 -- 2023-02-20
 
 * First version with proper documentation.
diff --git a/brick-list-search.cabal b/brick-list-search.cabal
--- a/brick-list-search.cabal
+++ b/brick-list-search.cabal
@@ -1,6 +1,6 @@
 cabal-version: 3.0
 name: brick-list-search
-version: 0.1.0.0
+version: 0.1.1.0
 
 synopsis: Search forward or backward for certain kinds of items in brick list
 
diff --git a/demos/BrickListSearch.hs b/demos/BrickListSearch.hs
--- a/demos/BrickListSearch.hs
+++ b/demos/BrickListSearch.hs
@@ -1,6 +1,7 @@
 {-# LANGUAGE LambdaCase #-}
 module Main where
 
+import Brick.Widgets.List.Search
 -- base
 import Control.Monad (void)
 -- Third party libraries
@@ -15,7 +16,6 @@
 import Brick.Widgets.Border
 import Brick.Widgets.List
 import Brick.Widgets.Center
-import Brick.Widgets.List.Search
 import Graphics.Vty (defAttr, Event(..), Key(..), Modifier(..), black, white)
 
 data Name = TheList deriving (Eq, Ord, Show)
@@ -37,6 +37,10 @@
   VtyEvent (EvKey KEnd []) -> modify $ listSearchFromEnd isItem
   VtyEvent (EvKey KPageUp []) -> listSearchPageUp isItem
   VtyEvent (EvKey KPageDown []) -> listSearchPageDown isItem
+  VtyEvent (EvKey (KChar 'u') [MCtrl]) -> listSearchByPages isItem (-0.5)
+  VtyEvent (EvKey (KChar 'd') [MCtrl]) -> listSearchByPages isItem 0.5
+  VtyEvent (EvKey (KChar 'k') []) -> modify $ listSearchBy isItem (-2)
+  VtyEvent (EvKey (KChar 'j') []) -> modify $ listSearchBy isItem 2
   _ -> return ()
 
 renderListElement :: Bool -> ListElem -> Widget Name
@@ -52,7 +56,11 @@
                       , "Press Home to move to the beginning"
                       , "Press End to move to the end"
                       , "Press PageUp to move up one page"
-                      , "Press PageDown to move down one page" ]
+                      , "Press PageDown to move down one page"
+                      , "Press Ctrl+u to move up half page"
+                      , "Press Ctrl+d to move down half page"
+                      , "Press k to move up two items"
+                      , "Press j to move down two items"]
   in [vCenter $ vBox $
       hCenter (border $ vLimit 20 $ hLimit 30 $ renderList renderListElement True l) : map (hCenter . str) msgs]
 
diff --git a/src/Brick/Widgets/List/Search.hs b/src/Brick/Widgets/List/Search.hs
--- a/src/Brick/Widgets/List/Search.hs
+++ b/src/Brick/Widgets/List/Search.hs
@@ -14,12 +14,14 @@
 , searchListForward
 , searchListBackward
 -- * List manipulation
-, listSearchDown
+, listSearchBy
 , listSearchUp
-, listSearchFromBeginning
-, listSearchFromEnd
+, listSearchDown
+, listSearchByPages
 , listSearchPageUp
 , listSearchPageDown
+, listSearchFromBeginning
+, listSearchFromEnd
 -- * Classes
 , Searchable(..)
 ) where
@@ -78,18 +80,34 @@
   es = take start $ l ^. L.listElementsL
   in searchBackward (start-1) es
 
--- | Search forward for the first element that passes the test.
+-- | Move by an amount of list elements in the list. If the amount to move by is 0, no change is made. Otherwise, call
+-- 'L.listMoveBy'.
 --
--- The current element is not included in the search.
+-- The element chosen by 'L.listMoveBy' is included in the search.
 --
--- If forward search fails, no change is made.
-listSearchDown :: Searchable t
+-- After calling 'L.listMoveBy', if the amount to move by was positive, search forward for the first element that passes
+-- the test. If forward search fails, search backward for the first such element. If backward search fails too, no
+-- change is made.
+--
+-- After calling 'L.listMoveBy', if the amount to move by was negative, search backward for the first element that
+-- passes the test. If backward search fails, search forward for the first such element. If forward search fails too, no
+-- change is made.
+listSearchBy :: (Searchable t, Foldable t, L.Splittable t)
   => (e -> Bool) -- ^ The test
+  -> Int -- ^ The amount of list elements to move by
   -> L.GenericList n t e
   -> L.GenericList n t e
-listSearchDown test l = case searchListForward False test l of
-  Nothing -> l
-  Just idx -> l & L.listSelectedL ?~ idx
+listSearchBy test amt l = if amt == 0
+    then l
+    else let l' = L.listMoveBy amt l
+             (searchList, searchListOpposite) = if amt < 0
+               then (searchListBackward, searchListForward)
+               else (searchListForward, searchListBackward)
+    in case searchList True test l' of
+      Nothing -> case searchListOpposite True test l' of
+        Nothing -> l
+        Just idx -> l & L.listSelectedL ?~ idx
+      Just idx -> l & L.listSelectedL ?~ idx
 
 -- | Search backward for the first element that passes the test.
 --
@@ -104,31 +122,48 @@
   Nothing -> l
   Just idx -> l & L.listSelectedL ?~ idx
 
--- | From the first element, search forward for the first element that passes the test.
+-- | Search forward for the first element that passes the test.
 --
--- The first element is included in the search.
+-- The current element is not included in the search.
 --
 -- If forward search fails, no change is made.
-listSearchFromBeginning :: (Searchable t, Foldable t, L.Splittable t)
+listSearchDown :: Searchable t
   => (e -> Bool) -- ^ The test
   -> L.GenericList n t e
   -> L.GenericList n t e
-listSearchFromBeginning test l = case searchListForward True test (L.listMoveToBeginning l) of
+listSearchDown test l = case searchListForward False test l of
   Nothing -> l
   Just idx -> l & L.listSelectedL ?~ idx
 
--- | From the last element, search backward for the first element that passes the test.
+-- | Move by a (fractional) number of pages in the list. If the number of pages to move by is 0, no change is made.
+-- Otherwise, call 'L.listMoveByPages' with the number of pages to move by.
 --
--- The last element is included in the search.
+-- The element chosen by 'L.listMoveByPages' is included in the search.
 --
--- If backward search fails, no change is made.
-listSearchFromEnd :: (Searchable t, Foldable t, L.Splittable t)
+-- After calling 'L.listMoveByPages', if the number of pages to move by was positive, search forward for the first
+-- element that passes the test. If forward search fails, then search backward for the first such element. If backward
+-- search fails too, cancel movements made by this function.
+--
+-- After calling 'L.listMoveByPages', if the number of pages to move by was negative, search backward for the first
+-- element that passes the test. If backward search fails, then search forward for the first such element. If forward
+-- search fails too, cancel movements made by this function.
+listSearchByPages :: (Searchable t, Foldable t, L.Splittable t, Ord n, RealFrac m)
   => (e -> Bool) -- ^ The test
-  -> L.GenericList n t e
-  -> L.GenericList n t e
-listSearchFromEnd test l = case searchListBackward True test (L.listMoveToEnd l) of
-  Nothing -> l
-  Just idx -> l & L.listSelectedL ?~ idx
+  -> m -- ^ Pages to move by
+  -> EventM n (L.GenericList n t e) ()
+listSearchByPages test p = if p == 0
+  then return ()
+  else do
+    origL <- get
+    L.listMoveByPages p
+    let (searchList, searchListOpposite) = if p < 0
+           then (searchListBackward, searchListForward)
+           else (searchListForward, searchListBackward)
+    modify $ \l -> case searchList True test l of
+      Nothing -> case searchListOpposite True test l of
+        Nothing -> origL
+        Just idx -> l & L.listSelectedL ?~ idx
+      Just idx -> l & L.listSelectedL ?~ idx
 
 -- | Move up one page, and search backward for the first element that passes the test.
 --
@@ -140,14 +175,7 @@
 listSearchPageUp :: (Searchable t, Foldable t, L.Splittable t, Ord n)
   => (e -> Bool) -- ^ The test
   -> EventM n (L.GenericList n t e) ()
-listSearchPageUp test = do
-  origL <- get
-  L.listMovePageUp
-  modify $ \l -> case searchListBackward True test l of
-    Nothing -> case searchListForward True test l of
-      Nothing -> origL
-      Just idx -> l & L.listSelectedL ?~ idx
-    Just idx -> l & L.listSelectedL ?~ idx
+listSearchPageUp test = listSearchByPages test (-1 :: Double)
 
 -- | Move down one page, and search forward for the first element that passes the test.
 --
@@ -159,14 +187,33 @@
 listSearchPageDown :: (Searchable t, Foldable t, L.Splittable t, Ord n)
   => (e -> Bool) -- ^ The test
   -> EventM n (L.GenericList n t e) ()
-listSearchPageDown test = do
-  origL <- get
-  L.listMovePageDown
-  modify $ \l -> case searchListForward True test l of
-    Nothing -> case searchListBackward True test l of
-      Nothing -> origL
-      Just idx -> l & L.listSelectedL ?~ idx
-    Just idx -> l & L.listSelectedL ?~ idx
+listSearchPageDown test = listSearchByPages test (1 :: Double)
+
+-- | From the first element, search forward for the first element that passes the test.
+--
+-- The first element is included in the search.
+--
+-- If forward search fails, no change is made.
+listSearchFromBeginning :: (Searchable t, Foldable t, L.Splittable t)
+  => (e -> Bool) -- ^ The test
+  -> L.GenericList n t e
+  -> L.GenericList n t e
+listSearchFromBeginning test l = case searchListForward True test (L.listMoveToBeginning l) of
+  Nothing -> l
+  Just idx -> l & L.listSelectedL ?~ idx
+
+-- | From the last element, search backward for the first element that passes the test.
+--
+-- The last element is included in the search.
+--
+-- If backward search fails, no change is made.
+listSearchFromEnd :: (Searchable t, Foldable t, L.Splittable t)
+  => (e -> Bool) -- ^ The test
+  -> L.GenericList n t e
+  -> L.GenericList n t e
+listSearchFromEnd test l = case searchListBackward True test (L.listMoveToEnd l) of
+  Nothing -> l
+  Just idx -> l & L.listSelectedL ?~ idx
 
 -- | Functions for searching elements.
 class Searchable (t :: * -> *) where
