OutSystems uses a 12-column CSS grid system. Set column widths on Container widgets (e.g., 6 columns = half width). Use responsive visibility classes (.visible-desktop, .visible-phone) and the Width properties in the Styles Editor to define breakpoint-specific layouts. The grid is mobile-first: start with phone layout, then override for larger screens.
Responsive Design Without CSS Media Queries
OutSystems' responsive layout system is built on a 12-column grid derived from Bootstrap, with OutSystems-specific widget properties that let you set responsive widths visually without writing CSS media queries. Every Container widget has width settings that correspond to grid column spans, and OutSystems provides helper CSS classes for showing and hiding content at phone, tablet, and desktop breakpoints. This tutorial builds a practical dashboard layout that adapts from three columns on desktop to one column on mobile.
Prerequisites
- A Reactive Web application open in Service Studio
- A screen to apply responsive layout to (create a blank screen if needed: Interface tab → UI Flows → MainFlow → right-click → Add Screen)
- Basic understanding of CSS grid columns is helpful but not required
Step-by-step guide
Understand the 12-Column Grid System
Understand the 12-Column Grid System
OutSystems UI uses a 12-column grid. Every Container widget placed on a screen can be assigned a column width from 1 to 12. Widgets in the same row share the 12 columns: - A single Container set to 12 columns spans the full width - Two Containers each set to 6 columns sit side by side (50% each) - Three Containers each set to 4 columns create a three-column layout - A Container set to 8 and one set to 4 creates a classic sidebar layout **Breakpoints in OutSystems UI:** | Name | Width range | Class suffix | |---|---|---| | Phone | up to 767px | -phone | | Tablet | 768px – 1023px | -tablet | | Desktop | 1024px and above | -desktop | The grid is mobile-first by default. Container width set in the Properties panel applies to all screen sizes. To override per breakpoint, use CSS media queries in your theme or the responsive helper classes. **View the grid in Service Studio:** Open any screen in the Screen Editor. The canvas shows column guides. In the Toolbox, search for 'Container' — drag one onto the screen and look at the 'Width' property in the Properties panel to see the column-based sizing.
Expected result: You understand that a 12-column grid underlies all OutSystems layouts. Container widgets are your primary layout tool, and their Width property controls column span.
Build a Responsive Header and Two-Column Layout
Build a Responsive Header and Two-Column Layout
Open a screen in the Screen Editor (Interface tab → UI Flows → MainFlow → double-click your screen). **Step 1 — Add a full-width header:** 1. Drag a Container from the Toolbox onto the screen canvas 2. In Properties panel → set Name to 'HeaderContainer' 3. In Properties panel → Styles tab → Width: 12 columns (full width) 4. Drag a Text widget inside the HeaderContainer, set Text to "Dashboard" 5. In Style Classes: `"font-size-h2 bold margin-bottom-m"` **Step 2 — Add a two-column content area:** 1. Drag a new Container below the HeaderContainer → Name: 'ContentRow' 2. Set ContentRow Style Classes: `"row"` (activates flex row layout) 3. Inside ContentRow, drag two Containers: - First: Name 'MainContent', Style Classes: `"col col-8"` (8 of 12 columns) - Second: Name 'Sidebar', Style Classes: `"col col-4"` (4 of 12 columns) **Column class format:** `col col-[n]` where n is 1–12. On phone screens, `col-[n]` classes default to full width (12 columns) automatically in the OutSystems UI grid — your layout stacks vertically on mobile without additional CSS.
1/* Widget tree for the two-column layout:23 Container (HeaderContainer) — col 124 └─ Text: "Dashboard"56 Container (ContentRow) — Style Classes: "row"7 ├─ Container (MainContent) — Style Classes: "col col-8"8 │ └─ [main content widgets here]9 └─ Container (Sidebar) — Style Classes: "col col-4"10 └─ [sidebar widgets here]11*/Expected result: The Screen Editor canvas shows a full-width header and a two-column content area (8-column main + 4-column sidebar). On mobile (check by resizing the browser), columns stack vertically.
Add Responsive Visibility — Show or Hide by Device
Add Responsive Visibility — Show or Hide by Device
OutSystems provides built-in CSS classes that show or hide elements at specific breakpoints: - `.visible-desktop` — visible on desktop only (≥1024px) - `.visible-tablet` — visible on tablet only (768–1023px) - `.visible-phone` — visible on phone only (≤767px) - `.hidden-desktop` — hidden on desktop, visible on other sizes - `.hidden-phone` — hidden on phone, visible on other sizes These classes are applied to the widget's **Style Classes** property. **Common use cases:** **Desktop-only sidebar:** Select the Sidebar container → Style Classes: `"col col-4 hidden-phone"`. The sidebar disappears on phone screens. **Mobile-only compact header:** Add a second Header container designed for mobile → Style Classes: `"hidden-desktop"`. The compact header shows only on phones. **Alternative — the Visible property:** Every widget also has a boolean **Visible** property. Set it to an expression: `If(DeviceType = "Phone", False, True)`. However, using CSS helper classes is more performant since the widget is hidden with CSS rather than removed from the DOM.
1/* Responsive visibility class examples in Style Classes property */23/* Show only on desktop: */4"visible-desktop col col-4"56/* Hide on phone (show on tablet + desktop): */7"col col-4 hidden-phone"89/* Show only on mobile: */10"visible-phone"1112/* Responsive text sizing using OutSystems UI utilities: */13"font-size-h3 visible-desktop font-size-h5 visible-phone"14/* Note: use separate If expression for conditional font size */1516/* Expression for conditional Style Classes: */17If(IsDesktop, "heading-desktop", "heading-mobile")Expected result: Elements with .visible-desktop class are invisible when you resize the browser below 1024px. Elements with .hidden-phone are invisible on phone-sized viewports. The layout adapts without JavaScript.
Use the Styles Editor for Visual Responsive Sizing
Use the Styles Editor for Visual Responsive Sizing
For per-widget sizing without writing CSS class names manually, use the **Styles Editor** in the Properties panel. 1. Select any widget on the screen canvas 2. In the Properties panel, click the **Styles tab** (paintbrush icon, second tab) 3. The Styles Editor shows visual controls for: Width, Height, Margin (top/right/bottom/left), Padding, Font, Color, Border, Shadow **Setting responsive width:** - In the Width field, enter `100%` for full width, `50%` for half, or `auto` - The Styles Editor adds inline styles — these override class-level CSS **Setting a max-width for readable content:** - Width: 100% - Max Width (in the Advanced section): 800px - Margin: 0 auto (centers the container) This is equivalent to the CSS: ``` .element { width: 100%; max-width: 800px; margin: 0 auto; } ``` Use the Styles Editor for one-off adjustments. For styles that apply to multiple widgets, always put the CSS in your Application Theme's Style Sheet Editor instead.
Expected result: The widget displays with the exact width and spacing you set in the Styles Editor. The Styles Editor values appear as inline styles in the rendered HTML, visible in browser DevTools.
Test Responsive Behavior and Use the Theme Editor
Test Responsive Behavior and Use the Theme Editor
**Testing in browser:** 1. Publish your app with 1-Click Publish 2. Open in browser 3. Open DevTools (F12) → click the Device Toggle icon (phone/tablet icon in toolbar) 4. Select device presets: iPhone SE, iPad, or set custom viewport width 5. Verify: two-column layout collapses to single-column at phone width; hidden-phone elements disappear **Using the Theme Editor for global responsive settings:** 1. In Service Studio, Interface tab → Themes → double-click your theme 2. Click the **Theme Editor** button in the toolbar (paint palette icon) 3. The Theme Editor dialog opens with visual sliders for: - Primary/Secondary/Heading colors - Font family and base size - Spacing density (Compact / Regular / Comfortable) - Header size 4. Changes in the Theme Editor generate CSS variable overrides automatically — no manual CSS needed for these global settings **Responsive grid breakpoints in OutSystems UI (for reference when writing custom media queries):**
1/* OutSystems UI grid breakpoints — use in custom CSS when needed */23/* Phone: up to 767px */4@media (max-width: 767px) {5 .dashboard-stats-row {6 flex-direction: column;7 }89 .stat-card {10 width: 100%;11 margin-bottom: 12px;12 }13}1415/* Tablet: 768px to 1023px */16@media (min-width: 768px) and (max-width: 1023px) {17 .col-4 {18 /* Override to show 2 columns on tablet instead of 3 */19 flex: 0 0 50%;20 max-width: 50%;21 }22}2324/* Desktop: 1024px and above */25@media (min-width: 1024px) {26 .page-container {27 max-width: 1200px;28 margin: 0 auto;29 }30}Expected result: Your app's layout adapts correctly at each breakpoint. The browser DevTools responsive viewer shows the layout changes as you drag the viewport width. The Theme Editor changes take effect after 1-Click Publish.
Complete working example
1/* ============================================2 Responsive Dashboard Layout CSS3 Add to: Application Theme → Style Sheet Editor4 ============================================ */56/* Dashboard wrapper */7.dashboard-wrapper {8 max-width: 1280px;9 margin: 0 auto;10 padding: 24px 16px;11}1213/* Stats row — 4 cards on desktop */14.stats-row {15 display: flex;16 flex-wrap: wrap;17 gap: 16px;18 margin-bottom: 24px;19}2021.stat-card {22 flex: 1 1 calc(25% - 16px);23 min-width: 200px;24 background: #ffffff;25 border-radius: 12px;26 padding: 20px;27 box-shadow: 0 2px 8px rgba(0,0,0,0.06);28}2930.stat-card__value {31 font-size: 32px;32 font-weight: 700;33 color: #2C6ECB;34 line-height: 1;35 margin-bottom: 4px;36}3738.stat-card__label {39 font-size: 14px;40 color: #6B7280;41}4243/* Main content grid */44.content-grid {45 display: grid;46 grid-template-columns: 1fr 320px;47 gap: 24px;48 align-items: start;49}5051/* Tablet: sidebar below main */52@media (max-width: 1023px) {53 .content-grid {54 grid-template-columns: 1fr;55 }5657 .stat-card {58 flex: 1 1 calc(50% - 16px);59 }60}6162/* Phone: full width everything */63@media (max-width: 767px) {64 .dashboard-wrapper {65 padding: 16px 12px;66 }6768 .stats-row {69 gap: 12px;70 }7172 .stat-card {73 flex: 1 1 100%;74 min-width: unset;75 }7677 .stat-card__value {78 font-size: 24px;79 }80}Common mistakes
Why it's a problem: Setting Container width to a fixed pixel value (e.g., width: 600px) instead of a column-based or percentage value
How to avoid: Use Style Classes 'col col-8' for column-based widths, or set Width to 100% with Max Width to a pixel value in the Styles Editor. Fixed pixel widths overflow on small screens.
Why it's a problem: Forgetting to add the 'row' class to the parent Container — child 'col' containers stack vertically instead of sitting side by side
How to avoid: The parent container of a grid row must have Style Classes set to 'row'. This enables flex display. Without 'row', the col classes apply widths but the layout remains block (vertical stacking).
Why it's a problem: Using display:none in custom CSS to hide an element, then wondering why the Visible property's logic does not work
How to avoid: If both CSS (display:none via a class) and the Visible property (removes from DOM) are in conflict, behavior is unpredictable. Choose one mechanism: use the Visible property for logic-driven visibility, or use CSS classes for viewport-based visibility. Do not mix both on the same widget.
Why it's a problem: Designing only for desktop resolution in Service Studio's canvas and never testing mobile
How to avoid: The Service Studio Screen Editor canvas is not a reliable mobile preview. Always test mobile layout by publishing to your environment and using browser DevTools (F12 → device toggle) to view at phone and tablet widths.
Best practices
- Design mobile-first: start with phone layout (single column, stacked) and use CSS to expand for larger screens
- Use OutSystems' col-n class system for simple layouts; switch to CSS Grid for complex asymmetric layouts
- Test responsive behavior in browser DevTools at each breakpoint (767px, 1023px) before publishing to production
- Use .hidden-phone and .hidden-desktop rather than the Visible property for performance — CSS-hidden elements render faster than DOM-removed ones
- Set max-width on main content containers (e.g., max-width: 1200px, margin: 0 auto) to prevent excessively wide layouts on large monitors
- Use the Theme Editor for global design changes (colors, fonts, spacing) before writing custom CSS — it generates safe, platform-aware CSS
- Avoid fixed pixel widths on Containers — use percentages, grid column units, or max-width with 100% width for truly flexible layouts
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I am building an OutSystems Reactive Web dashboard. On desktop it should show 4 stat cards in a row, then a two-column layout (main content area + sidebar). On tablet, the stats should be 2 per row and the sidebar should move below the main content. On phone, everything should be single column. Provide the CSS to add to my OutSystems Application Theme and the Service Studio widget structure (using the col class system) to achieve this.
In my OutSystems screen, I have a Container with Style Classes 'row' containing three inner Containers each with 'col col-4'. On desktop this shows three columns. How do I make the layout show two columns on tablet and one column on phone, using OutSystems' built-in responsive classes and CSS media queries in the Application Theme?
Frequently asked questions
Does OutSystems support CSS Grid and Flexbox, or is it limited to the column system?
Yes, CSS Grid and Flexbox work normally in OutSystems apps. You can write standard CSS Grid and Flexbox rules in your Application Theme's Style Sheet Editor and apply them via Style Classes on Container widgets. The OutSystems col system is built on Flexbox internally. You can use custom Grid/Flexbox alongside or instead of the col system — there is no restriction.
How do I make images responsive in OutSystems?
Set the Image widget's Width property to 100% in the Styles Editor, and optionally set Max Width to prevent it from scaling beyond its natural size. In your Theme CSS, add: img { max-width: 100%; height: auto; } as a global rule. OutSystems Image widgets render as standard HTML img elements, so standard CSS responsive image techniques apply.
Can I use CSS Container Queries (modern CSS) in OutSystems?
CSS Container Queries are a browser feature and work in OutSystems apps just like any other CSS. Add them to your Application Theme's Style Sheet Editor. Browser support for Container Queries is good as of 2026 (Chrome 106+, Firefox 110+, Safari 16+). Since OutSystems apps target modern browsers, Container Queries are safe to use.
What is the Screen Editor canvas resolution, and does it reflect real mobile size?
The Service Studio Screen Editor canvas shows an approximate desktop layout — it is not an accurate mobile preview. The canvas does not simulate breakpoints or device widths. For accurate mobile testing, publish the app and use browser DevTools (F12 → device toggle icon) to simulate specific device sizes, or test on a real device.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation