OutSystems Front-End Developer Specialist study materials
OutSystems Front-End Developer Specialist study resources

Three KPI Cards That Only Fit on the Developer's Laptop

OutSystems Front-End Developer Specialist · Put your knowledge to work in context.

All case studies

Three KPI Cards That Only Fit on the Developer's Laptop

An insurance company is rebuilding its agent dashboard as a Reactive Web app in OutSystems 11 with OutSystems UI 2.9. The design specifies a row of three KPI cards: 24 px gutters, each card one-third width on desktop, one-half on tablet, and full width on phone. The developer built the row with a Container, set its Style Classes to a screen-level class .kpi-row, and wrote .kpi-row { display: flex; gap: 24px; } .kpi-card { width: 360px; }. On a 1366x768 laptop the row looks correct. On a 1280 px-wide Surface Pro the third card wraps below the first two and leaves a 240 px empty gap on the right. On a 1920 px monitor the three cards stay left-aligned instead of filling the content area, and the page shows a horizontal scrollbar. The app uses the Theme Grid for other screens. The team wants to keep the custom 8 px radius and shadow on the cards.

1. Diagnose why the fixed-width flex row breaks at 1280 px and 1920 px, and explain what the Theme Grid's Columns widget would do differently.

Read the worked answer

The row is sized by content, not by the container. Three cards at 360 px plus two 24 px gaps need 1128 px. Once the content area drops below roughly 1128 px after page padding and the side menu, the flex items cannot shrink because their flex-basis is a fixed width and their default min-width: auto prevents shrinking below content. The third card wraps. At 1920 px the opposite happens: fixed widths do not grow, so the row stays at 1128 px and leaves unused space. The horizontal scrollbar usually comes from a child wider than its parent, often an icon or a long label inside a card with no min-width: 0.

The Theme Grid Columns widget is percentage-based on a 12-column grid. Each Column has Desktop, Tablet and Phone width settings. Setting the three columns to 4, 6 and 12 gives one-third, one-half and full width at the theme breakpoints. Gutters are handled by the grid rather than by fixed widths, so the row fills the content area at every viewport.

2. Write the replacement layout using OutSystems UI widgets and CSS, including the exact breakpoint behaviour and gutter handling. Mention any properties you would set in Service Studio.

Read the worked answer

Preferred approach: drop the custom flex row and use a Columns widget with three Column children. On each Column set Desktop width 4, Tablet width 6, Phone width 12. Set the Columns widget Gutter to the theme size that resolves to 24 px in your theme, or use the closest token and adjust the theme token rather than adding margins. Remove .kpi-card { width: 360px; } entirely; apply the card visual class through the Style Classes property on each card Container.

If the team must keep flex for a non-grid reason, use .kpi-row { display: flex; flex-wrap: wrap; gap: 24px; } and .kpi-card { flex: 1 1 calc((100% - 48px) / 3); min-width: 0; box-sizing: border-box; }. Add media queries at the theme breakpoints: below 1024 px use flex-basis: calc((100% - 24px) / 2); below 768 px use flex-basis: 100%. The min-width: 0 is not optional: without it, a long KPI label can still force overflow.

3. The card shadow and 8 px radius must stay. Where should that CSS live, and how do you avoid overriding the theme's spacing tokens?

Read the worked answer

Put the reusable visual treatment in the app's global style sheet as a named class such as .card-elevated, not in each screen's local style sheet. The screen style sheet should contain only layout rules that are genuinely specific to that screen; otherwise the same shadow gets redefined in five places and drifts.

Use the theme's radius and elevation variables where they exist, for example border-radius: var(--border-radius-soft) and the theme shadow token, and fall back to the literal 8 px only if the theme has no matching token. Do not put margin or padding on .card-elevated; those belong to the grid gutter and to the card's internal spacing, otherwise the grid gutter and the card margin add together and produce a 48 px visual gap. Avoid !important; if a rule is not winning, the cause is usually selector order or an inline style, and adding !important hides that.