Making PCF Controls Work on Phones and Small Screens

A technical guide for the developer whose PCF control breaks on a phone: the host sizing contract, trackContainerResize and allocatedWidth, CSS without fixed widths, touch targets, scroll conflicts and testing in the Power Apps mobile app.

A PCF control breaks on a phone because the host allocates its space and the control ignored it. A control built against a desktop width overflows, clips or collapses when the form gives it less. The fix is to honour the sizing contract: call context.mode.trackContainerResize(true) in init, lay out against context.mode.allocatedWidth and allocatedHeight in updateView, handle -1 for an unconstrained dimension, and use a ResizeObserver for internal layout. Remove fixed pixel widths and minimum table widths from the CSS. Then make it usable, not merely visible: touch targets large enough for a finger, no scroll or gesture fights with the host form, and testing in the Power Apps mobile app on real devices rather than a narrowed desktop browser.

Why does a PCF control that works on desktop break on a phone?

Because a code component does not own its space. The model-driven form, the section column layout, the device and the app decide how much width the control receives, and they can change that allocation while the form is open, for example when a phone rotates or a side pane opens. A control written as if it always had a desktop section to fill makes decisions the host never agreed to: a grid with a fixed column set wider than the screen, a toolbar that assumes one line, a chart sized once at init, or a drag surface that swallows the touch gestures the page needs to scroll.

The symptoms are familiar: a horizontal scrollbar on the whole form, content cut off at the right edge, a control that renders as a thin strip, buttons too small to hit, or a form that cannot be scrolled while a finger is over the control. None of them are phone bugs in the platform. They are the control not reacting to the space it was given.

Sizing inside model-driven forms is one of several harness against production gaps, and the full catalogue is in PCF controls in production. This page goes deeper on the small screen case only.

What is the sizing contract between the host and a PCF control?

The host tells the control how much room it has through context.mode, and only when the control asks for it. These are the parts of the framework that matter for responsive behaviour. Exact host behaviour can differ between model-driven forms, custom pages, canvas apps and releases, so confirm it in your own environment and in current Microsoft documentation.

APIWhat it gives youWhat to do with it
context.mode.trackContainerResize(true)Asks the host to report the allocated size and to call updateView when it changesCall it once in init for any control whose layout depends on width
context.mode.allocatedWidthThe width in pixels the host has allocated to the controlLay out against it instead of window.innerWidth or a hard-coded breakpoint
context.mode.allocatedHeightThe allocated height, often -1 on model-driven forms because the section grows with contentTreat -1 as unconstrained and let height follow content
updateViewCalled when properties change, dataset pages load and, with tracking on, when the container resizesRe-render cheaply from the new size; do not rebuild the whole tree or re-fetch data
context.client.getFormFactor()The form factor the app is running as: unknown, desktop, tablet or phoneSwitch interaction patterns, not pixel layout, for example a list instead of a wide grid

How do you use trackContainerResize and allocatedWidth correctly?

Turn tracking on in init, read the size in updateView, and guard against the values that break naive code. Without the init call, allocatedWidth and allocatedHeight can stay at -1, and a control that writes width: -1px or divides by the height renders nothing useful.

Keep the reaction cheap. updateView can fire many times while the user rotates a device or the form reflows, so a size change should update a width in state and let the layout respond, not reload data or recreate a third party chart. Where a library needs an explicit size, resize the existing instance rather than destroying and creating it. The lifecycle rules behind this, including what belongs in init and what belongs in updateView, are part of our PCF controls development guide.

  • Call context.mode.trackContainerResize(true) in init, before the first render.
  • In updateView, read context.mode.allocatedWidth; if it is -1 or 0, fall back to the width of your own root element rather than to the window.
  • Treat allocatedHeight of -1 as "grow with content" on model-driven forms, and never compute row counts or chart heights by dividing it.
  • Compare the new width with the last rendered width and skip work when only other properties changed; context.updatedProperties helps you tell the difference.
  • Pick layout modes from width bands you define for the control, such as narrow, medium and wide, instead of from device names.

Why use a ResizeObserver inside the control as well?

Because the allocated width describes the outer box, and responsive problems often happen inside it. A toolbar that wraps to two lines, a panel that opens within the control, a label that grows after translation or a chart legend that takes half the space all change the size available to child elements without the host allocation changing at all.

A ResizeObserver attached to the control's own root or to a specific inner region reports the real rendered size of that element, so internal layout can react to it: collapse secondary actions into a menu, hide a legend, switch a two column detail view to one column. Create the observer once in init or when the root element mounts, and disconnect it in destroy, or it keeps firing after the control has left the form. Throttle the handler to one update per animation frame so a rotation does not cause a burst of re-renders.

Use the two together: allocatedWidth to decide the overall mode the host has given you, and the observer for the fine layout inside it.

Which CSS patterns break PCF controls on small screens?

