Complex UI components like cards and modals in Bubble are built by combining Groups, conditional visibility, and custom states. This tutorial covers designing reusable card layouts with image, title, and description patterns, building modal popups with forms, and creating overlay patterns for detail views that open without navigating to a new page.
Overview: Building Cards, Modals, and Complex Components
Cards and modals are foundational UI patterns in modern apps. This tutorial teaches you to build polished card layouts for Repeating Groups, modal popup dialogs for forms and detail views, and overlay patterns that enhance user experience without page navigation. You will learn to make these components reusable and data-driven.
Prerequisites
- A Bubble account with an app
- Basic familiarity with Groups and element styling
- Understanding of custom states and conditional visibility
- At least one Data Type with records to display
Step-by-step guide
Design a reusable card component
Design a reusable card component
Create a Group element with Column layout, white background, 1px border (using your border color variable), 12px border-radius, and 0px padding. Inside, add: an Image element at the top (set to cover mode, fixed height like 200px, full width), then a Group with 20px padding containing a Text element for the title (18px bold), a Text for description (14px, 2-line clamp using max-height and overflow hidden), and a Group with Row layout for metadata (date, category badge, etc.). Save this Group as an Element Style called 'Card' so you can reuse the styling on any similar group throughout your app.
Pro tip: Add a hover effect using conditional formatting: when This Group is hovered, add a subtle shadow (0 4px 12px rgba(0,0,0,0.1)) for visual feedback.
Expected result: A polished card component with image, title, description, and metadata ready for use in Repeating Groups.
Use cards in a Repeating Group grid
Use cards in a Repeating Group grid
Add a Repeating Group with Row layout and set the number of columns (3 for desktop). Set the type of content to your Data Type and configure the data source. In the first cell, build or paste your card structure. Bind each element to the current cell's data: Image source = Current cell's image field, title Text = Current cell's title, description Text = Current cell's description. Add the 'Card' style to the outer Group. Set row-gap and column-gap to 24px for consistent spacing. Make the RG responsive by enabling row wrapping so cards stack on smaller screens.
Expected result: A responsive grid of cards displaying data from your database with consistent styling.
Build a modal popup for forms
Build a modal popup for forms
Add a Popup element to the page (found in the Element Palette under Containers). Name it 'Popup Form'. Set it to not visible on page load. Inside, add a Group with Column layout and max-width of 500px. Add a header Group with Row layout containing a title Text and a close button (X icon). Below, add your form elements: Inputs, Dropdowns, Multiline Inputs as needed. Add Save and Cancel buttons at the bottom. The Cancel button workflow hides the popup. The Save button workflow creates or updates a record, then hides the popup. Bubble automatically adds a semi-transparent overlay behind popups.
Expected result: A centered modal popup with a form that appears over the current page content.
Create a detail view overlay
Create a detail view overlay
Add another Popup called 'Popup Detail'. Set its type of content to your Data Type. Inside, build a full detail view: large Image, title, full description (no line clamping), metadata, and action buttons (Edit, Delete, Share). To open this popup from a card click, add a workflow on the card Group: when clicked, Display data in 'Popup Detail' (sending the current cell's data) and then Show 'Popup Detail'. The popup receives the data and all its elements dynamically display the selected record's fields. Add an Edit button that opens 'Popup Form' pre-filled with the record's data.
Expected result: Clicking a card opens a detail overlay showing the full record without navigating to a new page.
Pass data between components using custom states and Display data
Pass data between components using custom states and Display data
For communication between cards and popups, use two patterns. Pattern 1 (Display data): when showing a popup, use 'Display data in a group' to send the selected record to the popup. The popup's elements reference 'Parent group's [Data Type]' to access the data. Pattern 2 (Custom states): create a custom state on the page called selected_item (type: your Data Type). When a card is clicked, set the state to the current cell's data. The popup reads from the page's state. This pattern is useful when multiple components need to react to the same selection.
Expected result: Data flows seamlessly between card clicks and popup displays using Display data or custom states.
Make components reusable across pages
Make components reusable across pages
Convert your card and modal patterns into reusable elements for use across multiple pages. Select the card Group, right-click, and choose 'Convert to reusable element' (or create a new reusable element and rebuild the structure). For the modal popup, create a reusable element of type Popup. Add custom properties to pass configuration data: title text, button labels, form fields to show. Place these reusable elements on any page. When the card needs to communicate with the popup, use custom states on the reusable elements that the parent page can read.
Expected result: Card and modal components exist as reusable elements deployable on any page in your app.
Complete working example
1CARD AND MODAL COMPONENT SUMMARY2==================================34CARD COMPONENT (Group, Column layout):5 Style: white bg, 1px border, 12px radius, no padding6 Structure:7 Image (cover mode, 200px height, full width)8 Content Group (20px padding, Column):9 Title Text (18px bold)10 Description Text (14px, 2-line clamp)11 Meta Group (Row): date, category badge12 Hover: conditional shadow13 Click: Display data in Popup Detail → Show popup1415MODAL POPUP (Popup element):16 Not visible on page load17 Inner Group: 500px max-width, Column layout18 Structure:19 Header (Row): Title + Close (X) button20 Form Body: Inputs, Dropdowns, etc.21 Footer (Row): Cancel + Save buttons22 Close: Hide this popup23 Save: Create/Modify record → Hide popup2425DETAIL OVERLAY (Popup element, typed):26 Type of content: [Data Type]27 Structure:28 Large Image29 Full title and description30 Metadata31 Action buttons: Edit, Delete, Share32 Data: received via Display data action3334DATA PASSING PATTERNS:35 Card → Modal (Display data):36 Card clicked → Display data in Popup → Show Popup37 Popup elements: Parent group's [type]'s [field]3839 Card → Page state (Custom state):40 Card clicked → Set state selected_item = cell's data41 Any element reads: page's selected_item's [field]4243RESPONSIVE GRID:44 Repeating Group: Row layout, 3 columns45 Gap: 24px row-gap and column-gap46 Wrap: enabled for mobile stackingCommon mistakes when expanding to complex components like cards and modals in Bubble.io: Step-by-
Why it's a problem: Building card layouts directly in the Repeating Group without a reusable pattern
How to avoid: Create an Element Style for the card Group and convert the card into a reusable element for consistent use across pages
Why it's a problem: Using Go to page for detail views instead of popups
How to avoid: Use Popup elements for detail views that open as overlays, keeping the user on the same page with their context intact
Why it's a problem: Not setting the Popup's type of content before adding dynamic elements
How to avoid: Set the Popup's type of content in the Property Editor before adding any dynamic Text or Image elements inside it
Best practices
- Create Element Styles for card and modal patterns for consistent reuse
- Use popups for detail views and forms to avoid page navigation
- Set Popup type of content before adding dynamic elements inside
- Add hover effects on cards for visual click affordance
- Pass data to popups using Display data for simple cases and custom states for complex multi-component coordination
- Make card grids responsive with row wrapping enabled
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I need to build a product catalog in Bubble with card-style product listings and a detail popup when you click a card. Can you help me design the card layout and the popup interaction?
Help me create reusable card components for my product listing and a modal popup for the detail view. When a user clicks a card, show the full product details in a popup overlay with an Edit button.
Frequently asked questions
Can I animate modals when they open?
Yes. Add a transition animation to the Popup or its inner Group in the Appearance tab. Bubble supports fade, slide, and scale transitions when elements become visible.
How do I close a modal by clicking outside it?
Bubble popups close automatically when the user clicks outside the popup area (on the overlay). This is the default behavior and does not require additional configuration.
Can I have multiple popups on one page?
Yes. Add as many Popup elements as needed. Each has its own Show/Hide actions. Just make sure only one is shown at a time to avoid overlap confusion.
How do I limit description text to 2 lines in a card?
Set the Text element to a fixed max-height (about 40px for 2 lines at 14px font) and check 'Cut off content if element is not tall enough' in the Layout tab.
Can I create a card with a dropdown menu?
Yes. Add a Group inside the card with a three-dot icon. On click, toggle a custom state that shows a hidden Group containing menu options (Edit, Delete, Share). Position it using Align to Parent layout.
Can RapidDev help build a component library for my Bubble app?
Yes. RapidDev can create a full component library with reusable cards, modals, forms, navigation elements, and data displays that maintain consistency across your entire application.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation