Part 93: Building Mobile Ready LWC
Welcome back to the Salesforce blog series. We have covered a lot of ground with Lightning Web Components so far, from the basics of CSS in Part 75 all the way through dynamic template rendering in Part 79 and the Salesforce Mobile App itself back in Part 34. Now it is time to bring all of those topics together and talk about something that too many developers leave as an afterthought: building components that actually work on mobile.
The Salesforce Mobile App is not going away. In fact, Salesforce has been doubling down on mobile experiences for years. More and more users are accessing their orgs from phones and tablets, and if your custom LWC looks great on a desktop monitor but falls apart on a five-inch screen, you have a problem. The good news is that building mobile-ready components is not difficult once you understand the patterns. It just requires a little planning and some specific techniques.
In this post, we are going to cover what mobile readiness actually means, how to design your components for mobile from the start, how to set up CSS that responds to different screen sizes, and how to use dynamic template rendering to serve entirely different layouts when the situation calls for it.
What Does It Mean to Be Mobile Ready?
Before we start writing code, let us take a step back and define what we are actually talking about. A mobile-ready LWC is a component that provides a usable, functional, and visually appropriate experience on mobile devices. That includes phones and tablets running the Salesforce Mobile App, as well as mobile browsers accessing a Lightning Experience org.
Mobile readiness is not the same as responsiveness. Responsiveness is one tool in the toolbox. A responsive component adjusts its layout based on the available viewport width. But true mobile readiness goes further. It considers touch targets, network conditions, screen density, limited screen real estate, the absence of hover states, and the behavioral differences between the Salesforce Mobile App and the desktop Lightning Experience.
Here are the key dimensions of mobile readiness:
- Layout adaptability — Your component should rearrange its content gracefully as the screen gets narrower. Multi-column layouts should collapse to single columns. Tables should transform into stacked cards or lists.
- Touch-friendly interactions — Buttons and interactive elements need to be large enough to tap comfortably. The general guideline is a minimum of 44 by 44 pixels for any tappable target. Hover-dependent interactions need alternatives since there is no hover on a touchscreen.
- Performance awareness — Mobile devices often have less processing power and slower network connections. Minimize the amount of data you load upfront. Lazy-load when possible. Avoid heavy DOM trees.
- Platform behavior differences — The Salesforce Mobile App does not support every feature that the desktop Lightning Experience does. Some base Lightning components behave differently on mobile. Navigation patterns change. You need to test on actual mobile devices, not just a narrow browser window.
- Content prioritization — On a small screen, you cannot show everything at once. Decide what information is essential and what can be hidden behind a tap or swipe. This is a design decision, not just a CSS one.
The simplest test for mobile readiness is to open your component on an actual phone. If you can complete every workflow without zooming, scrolling horizontally, or struggling to tap a button, you are in good shape. If not, you have work to do.
How to Design Your Components to Work on Mobile
Good mobile readiness starts in the design phase, not in the CSS file. If you design a component that assumes a wide viewport and then try to retrofit it for mobile, you are going to have a bad time. The better approach is to design mobile-first and then expand for larger screens.
Think in Terms of Stacking
On desktop, you might have a component that shows a data table next to a detail panel, side by side. On mobile, those two sections need to stack vertically. The data table goes on top, the detail panel goes below. Or maybe you hide the detail panel entirely and let the user tap a row to navigate to a detail view.
When you are planning your component layout, think about how every section will stack. Draw it out if you have to. A quick wireframe on paper showing the desktop layout and the mobile layout side by side will save you hours of CSS debugging later.
Reduce and Prioritize
On desktop, you might show ten columns in a table. On mobile, you can realistically show two or three. That means you need to decide which columns are essential. The rest can be hidden or moved into an expandable detail section.
This applies to forms as well. A form with twenty fields on desktop should probably be broken into steps or sections on mobile. Show the most important fields first and let the user expand for more.
Use Standard Components When Possible
Salesforce base Lightning components like lightning-datatable, lightning-card, and lightning-accordion already have some degree of mobile awareness built in. They handle basic touch events, respect platform styling, and in some cases adjust their layout for smaller screens. Before building a custom solution, check whether a base component already handles what you need.
Plan Your Navigation
Navigation in the Salesforce Mobile App works differently than on desktop. The mobile app uses a tab-based navigation model with a bottom navigation bar. Page references and NavigationMixin (which we covered in earlier parts of this series) still work, but the visual result is different. Pop-up modals on mobile take up the full screen. Utility bars are not available. Plan your user flows with these constraints in mind.
How to Set Up Mobile Compatible CSS
Now let us get into the code. The primary tool for making your LWC layouts responsive is CSS media queries. If you followed along in Part 75, you already know how CSS works inside LWC. The same principles apply here, but we are adding viewport-aware rules.
Media Queries in LWC
Media queries let you apply different styles depending on the characteristics of the device or viewport. The most common use is to target viewport width. Here is a basic example of a component CSS file that adjusts layout based on screen size:
/* Default mobile-first styles */
.container {
display: flex;
flex-direction: column;
gap: 1rem;
padding: 0.75rem;
}
.card {
width: 100%;
padding: 1rem;
border: 1px solid var(--slds-g-color-border-base-1, #e5e5e5);
border-radius: var(--slds-g-radius-border-2, 0.25rem);
}
.card-title {
font-size: 1rem;
font-weight: 700;
}
.action-button {
min-height: 44px;
min-width: 44px;
padding: 0.75rem 1.5rem;
font-size: 1rem;
}
/* Tablet and up */
@media (min-width: 768px) {
.container {
flex-direction: row;
flex-wrap: wrap;
padding: 1rem;
}
.card {
width: calc(50% - 0.5rem);
}
}
/* Desktop and up */
@media (min-width: 1024px) {
.container {
padding: 1.5rem;
}
.card {
width: calc(33.333% - 0.67rem);
}
.card-title {
font-size: 1.125rem;
}
}
Notice the mobile-first approach. The default styles target the smallest screen. Then we use min-width media queries to add complexity as the viewport grows. This is the opposite of writing desktop styles first and then overriding them for mobile, and it results in cleaner, more maintainable CSS.
The SLDS Grid System
If you are using the Salesforce Lightning Design System (which you should be), the SLDS grid provides responsive utility classes out of the box. You can use the slds-size_ and slds-large-size_ classes in your HTML template to control column widths at different breakpoints:
<template>
<div class="slds-grid slds-wrap slds-gutters">
<div class="slds-col slds-size_1-of-1 slds-medium-size_1-of-2 slds-large-size_1-of-3">
<c-info-card title="Account Details"></c-info-card>
</div>
<div class="slds-col slds-size_1-of-1 slds-medium-size_1-of-2 slds-large-size_1-of-3">
<c-info-card title="Recent Activity"></c-info-card>
</div>
<div class="slds-col slds-size_1-of-1 slds-medium-size_1-of-1 slds-large-size_1-of-3">
<c-info-card title="Open Cases"></c-info-card>
</div>
</div>
</template>
This gives you a single-column layout on phones, two columns on tablets, and three columns on desktops, all without writing a single media query yourself. The SLDS grid handles it through its class-based responsive system.
Handling Touch Targets
One of the most common mobile usability problems is buttons and links that are too small to tap. On desktop, a tiny icon button works fine because a mouse cursor is precise. On mobile, your finger is not. Always ensure interactive elements meet the 44px minimum tap target size:
.icon-button {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 44px;
min-height: 44px;
padding: 0.5rem;
cursor: pointer;
}
/* Remove hover effects on touch devices */
@media (hover: none) {
.icon-button:hover {
background-color: transparent;
}
}
The @media (hover: none) query is a useful trick. It targets devices that do not support hover, which effectively means touchscreens. Use it to strip out hover states that do not make sense on mobile and replace them with active or focus states instead.
Hiding and Showing Content
Sometimes you need to hide non-essential content on mobile entirely. You can do this with media queries and a utility class pattern:
.desktop-only {
display: none;
}
.mobile-only {
display: block;
}
@media (min-width: 768px) {
.desktop-only {
display: block;
}
.mobile-only {
display: none;
}
}
Use this sparingly. Hiding content is not a substitute for good design. If something is important enough to show on desktop, consider whether it really should be hidden on mobile or if it just needs a different presentation.
How to Leverage Dynamic Template Rendering for Mobile
Sometimes CSS alone is not enough. When the desktop and mobile versions of a component are fundamentally different in structure, not just in styling, you need to render different templates entirely. This is where dynamic template rendering comes in. We covered the mechanics of this technique back in Part 79, so I will focus on how to apply it specifically for mobile scenarios.
Detecting the Form Factor
Salesforce provides a way to detect the form factor of the current device through the @salesforce/client/formFactor module. This returns one of three values: Large for desktops, Medium for tablets, and Small for phones.
import { LightningElement } from 'lwc';
import FORM_FACTOR from '@salesforce/client/formFactor';
import desktopTemplate from './desktopTemplate.html';
import mobileTemplate from './mobileTemplate.html';
export default class AdaptiveComponent extends LightningElement {
get isMobile() {
return FORM_FACTOR === 'Small';
}
get isTablet() {
return FORM_FACTOR === 'Medium';
}
get isDesktop() {
return FORM_FACTOR === 'Large';
}
render() {
if (this.isMobile) {
return mobileTemplate;
}
return desktopTemplate;
}
}
The render() method is called by the framework to determine which template to use. By importing multiple HTML files and returning the appropriate one based on the form factor, you can serve completely different markup to different devices.
Structuring Your Files
When using multiple templates, your component folder will look something like this:
adaptiveComponent/
adaptiveComponent.js
adaptiveComponent.css
desktopTemplate.html
mobileTemplate.html
The main JavaScript file imports both HTML files and chooses between them in the render() method. The CSS file applies to whichever template is currently rendered. If you need different styles for each template, you can use class-based scoping within a shared CSS file or keep your responsive styles in the single CSS file.
When to Use Dynamic Templates vs CSS
This is an important design decision. Here is how to think about it:
Use CSS media queries when the content is the same but the layout needs to change. Cards stacking vertically instead of horizontally, font sizes adjusting, columns collapsing — these are all CSS-level concerns.
Use dynamic template rendering when the content or structure is fundamentally different. For example, a desktop version of a component might show a full data table with inline editing, while the mobile version shows a simplified list with tap-to-edit detail views. Trying to handle that difference with CSS alone would result in bloated markup where half the DOM is always hidden.
A practical example: imagine you are building a dashboard component. The desktop version has a sidebar with filters and a main content area with charts. The mobile version drops the sidebar entirely and moves the filters behind a toggle button at the top of the screen. The chart area takes full width and the charts stack vertically. That is a case where two separate templates make the code much cleaner than a single template with conditional rendering and media queries fighting each other.
Combining Both Approaches
In practice, you will often use both techniques together. Dynamic templates handle the major structural differences, and CSS media queries handle the fine-tuning within each template. The mobile template might still use media queries to adjust between a small phone and a larger phone. The desktop template might use media queries to handle the difference between a laptop and a wide monitor.
import { LightningElement } from 'lwc';
import FORM_FACTOR from '@salesforce/client/formFactor';
import desktopTemplate from './desktopTemplate.html';
import mobileTemplate from './mobileTemplate.html';
export default class DashboardComponent extends LightningElement {
showFilters = false;
render() {
return FORM_FACTOR === 'Small' ? mobileTemplate : desktopTemplate;
}
handleToggleFilters() {
this.showFilters = !this.showFilters;
}
}
The mobile template uses showFilters to toggle a collapsible filter section, while the desktop template always shows the filters in a sidebar. Same data, same logic, different presentation. This separation keeps both templates clean and focused.
Section Notes
Building mobile-ready LWC is not about adding a few media queries at the end of a project. It is a mindset that starts with design and runs through every line of CSS and every architectural decision.
The key takeaways from this section:
- Mobile readiness encompasses layout, touch targets, performance, platform differences, and content prioritization. It is broader than just responsive CSS.
- Design mobile-first. Start with the smallest screen and add complexity as the viewport grows. This results in cleaner code and forces you to prioritize what matters.
- Use CSS media queries with a mobile-first
min-widthapproach for layout adjustments. Lean on the SLDS grid system for responsive column layouts without writing custom queries. - Ensure all interactive elements meet the 44px minimum tap target size. Use
@media (hover: none)to handle touch-specific interaction states. - Use
@salesforce/client/formFactorand dynamic template rendering when the desktop and mobile experiences are structurally different, not just visually different. - Combine CSS responsiveness and dynamic templates for the cleanest results. Let templates handle structural differences and CSS handle visual fine-tuning.
- Always test on actual mobile devices. The Salesforce Mobile App and a narrow desktop browser are not the same thing.
In the next post, we will continue building on these patterns and explore more advanced LWC topics. See you there.