Most broken mobile controls come down to a handful of CSS decisions made on a wide monitor. The control's styles should let it shrink to the allocated width without the host form ever showing a horizontal scrollbar.

PatternWhat happens on a phoneReplace it with
Fixed pixel width on the root or main panelsThe control is wider than the section and pushes the form sidewayswidth: 100% with max-width, and box-sizing: border-box
min-width on a table or gridThe whole form scrolls horizontally, not just the gridA narrow layout with fewer columns or a card list, and horizontal scrolling contained inside the grid if it must stay a table
Many fixed-width columnsColumns are squeezed into unreadable slivers or overflowPriority columns shown at narrow widths, the rest in a detail view
Long unbroken text such as emails and IDsOne value stretches the layoutoverflow-wrap: anywhere or truncation with the full value available on tap
Layout based on window width media queriesMedia queries see the whole screen, not the section the control sits inLayout from allocatedWidth, or CSS container queries on the control root where the host browser supports them
Hover-only actions and tooltipsActions never appear on touch devicesVisible actions or an explicit menu button
Global selectors or styles on body and htmlStyles leak into the host form and break its layout on smaller screensStyles scoped to a class on the control root

How big should touch targets be in a PCF control?

Large enough to hit with a thumb while walking, and far enough apart that the neighbour is not hit instead. WCAG 2.2 sets a minimum target size of 24 by 24 CSS pixels at level AA and an enhanced size of 44 by 44 at level AAA; for controls used on phones in the field, designing towards the larger size is the safer habit. Spacing counts as much as size: a row of small icons with no gap between them fails in practice even if each icon meets a number.

Fluent UI components give sensible defaults, but custom interactions such as grid cells, chips, drag handles and inline icons are where controls usually fall short. Replace drag and drop with a tap-based alternative on phones, such as a move menu, because long-press dragging inside a scrolling form is unreliable and hard to discover. The same alternative is also what keyboard and assistive technology users need, which is covered with the rest of keyboard, focus and screen reader work in retrofitting accessibility into PCF controls.

  • Make the whole row or card the target where tapping it has one obvious meaning, not only a small icon inside it.
  • Keep destructive actions away from frequently tapped ones, and confirm them.
  • Show pressed and selected states clearly, because there is no hover state on touch.
  • Do not rely on double tap or right click; neither is a reliable gesture in a mobile host.

How do you stop a PCF control fighting the host form for scrolling?

On a phone the form itself scrolls vertically, and every nested scroll area inside a control competes with it. A user who puts a finger on a grid with its own vertical scroll can find the form will not move, or that the grid scrolls when they meant to move the page. Nested vertical scrolling is the most common reason a control that renders correctly is still reported as broken on mobile.

  • Avoid a fixed-height inner area with its own vertical scroll on narrow layouts; let the control grow with content and show a limited number of records with a "show more" action.
  • If a region must scroll horizontally, such as a wide table, contain it with overflow-x: auto on that region only, and set touch-action: pan-x pan-y so vertical swipes still reach the form.
  • Do not call preventDefault on touchstart or touchmove for the whole control. Listeners that block scrolling should be limited to the element that genuinely needs the gesture, such as a signature pad or a map.
  • Use overscroll-behavior: contain on inner scroll regions so reaching the end of a list does not unexpectedly scroll or refresh the page around it.
  • For maps, charts and canvases, consider requiring an explicit tap to activate panning, so a user scrolling past the control does not get trapped in it.
  • Release every touch, pointer and resize listener in destroy.

When should a control change behaviour by form factor instead of just shrinking?

When a smaller version of the desktop design is still the wrong design. A twelve column editable grid cannot become usable at phone width by narrowing columns; it needs a different interaction, such as a list of cards showing the two or three fields that matter with a tap into details. context.client.getFormFactor() tells the control whether the app is running as a phone, tablet or desktop, which is a reasonable signal for choosing that interaction pattern.

Use it for interaction decisions and allocatedWidth for layout decisions. A desktop form can place a control in a narrow column, and a tablet in landscape can give it plenty of width, so width bands should still drive the visual layout within whichever pattern the form factor selected. Keep one control with two presentations sharing the same data and state logic, rather than two separate controls configured on different forms, so fixes land in one place.

If the real need is a frontline app built for phones from the start, a PCF control inside a model-driven form may not be the right vehicle at all. The routes for mobile users are compared in Dynamics 365 mobile app options, and canvas hosting of code components is covered in using PCF controls in canvas apps.

How should a PCF control be tested on real phones and in the mobile app?

