Tutorials
How to Build a Retool Image Gallery Component
If you've gone looking for a native Retool image gallery component, you already know it doesn't exist — at least not out of the box. Whether you're building a customer support tool where agents need to browse product images, or an internal CMS where teams review uploaded photos, you'll need to wire this together yourself. The good news: it's very doable, and this guide walks you through exactly how.
What You're Actually Trying to Build
Most people searching for a Retool image gallery want the same core feature set:
- A grid of image thumbnails — typically 3–4 per row
- Clicking a thumbnail opens a larger view in a modal or lightbox
- Optionally, left/right arrow navigation to cycle through images while the modal is open
- Support for multiple galleries grouped by category or entity
None of Retool's built-in components do all of this natively. But combining a Custom Component with a Modal gets you 90% of the way there with clean UX.
Approach 1: Custom Component + Retool Modal (Recommended)
This is the most flexible approach and the one that produces the best result. Here's how it works at a high level: your Custom Component renders the image grid using a library like material-ui GridList or CSS Grid, and a Retool-native Modal component handles the lightbox. Keeping the modal outside the iframe is critical — if you open a modal inside the Custom Component, it renders within the iframe boundaries, not full-screen.
Step-by-Step: Building the Image Grid
- Step 1 — Set up your Custom Component. In your Retool app, drag in a
Custom Component. This will render your thumbnail grid inside an iframe using HTML, CSS, and JavaScript you control directly. - Step 2 — Pass image data as a model prop. Use the Custom Component's
modelto pass in your image array from a query — something like{{ getProductImages.data }}. Each image object should include a URL and any metadata you want to display. - Step 3 — Render the grid in your component code. Inside the component, use CSS Grid or a library like
material-ui GridListto render thumbnails. A simple CSS approach:display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px;. This gives you a clean 4-column layout. - Step 4 — Wire up click events to trigger a Retool Modal. When a user clicks a thumbnail, use
Retool.modelUpdate()to push the selected image URL (and index) back to Retool. Then set aJS queryto fire on model change and callopenModal1()— or whatever your modal is named. - Step 5 — Configure the Retool Modal. Inside the modal, use an
Imagecomponent bound to the selected image URL stored in state or a variable. Add left/rightButtoncomponents that run a JS query to increment or decrement the selected image index. - Step 6 — Handle navigation logic. Write a small JS query that updates the current image index, clamped to the array length. Something like:
const next = (currentIndex + 1) % images.length;— then update your state variable and the image component rerenders automatically.
Approach 2: ListView Component (Simpler, Less Flexible)
If you want to avoid a Custom Component entirely, Retool's ListView can work as a lightweight alternative. You can render one image per row with a click handler that opens a modal. The limitation: ListView is inherently vertical, so you lose the grid layout. You can simulate columns by placing multiple ListView components side by side — one per column — but nesting a ListView inside another ListView row gets messy fast and is hard to maintain. Use this approach only if your image count is small and layout precision doesn't matter.
What About a Carousel Instead?
If a full image gallery grid is more than you need and a sequential image viewer would do the job, a Retool image carousel is a simpler build. The community has documented a working carousel pattern using a Custom Component with a lightweight carousel library. The same modal + index navigation logic described above applies — you're just changing the UI chrome around it. Check the Retool community thread on image carousel components for a full walkthrough.
Known Limitations to Plan Around
- Retool does not have a native
image galleryorcarouselcomponent as of this writing — always check the original feature request thread for updates. - Modals opened inside a
Custom Componentiframe are scoped to the iframe — they won't go full-screen. Always open modals at the Retool app level. - Passing large base64-encoded images through the
modelprop can cause performance issues. Pass URLs and load images directly in the browser instead. - If you need multiple galleries (e.g., one per product category), render multiple
Custom Componentinstances bound to filtered query data rather than trying to nestListViewcomponents.
When Retool Ships a Native Solution
Retool's team has acknowledged this gap and indicated they're tracking it. Until a native image gallery or grid component ships, the Custom Component approach above is your most production-ready option. It's not zero effort, but it's a one-time build you can turn into a reusable module across apps. If your team is building internal tools where image review is a core workflow — think customer support, QA, asset management — the investment is worth it.
Ready to build?
We scope, design, and ship your Retool app — fast.