diff --git a/CHANGELOG.md b/CHANGELOG.md
index b24dbfe9a..3f74318af 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,7 @@
 ### Improvements
 - Have zarr use read-only mode ([#1360](../../pull/1360))
 - Use minified geojs ([#1362](../../pull/1362))
+- Configurable item list grid view ([#1363](../../pull/1363))
 
 ### Bug Fixes
 - Default to "None" for the DICOM assetstore limit ([#1359](../../pull/1359))
diff --git a/docs/girder_config_options.rst b/docs/girder_config_options.rst
index 8f8716c2e..78ef39d40 100644
--- a/docs/girder_config_options.rst
+++ b/docs/girder_config_options.rst
@@ -55,6 +55,13 @@ This is used to specify how items appear in item lists.  There are two settings,
     ---
     # If present, show a table with column headers in item lists
     itemList:
+      # layout does not need to be specified.
+      layout:
+        # The default layout is a list.  This can optionally be "grid"
+        mode: grid
+        # max-width is only used in grid mode.  It is the maximum width in
+        # pixels for grid entries.  It defaults to 250.
+        max-width: 250
       # show these columns in order from left to right.  Each column has a
       # "type" and "value".  It optionally has a "title" used for the column
       # header, and a "format" used for searching and filtering.
@@ -99,6 +106,17 @@ This is used to specify how items appear in item lists.  There are two settings,
           # the length of arrays.
           value: gloms.length
           title: Number of Gloms
+          # You can have this value be populated for just some of the items by
+          # specifying an "only" list.  Each entry in the only list must have
+          # the "type" and "value" as per the column it is filtering on, plus a
+          # "match" value that is used as a case-insensitive RegExp.  All such
+          # limits must match to show the value.
+          only:
+            -
+              type: record
+              value: name
+              # only show this for items whose names end with ".svs".
+              match: "\\.svs$"
         # You can edit metadata in a item list by adding the edit: true entry
         # and the options from the itemMetadata records that are detailed
         # below.  In this case, edits to metadata that validate are saved
diff --git a/girder/girder_large_image/web_client/stylesheets/itemList.styl b/girder/girder_large_image/web_client/stylesheets/itemList.styl
index de559d012..69b605c22 100644
--- a/girder/girder_large_image/web_client/stylesheets/itemList.styl
+++ b/girder/girder_large_image/web_client/stylesheets/itemList.styl
@@ -84,6 +84,20 @@ ul.g-item-list
         justify-content center
         width inherit
 
+  &.li-item-list[layout_mode="grid"]
+    display block
+
+    &>li.g-item-list-entry
+      display inline-block
+      overflow hidden
+      border 1px solid rgba(0, 0, 0, 0.1)
+      padding 1px
+      vertical-align top
+      max-width 250px
+
+    &>li>.li-item-list-cell
+      display inline-block
+
 .li-item-list-filter
   padding-left 12px
 
diff --git a/girder/girder_large_image/web_client/templates/itemList.pug b/girder/girder_large_image/web_client/templates/itemList.pug
index 857191a08..d186bf75e 100644
--- a/girder/girder_large_image/web_client/templates/itemList.pug
+++ b/girder/girder_large_image/web_client/templates/itemList.pug
@@ -1,18 +1,20 @@
-ul.g-item-list.li-item-list
+ul.g-item-list.li-item-list(layout_mode=(itemList.layout || {}).mode || '')
+  - var colNames = [];
   li.li-item-list-header
     if checkboxes
       span.li-item-list-header
-    for column in itemList.columns
+    for column, colidx in itemList.columns
       if column.type !== 'image' || hasAnyLargeImage
         span.li-item-list-header(
             class=((column.type === 'record' && column.value !== 'controls') || column.type === 'metadata' ? 'sortable' : '') + ' ' + (sort && sort[0].type === column.type && sort[0].value === column.value ? sort[0].dir : ''),
             column_type=column.type, column_value=column.value)
           if column.title !== undefined
-            = column.title
+            - colNames[colidx] = column.title
           else
-            = `${column.value.substr(0, 1).toUpperCase()}${column.value.substr(1)}`
+            - colNames[colidx] = `${column.value.substr(0, 1).toUpperCase()}${column.value.substr(1)}`
+          = colNames[colidx]
   each item in items
-    li.g-item-list-entry(class=(highlightItem && item.id === selectedItemId ? 'g-selected' : ''), public=(isParentPublic ? 'true' : 'false'))
+    li.g-item-list-entry(class=(highlightItem && item.id === selectedItemId ? 'g-selected' : ''), public=(isParentPublic ? 'true' : 'false'), style=(itemList.layout || {}).mode == 'grid' ? ('max-width: ' + parseInt((itemList.layout || {})['max-width'] || 250) + 'px') : '')
       if checkboxes
         span.li-item-list-cell
           input.g-list-checkbox(type="checkbox", g-item-cid=item.cid)
@@ -23,8 +25,26 @@ ul.g-item-list.li-item-list
             var classes = divtype == 'a' ? ['g-item-list-link']: [];
             if (('' + column.type + column.value).match(/^[a-zA-Z][a-zA-Z0-9-_]*$/))  classes.push(`li-column-${column.type}-${column.value}`);
             if (('' + column.type).match(/^[a-zA-Z][a-zA-Z0-9-_]*$/))  classes.push(`li-column-${column.type}`);
-          #{divtype}.li-item-list-cell(class=classes.join(' '), g-item-cid=item.cid, href=`#item/${item.id}`)
-            if column.type === 'record'
+            var skip = false;
+            (column.only || []).forEach((only) => {
+              if (!(only || {}).match) {
+                return;
+              }
+              var onlyval = (only.type === 'record' && only.value === 'name') ? item.name() : (only.type === 'record' && only.value === 'description') ? item.get(only.value) : '';
+              if (only.type === 'metadata') {
+                onlyval = item.get('meta') || {};
+                only.value.split('.').forEach((part) => {
+                  onlyval = (onlyval || {})[part];
+                })
+              }
+              if (onlyval.match(new RegExp(only.match, 'i')) === null) {
+                skip = true;
+              }
+            });
+          #{divtype}.li-item-list-cell(class=classes.join(' '), g-item-cid=item.cid, href=`#item/${item.id}`, title=colNames[colidx])
+            if skip
+              //- ignore
+            else if column.type === 'record'
               if column.value === 'name'
                 span.g-item-list-link
                   i.icon-doc-text-inv
diff --git a/test/test_files/.large_image_config.yaml b/test/test_files/.large_image_config.yaml
index 0dee9d424..24693f87d 100644
--- a/test/test_files/.large_image_config.yaml
+++ b/test/test_files/.large_image_config.yaml
@@ -3,6 +3,11 @@ access:
   user:
     # itemList adjustments
     itemList:
+      layout:
+        # grid or list
+        # mode: grid
+        # for grids, how wide should items be
+        min-width: 200
       # Show these columns
       columns:
         -
@@ -24,6 +29,11 @@ access:
           type: metadata
           value: Stain
           format: text
+          # Only show this record for entries that match a particular value
+          only:
+            - type: record
+              value: name
+              match: "\\.svs$"
         -
           type: metadata
           value: Classification