Every Canvas Control Has Four Hidden Sizing Properties You Cannot See in Studio
And one of them explains why your container stops growing at a very specific number.
Open the property panel on any canvas control and count the sizing properties. X, Y, Width, Height. Four.
Open the control’s template and count again. There are eight.
<!-- Hidden properties -->
<appMagic:includeProperty name="minimumWidth" defaultValue="1" />
<appMagic:includeProperty name="minimumHeight" defaultValue="1" />
<appMagic:includeProperty name="maximumWidth" defaultValue="1366" />
<appMagic:includeProperty name="maximumHeight" defaultValue="7680" />
That is from the label control, under a comment Microsoft wrote itself: <!-- Hidden properties -->. Note the lowercase-first naming, which is the platform’s convention for properties outside the public surface.
They appear on all 15 of the classic controls we examined. Every one.
The values, control by control
| Control | min W | min H | max W | max H |
|---|---|---|---|---|
label | 1 | 1 | 1366 | 7680 |
htmlViewer | 35 | 35 | 1366 | 7680 |
groupContainer | 20 | 20 | 1366 | 7680 |
image | 1 | 1 | 1366 | 768 |
rectangle | 1 | 1 | 1366 | 768 |
circle | 1 | 20 | 1366 | 768 |
icon | 1 | 20 | 1366 | 768 |
gallery | 20 | 20 | 1366 | 768 |
button | 5 | 5 | 1366 | 768 |
timer | 5 | 5 | 1366 | 768 |
text | 10 | 30 | 1366 | 768 |
datepicker | 10 | 30 | 1366 | 768 |
combobox | 80 | 35 | 1366 | 768 |
attachments | 80 | 35 | 1366 | 768 |
fluidGrid | 20 | 20 | 600 | 300 |
Several things fall out of that table.
1366 is everywhere. It is the tablet layout width, and it is hard-coded as the maximum width of every control. Not derived from App.Width, not from the screen — a literal in the template.
7680 is the tall-container exemption. Three controls can exceed 768 in height: label, htmlViewer, and groupContainer. Those are exactly the three you would use to build a long scrolling page. Everything else — galleries included — is capped at 768, one screen height.
The gallery caps at 768. A gallery cannot be declared taller than one screen. This is why long lists scroll internally rather than extending the page, and it is a template constant, not a design guideline.
fluidGrid caps at 600 × 300. The most restrictive control in the library by a wide margin — less than half the screen in each dimension.
Minimums are why controls refuse to shrink. A combobox will not go below 80 × 35. Neither will an attachments control. Circles and icons have a 20px floor on height but a 1px floor on width. If you have ever dragged a resize handle and watched it stop, this table is the reason.
The phone variants are different, and stranger
Two controls override these caps for phone layout:
| Control | Tablet | Phone |
|---|---|---|
groupContainer | max 1366 × 7680 | max 640 × 11360 |
datepicker | max 1366 × 768 | max 640 × 1136 |
The phone container is allowed to be 11,360 pixels tall — 48% taller than its tablet equivalent, on the assumption that phone layouts are long vertical scrolls. Its width ceiling drops to 640.
The date picker’s phone ceiling of 640 × 1136 is precisely an iPhone 5 viewport at 2× density. That number was chosen a long time ago and never revisited.
The wider hidden-property inventory
Once you know to look for lowercase-first names and hidden="true", more surfaces. Across our 15 templates:
| Property | Where | What it looks like |
|---|---|---|
minimumWidth / minimumHeight / maximumWidth / maximumHeight | 15 controls | the sizing clamps above |
TemplateMaximumWidth | gallery | ceiling on the gallery template width |
MaxTemplateSize | gallery (new in 2026) | ceiling on template size |
HorizontalScrollPosition | gallery | readable scroll offset |
SelectionTracksMove | gallery | feeds Selected in the dependency graph |
Layout | gallery | hidden layout enum |
Reset | 3 controls | the reset trigger, hidden |
UsePhoneLayout | 2 controls | form-factor switch |
IsErrorMessage | label | deprecated, explicitly marked |
HideCalendar, CalendarCellHeight, CalendarWidth, DateFontSize, CalendarPlaceholderWidth, SelectedDateFill, HoverDateFill, CurrentDateFill, CalendarHeaderFill, MonthColor, WeekColor, DayColor | datepicker | twelve hidden calendar styling properties |
ChevronWidth, FlyoutMaximumHeight, MoreItemsButtonColor, SearchItems | combobox / gallery | sub-part styling |
OnNavigate, NavigateFields | gallery | hidden navigation hooks |
The date picker is the standout. Twelve hidden properties controlling the calendar popup — cell height, header fill, month/week/day text colours, selected and hover date fills. Every one of them is something people ask for on the community forums and are told is impossible.
The template carries a note about them, too:
<!-- RDBug 5136801:- Remove the hidden properties -->
An open bug to delete them. So they are not a secret API waiting to be unlocked; they are debt someone intends to clear.
The dependency graph is declared, not inferred
The same templates publish an explicit property dependency DAG:
<appMagic:propertyDependencies>
<appMagic:propertyDependency input="AutoHeight" output="Height" />
</appMagic:propertyDependencies>
The full set across our sample:
| Control | Dependencies |
|---|---|
label | AutoHeight → Height |
htmlViewer | AutoHeight → Height |
gallery | Items → AllItems, AllItemsCount, SelectedDefault → SelectedReset → SelectedSelectionTracksMove → SelectedTemplateSize → TemplateWidth, TemplateHeightAutoHeight → Height |
attachments | Items → AttachmentsDefault → AttachmentsReset → Attachments |
This is the formal answer to a question that comes up constantly: why can I not set Height when AutoHeight is on? Because AutoHeight is declared as an input to Height. The platform owns the output.
Same reason four separate inputs feed Selected on a gallery — Items, Default, Reset, and SelectionTracksMove — which is why gallery selection resets at moments that feel arbitrary. Any of those four changing invalidates it.
What you can actually do with this
The hidden properties are hidden. You cannot set them from a formula, and one group has an open bug requesting deletion. This is not a list of secret features.
It is a list of explanations, and those have practical value:
- Design within 1366 × 768 for anything that is not a label, an HTML viewer, or a container. That is where the clamps are.
- Long pages need containers, not tall galleries. Only three controls can exceed 768 in height, and
groupContaineris the one meant for layout. - Do not fight the minimums. A combobox below 80 × 35 is not going to happen.
- Do not fight
AutoHeight. It is declared as owningHeight. fluidGridis capped at 600 × 300. If you were planning to use it as a page-level layout primitive, that is your ceiling.
And if you write tooling that generates canvas apps: these clamps are the validation rules to enforce before publish, because the platform will enforce them afterwards.
Methodology
Sample: 15 classic control templates from two production .msapp exports (2023-02-14, 2026-02-16).
unzip -q app.msapp -d app/
python3 - <<'EOF'
import json, re
for t in json.load(open('app/References/Templates.json'))['UsedTemplates']:
out = []
for m in re.finditer(r'name="(minimum\w+|maximum\w+)"([^/>]*)', t['Template']):
dv = re.search(r'defaultValue="([^"]*)"', m.group(2))
ph = re.search(r'phoneDefaultValue="([^"]*)"', m.group(2))
out.append(f"{m.group(1)}={dv.group(1) if dv else '?'}"
+ (f" (phone {ph.group(1)})" if ph else ''))
if out: print(f"{t['Name']:<18}" + ' '.join(out))
EOF
Property names and values are quoted verbatim. Claims about how the clamps are enforced are inferred from the declarations plus observed editor behaviour — Microsoft does not document these, so treat the mechanism as well-evidenced and the enforcement path as inference.