Build Lightning Web Components that are excellent citizens on Lightning pages. Components must look great standalone and alongside other components in App Builder's column layouts.
Core Principles
1Fluid, not fixed — components fill their column, never overflow
2Configurable — expose meaningful properties in App Builder
3Consistent height — cards in the same row should align visually
4Communicate cleanly — use LMS for cross-DOM, events for parent-child
5Design-time friendly — show useful previews in App Builder
App Builder Column Layouts
Lightning pages use a region-based grid. Components must adapt to these widths.
| Layout | Regions | Approximate Widths |
| Single column | 1 | ~100% (1200px max) |
| Two column (66/33) | 2 | ~780px / ~380px |
| Two column (50/50) | 2 | ~580px / ~580px |
| Three column (25/50/25) | 3 | ~280px / ~580px / ~280px |
| Three column (33/33/33) | 3 | ~380px / ~380px / ~380px |
Designing for All Columns
: host {
display: block;
width: 100%;
contain: layout;
}
.component-root {
background: var(--slds-g-color-surface-1, #ffffff);
border: var(--slds-g-sizing-border-1) solid var(--slds-g-color-border-1, #e5e5e5);
border-radius: var(--slds-g-radius-border-2, 0.25rem);
overflow: hidden;
}
Content Reflow Rules
| Column Width | Layout Behavior |
| >= 580px | Multi-column grids, side-by-side metrics |
| 380-579px | Two-column grids collapse to single, stacked layout |
| 280-379px | Single column, compact spacing, abbreviated labels |
.content-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: var(--slds-g-spacing-3, 0.75rem);
}
meta.xml Configuration
Exposing Properties in App Builder
<?xml version="1.0" encoding="UTF-8"?>
<class="code-tag">LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<class="code-tag">apiVersion>62.0</class="code-tag">apiVersion>
<class="code-tag">isExposed>true</class="code-tag">isExposed>
<class="code-tag">masterLabel>Account Overview Card</class="code-tag">masterLabel>
<class="code-tag">description>Displays key account metrics with configurable sections.</class="code-tag">description>
<class="code-tag">targets>
<class="code-tag">target>lightning__RecordPage</class="code-tag">target>
<class="code-tag">target>lightning__AppPage</class="code-tag">target>
<class="code-tag">target>lightning__HomePage</class="code-tag">target>
</class="code-tag">targets>
<class="code-tag">targetConfigs>
<class="code-tag">targetConfig targets="lightning__RecordPage">
<class="code-tag">objects>
<class="code-tag">object>Account</class="code-tag">object>
<class="code-tag">object>Contact</class="code-tag">object>
</class="code-tag">objects>
<class="code-tag">property name="showMetrics" type="Boolean" label="Show Metrics"
description="Display metric cards" default="true" />
<class="code-tag">property name="showChart" type="Boolean" label="Show Chart"
description="Display trend chart" default="true" />
<class="code-tag">property name="maxItems" type="Integer" label="Max Items"
description="Maximum items to display" default="5"
min="1" max="20" />
<class="code-tag">property name="variant" type="String" label="Card Style"
datasource="Default,Compact,Detailed"
default="Default" />
</class="code-tag">targetConfig>
<class="code-tag">targetConfig targets="lightning__AppPage,lightning__HomePage">
<class="code-tag">property name="title" type="String" label="Card Title"
default="Account Overview" />
</class="code-tag">targetConfig>
</class="code-tag">targetConfigs>
</class="code-tag">LightningComponentBundle>
Property Type Reference
| Type | Use For | Notes |
String | Labels, field names | Use datasource for picklists |
Boolean | Toggle sections on/off | Default should be the common case |
Integer | Counts, limits | Use min/max for validation |
Color | Theme accents | Renders a color picker in App Builder |
Property Best Practices
- Limit to 5-7 properties per target config (avoid overwhelming admins)
- Group related toggles:
showHeader, showMetrics, showFooter
- Provide sensible defaults so the component works with zero configuration
- Use
datasource for string properties with known options instead of free text
- Separate target configs when Record Page needs different options than App Page
Consistent Card Height and Alignment
When multiple components appear in the same row, misaligned heights look broken.
Self-Sizing Card
: host {
display: block;
height: 100%;
}
.card {
display: flex;
flex-direction: column;
height: 100%;
background: var(--slds-g-color-surface-1, #ffffff);
border: var(--slds-g-sizing-border-1) solid var(--slds-g-color-border-1, #e5e5e5);
border-radius: var(--slds-g-radius-border-2, 0.25rem);
}
.card__header {
flex-shrink: 0;
padding: var(--slds-g-spacing-3, 0.75rem) var(--slds-g-spacing-4, 1rem);
border-bottom: var(--slds-g-sizing-border-1) solid var(--slds-g-color-border-1, #e5e5e5);
}
.card__body {
flex: 1;
overflow-y: auto;
padding: var(--slds-g-spacing-4, 1rem);
}
.card__footer {
flex-shrink: 0;
padding: var(--slds-g-spacing-3, 0.75rem) var(--slds-g-spacing-4, 1rem);
border-top: var(--slds-g-sizing-border-1) solid var(--slds-g-color-border-1, #e5e5e5);
margin-top: auto;
}
Fixed-Height Scrollable Body
For components that can have variable amounts of data:
.card__body--scrollable {
max-height: 400px;
overflow-y: auto;
}
Cross-Component Communication
Decision Matrix
| Pattern | Direction | Scope | Use When |
@api properties | Parent to child | Same DOM tree | Passing data down |
CustomEvent | Child to parent | Same DOM tree | Bubbling actions up |
| Lightning Message Service | Any to any | Same Lightning page | Cross-DOM, different components |
| URL parameters | Page to component | Navigation | Deep linking, page context |
lightning/navigation | Component to page | App-wide | Record navigation, tab switching |
Lightning Message Service Pattern
import { publish, subscribe, unsubscribe, MessageContext } from class="code-string">'lightning/messageService';
import RECORD_SELECTED from class="code-string">'@salesforce/messageChannel/RecordSelected__c';
@wire(MessageContext)
messageContext;
connectedCallback() {
this._subscription = subscribe(
this.messageContext,
RECORD_SELECTED,
(message) => this.handleRecordSelected(message)
);
}
disconnectedCallback() {
unsubscribe(this._subscription);
this._subscription = null;
}
handleRecordSelected(message) {
this.selectedRecordId = message.recordId;
}
publishSelection(recordId) {
publish(this.messageContext, RECORD_SELECTED, { recordId });
}
Design-Time Preview
Components should look meaningful in App Builder even without live data.
Placeholder Pattern
get isDesignMode() {
return !this.recordId && !this._dataLoaded;
}
get displayData() {
if (this.isDesignMode) {
return this.placeholderData;
}
return this._liveData;
}
get placeholderData() {
return [
{ id: class="code-string">'1', name: class="code-string">'Sample Account', amount: class="code-string">'$125,000' },
{ id: class="code-string">'2', name: class="code-string">'Example Corp', amount: class="code-string">'$89,000' },
{ id: class="code-string">'3', name: class="code-string">'Demo Inc', amount: class="code-string">'$210,000' }
];
}
<class="code-tag">template>
<class="code-tag">div class={rootClass}>
<class="code-tag">div if:true={isDesignMode} class="design-mode-badge">
Preview Mode
</class="code-tag">div>
class="code-comment"><!-- Component content renders with placeholder or live data -->
</class="code-tag">div>
</class="code-tag">template>
.design-mode-badge {
position: absolute;
top: var(--slds-g-spacing-2, 0.5rem);
right: var(--slds-g-spacing-2, 0.5rem);
padding: var(--slds-g-spacing-1, 0.25rem) var(--slds-g-spacing-2, 0.5rem);
font-size: var(--slds-g-font-size-1, 0.625rem);
background: var(--slds-g-color-info-container-1, #e5f0fb);
color: var(--slds-g-color-info-1, #0176d3);
border-radius: var(--slds-g-radius-border-1, 0.125rem);
}
Demo Page Recipes
Pre-built Lightning page layout suggestions for common SE demo scenarios.
Account 360 Record Page
Layout: Two Column (66/33)
LEFT COLUMN (Main):
1. c-account-health-score — Radial gauge + trend (sf-lwc-dataviz)
2. c-key-metrics-row — 4 KPI cards: Revenue, Employees, Open Opps, Cases
3. c-activity-timeline — Recent activities with staggered reveal animation
4. c-related-contacts — Contact cards with role and last interaction
RIGHT COLUMN (Sidebar):
1. c-next-best-action — AI recommendation card (the wow moment)
2. c-quick-actions — Branded action buttons
3. c-team-members — Account team with avatars
meta.xml targets: lightning__RecordPage (Account)
Sales Dashboard App Page
Layout: Three Column (25/50/25)
LEFT COLUMN:
1. c-pipeline-summary — Funnel or stacked bar
2. c-top-deals — Top 5 opportunities list
CENTER COLUMN:
1. c-kpi-row — Pipeline Value, Win Rate, Avg Deal Size, Velocity
2. c-forecast-chart — Forecast vs Actual bar chart
3. c-recently-closed — Recent wins with amounts
RIGHT COLUMN:
1. c-team-leaderboard — Rep rankings with sparklines
2. c-upcoming-tasks — Next 5 tasks/events
meta.xml targets: lightning__AppPage
Service Console Record Page
Layout: Two Column (66/33)
LEFT COLUMN:
1. c-case-header — Status badge, priority, SLA timer
2. c-customer-context — Account info, sentiment, history
3. c-case-timeline — Full interaction history
RIGHT COLUMN:
1. c-knowledge-suggestions — AI-suggested articles
2. c-similar-cases — Matching resolved cases
3. c-quick-response — Template response buttons
meta.xml targets: lightning__RecordPage (Case)
Home Page Dashboard
Layout: Single Column → Two Column (50/50)
TOP (Full Width):
1. c-welcome-banner — Personalized greeting with task summary
BOTTOM LEFT:
1. c-my-open-items — Cases, leads, opps requiring action
2. c-recent-records — Recently viewed with quick actions
BOTTOM RIGHT:
1. c-team-performance — Team KPIs and trends
2. c-announcements — Org-wide updates
meta.xml targets: lightning__HomePage
Scoring Rubric (100 Points)Reference
| Category | Points | Pass Criteria |
| Fluid Layout | 20 | Works in all column widths; no overflow; reflows content |
| meta.xml Quality | 20 | Correct targets, sensible defaults, 5-7 configurable properties |
| Card Consistency | 15 | Full-height cards, aligned headers/footers, scrollable body |
| Communication | 20 | Correct pattern chosen per use case; LMS for cross-DOM |
| Design-Time Preview | 15 | Shows meaningful content in App Builder without live data |
| Slot Architecture | 10 | Uses for extensibility; allows parent customization |
Cross-Skill IntegrationReference
| Skill | Relationship |
| sf-lwc-design | Provides SLDS 2 hooks for all card/layout CSS |
| sf-lwc-ux | Loading/empty/error states must work in all column widths |
| sf-lwc-styling | Utility classes must be fluid-aware |
| sf-lwc-mobile | Small-column behavior mirrors mobile viewport patterns |
| sf-se-demo-scripts | Demo page recipes accelerate App Builder configuration |