On the devices and apps your users actually hold. A desktop browser window dragged narrow, or device emulation in developer tools, is useful for a first layout pass, but it does not reproduce the Power Apps mobile app's shell, real touch input, the on-screen keyboard taking half the height, rotation, slower devices or real network conditions. The local test harness is even further away, because you set the size yourself.

  • Open the real form in the Power Apps mobile app on at least one current iOS device and one Android device, signed in as a user with the production security role.
  • Test the placements the specification promised: the control in a narrow form section, on a full-width tab, and as a subgrid where applicable, because each gets a different allocation.
  • Rotate the device with the form open and check the control re-lays out without reloading data.
  • Scroll the whole form with a finger placed over the control, and check that inner scroll areas, maps and signature pads do not trap the page.
  • Tap every action with a thumb, including in the narrowest layout, and open the on-screen keyboard in any input.
  • Check read only and disabled states and a record with no data on the phone as well as on desktop.
  • Record the app version, device, OS version and form factor with each test result, since mobile host behaviour can change with app updates. Check current Microsoft documentation for debugging options on mobile.

Should a mobile-heavy process run on Dynamics 365 or a custom-built application?

For most organisations already on Dynamics 365 Customer Engagement or Power Platform, a responsive PCF control inside the existing model-driven app is the cheapest correct fix: users stay in one app, security and data stay in Dataverse, and the control can be corrected without changing the process. When a team's work is almost entirely on phones, with offline needs and interactions the model-driven shell does not suit, the comparison of routes in our mobile options guide is the better starting point.

We recommend the right solution - whether that's Microsoft Dynamics 365, Power Platform, or a custom-built CRM. Some businesses need the Microsoft ecosystem. Others need full control without licensing. We deliver both. For organisations that do not want per-user Microsoft licensing for a mobile workforce, a custom-built CRM on React, Node.js, PostgreSQL or .NET gives full control over the mobile interface, and the same responsive rules on this page apply to its components.

How does Solzet help make PCF controls work on phones and small screens?

We start by opening the broken control on real devices in the Power Apps mobile app, with the forms and roles your users have, and record exactly where it breaks: allocation, CSS, touch, scrolling or the interaction pattern itself. Then we fix the sizing contract, remove the fixed widths, add a narrow layout or a phone presentation where a smaller desktop layout will not do, resolve the scroll and gesture conflicts, and hand back a tested managed solution with source code. Where several controls share the same defects, the fixes go into a shared component layer once.

The work is done by senior consultants and full-stack developers delivering remotely from Yerevan, Armenia, with 8+ years of Dynamics 365 Customer Engagement and Power Platform work, directly for your team or white-label for Microsoft partners. New controls and larger rebuilds sit with our PCF controls development service.

What do people ask us?

Why is my PCF control broken on a mobile phone in Dynamics 365?

Usually because it was built against a desktop width and does not react to the space the host allocates. Call context.mode.trackContainerResize(true) in init, lay out against context.mode.allocatedWidth in updateView, handle -1 values, and remove fixed pixel widths and min-width on tables. If it renders but cannot be used, check touch target sizes and nested scroll areas that block the form from scrolling.

Why does context.mode.allocatedWidth return -1?

A value of -1 means the size is not being reported for that dimension, either because the control did not call context.mode.trackContainerResize(true) in init or because the host does not constrain it. Height is often unconstrained on model-driven forms, since sections grow with content. Treat -1 as unconstrained, fall back to your own root element size for width, and never use it directly in a calculation.

Does updateView run when the screen rotates or the container resizes?

When the control has called context.mode.trackContainerResize(true), the host calls updateView when the allocated size changes, which includes rotation and form reflow. updateView also runs for property changes and dataset loads, so compare the new width with the last one and keep the resize path cheap: update layout state, do not reload data or recreate library instances.

Should I use CSS media queries in a PCF control?

Not for the control's main layout. Media queries respond to the whole viewport, while a PCF control lives in a section that can be much narrower than the screen, including on desktop. Lay out from allocatedWidth, use a ResizeObserver or CSS container queries on the control root for internal layout where the host browser supports them, and scope all styles to the control.

How do I detect whether a PCF control is running on a phone?

context.client.getFormFactor() returns the form factor the app is running as, such as desktop, tablet or phone. Use it to choose an interaction pattern, for example a card list instead of a wide editable grid, and keep using the allocated width for visual layout within that pattern, because a desktop form can also give the control a narrow column.

Why can users not scroll the form when their finger is on my PCF control?

The control is capturing the gesture. Common causes are a fixed-height inner area with its own vertical scroll, touch listeners that call preventDefault across the whole control, and maps or canvases that pan on any touch. Let the control grow with content on narrow layouts, limit gesture handling to the element that needs it, and use touch-action and overscroll-behavior to leave vertical scrolling to the form.

Is testing in a narrow browser window enough for mobile?

No. It is a useful first pass for layout, but it does not reproduce the Power Apps mobile app shell, real touch input, the on-screen keyboard, rotation, slower devices or the allocations each form placement produces. Test the real form in the mobile app on iOS and Android devices as a user with the production role, and record app and OS versions with the results.

Which solution is right for your business?

Tell us what you need. A senior consultant replies within one business day with a recommendation - Dynamics 365, Power Platform, or a custom-built CRM - not a sales script.