DEV Community

Cover image for How to Create Horizontal Scroll & Freeze Pane in PowerApps Canvas
Vũ Xuân Hải
Vũ Xuân Hải

Posted on

How to Create Horizontal Scroll & Freeze Pane in PowerApps Canvas

How to Create Horizontal Scroll & Freeze Pane in PowerApps Canvas

Hi everyone,

Last week, I suddenly wanted to create a freeze pane in PowerApps Canvas to show my data, and guess what? I cannot find any solution in Youtube or any blogs that I want. So I think why should I create one to should anyone else who want the samething with me. So today I’d like to share how to build a PowerApps Canvas screen that mimics the Freeze Pane behavior in Excel while also supporting horizontal scrolling when you have many columns in your data table.


I. What is Freeze Pane?

In Excel, Freeze Pane is a feature that allows you to lock the first row and/or first column of a table. This way, the headers or key columns remain visible as you scroll.

PowerApps doesn’t provide this feature out of the box, but we can replicate it using a combination of layout containers and controls.

Image description

II. Creating a Table in PowerApps

The most common way to display tabular data in PowerApps is by using the Gallery control. There are three types of galleries:

  • Vertical gallery
  • Horizontal gallery
  • Flexible height vertical gallery

In this guide, we’ll use the Vertical Gallery, which is ideal for structured table-style layouts.

Image description


III. The Problem with Many Columns

When your dataset has many columns, some controls (like The blue column in below pic) may overflow the visible area and won’t be displayed.

Image description
A common approach is to wrap all gallery items inside a horizontal container and set its OverflowX to Scroll.

However, this results in each gallery item having its own independent scroll bar, which is not ideal from a user experience standpoint.

Image description

IV. Proper Horizontal Scrolling Using a Slider

Instead of scrolling each item individually, a better approach is to place all the columns inside a container and control its X position with a shared Slider. This ensures all rows are scrolled in sync.

What the user sees in the gallery is the area defined by X:0, Y:0 to TemplateWidth:TemplateHeight. So, if a component inside the gallery is positioned outside of this visible area, it won't be shown to the user.

We can take advantage of this behavior by hiding the leftmost columns (placing them outside the visible area), allowing more space to show additional columns on the right.

Image description

Sample setup:

V. Implementing Freeze Pane

To mimic the Freeze Pane behavior, we need to fix two things:

1. Freeze First Column

  • Move the first column out of the horizontally scrollable container but still in the gallery row.
  • Position it on the left of the row, fixed position.
  • Update the scrollable container's X property as follows:
X = lblFreezeColumn.Width - Slider1.Value
Enter fullscreen mode Exit fullscreen mode

With lblFreeColumn is the column that you moved out of the container. With this, your table have a fixed column and can horizontal scroll other columns

2. Add Header Row

Our table needs to have a header. This is quite simple:

  • Create a separate container for the header row above the gallery.
  • Copy components from the gallery to that container. You will get some errors if you reference some gallery contexts; just replace that to remove issues.

Image description

VI. Making the Slider Look Like a Native Scrollbar

The default Slider control in PowerApps doesn't look or behave like a native scrollbar, which may create UI inconsistency. Here’s a trick to replicate a scrollbar experience using scrollable containers.

Steps:

  1. Add a horizontal container below the gallery.

    • Set its Height to 12px.
  2. Inside this container, add another horizontal container:

    • Also set its Height to 12px.
    • Set its OverflowX property to Scroll.
  3. Name the inner container something like `conHorizontalScroll`.

  4. Set the Width of conHorizontalScroll to:

   = conScrollableColumnsTitle.Width + 12
Enter fullscreen mode Exit fullscreen mode
  1. Wherever you're currently using -Slider1.Value to control horizontal movement, replace it with:
    +conHorizontalScroll.X
Enter fullscreen mode Exit fullscreen mode

Why Does This Work?

In PowerApps, when a container is scrollable (either horizontal or vertical), its child elements' X and Y values automatically shift in the opposite direction of the scroll.

This means you can directly use the changing X position of a child element as a scroll reference—no need for a separate slider.

This method gives you better control over the scroll experience and integrates more cleanly with the app’s UI.
The code:

Screens:
  Freeze Pane Screen:
    Properties:
      Fill: =RGBA(255, 255, 255, 1)
      LoadingSpinnerColor: =RGBA(0, 120, 212, 1)
    Children:
      - Container3:
          Control: GroupContainer@1.3.0
          Variant: AutoLayout
          Properties:
            Height: =Parent.Height
            LayoutDirection: =LayoutDirection.Vertical
            LayoutGap: =12
            Width: =Parent.Width
          Children:
            - Header1:
                Control: Header@0.0.44
                Properties:
                  Fill: =RGBA(214, 221, 224, 1)
                  Logo: ='powerapp-2020-icon-1024x1024-1'
                  Style: ='Header.Style'.Neutral
                  Title: ="AWESOME APPLICATION    "
            - conMainGal:
                Control: GroupContainer@1.3.0
                Variant: AutoLayout
                Properties:
                  LayoutDirection: =LayoutDirection.Vertical
                Children:
                  - conTitle:
                      Control: GroupContainer@1.3.0
                      Variant: ManualLayout
                      Properties:
                        FillPortions: =0
                        Height: =60
                      Children:
                        - conScollColumns_Title:
                            Control: GroupContainer@1.3.0
                            Variant: AutoLayout
                            Properties:
                              BorderColor: =RGBA(214, 221, 224, 1)
                              BorderThickness: =1
                              Height: =60
                              LayoutDirection: =LayoutDirection.Horizontal
                              RadiusBottomLeft: =0
                              RadiusBottomRight: =0
                              RadiusTopLeft: =0
                              RadiusTopRight: =0
                              Width: =3000
                              X: =conFreezeColumnsTitle.Width + conHorizonScroll.X
                              Y: =1
                            Children:
                              - TextCanvas3_3:
                                  Control: Text@0.0.51
                                  Properties:
                                    Align: ='TextCanvas.Align'.Center
                                    AlignInContainer: =AlignInContainer.Stretch
                                    Fill: =RGBA(166, 215, 153, 1)
                                    FillPortions: =1
                                    Size: =18
                                    Text: ="Sample Text"
                                    VerticalAlign: =VerticalAlign.Middle
                                    Weight: ='TextCanvas.Weight'.Semibold
                              - TextCanvas3_4:
                                  Control: Text@0.0.51
                                  Properties:
                                    Align: ='TextCanvas.Align'.Center
                                    AlignInContainer: =AlignInContainer.Stretch
                                    Fill: =RGBA(255, 184, 174, 1)
                                    FillPortions: =1
                                    Size: =18
                                    Text: ="Sampleling Text"
                                    VerticalAlign: =VerticalAlign.Middle
                                    Weight: ='TextCanvas.Weight'.Semibold
                              - TextCanvas3_6:
                                  Control: Text@0.0.51
                                  Properties:
                                    Align: ='TextCanvas.Align'.Center
                                    AlignInContainer: =AlignInContainer.Stretch
                                    Fill: =RGBA(180, 214, 250, 1)
                                    FillPortions: =1
                                    Size: =18
                                    Text: ="Sampleling Text"
                                    VerticalAlign: =VerticalAlign.Middle
                                    Weight: ='TextCanvas.Weight'.Semibold
                              - TextCanvas3_8:
                                  Control: Text@0.0.51
                                  Properties:
                                    Align: ='TextCanvas.Align'.Center
                                    AlignInContainer: =AlignInContainer.Stretch
                                    Fill: =RGBA(156, 99, 207, 0.9)
                                    FillPortions: =1
                                    Size: =18
                                    Text: ="Sampleling Text"
                                    VerticalAlign: =VerticalAlign.Middle
                                    Weight: ='TextCanvas.Weight'.Semibold
                              - TextCanvas3_9:
                                  Control: Text@0.0.51
                                  Properties:
                                    Align: ='TextCanvas.Align'.Center
                                    AlignInContainer: =AlignInContainer.Stretch
                                    Fill: =RGBA(180, 214, 250, 1)
                                    FillPortions: =1
                                    Size: =18
                                    Text: ="Sampleling Text"
                                    VerticalAlign: =VerticalAlign.Middle
                                    Weight: ='TextCanvas.Weight'.Semibold
                        - conFreezeColumnsTitle:
                            Control: GroupContainer@1.3.0
                            Variant: AutoLayout
                            Properties:
                              BorderColor: =RGBA(214, 221, 224, 1)
                              BorderThickness: =1
                              Fill: =RGBA(174, 208, 221, 1)
                              Height: =60
                              LayoutDirection: =LayoutDirection.Horizontal
                              RadiusBottomLeft: =0
                              RadiusBottomRight: =0
                              RadiusTopLeft: =0
                              RadiusTopRight: =0
                              Y: =1
                            Children:
                              - TextCanvas3_5:
                                  Control: Text@0.0.51
                                  Properties:
                                    Align: ='TextCanvas.Align'.Center
                                    AlignInContainer: =AlignInContainer.Stretch
                                    FillPortions: =1
                                    Size: =18
                                    Text: ="Title"
                                    VerticalAlign: =VerticalAlign.Middle
                                    Weight: ='TextCanvas.Weight'.Semibold
                  - galMainGal:
                      Control: Gallery@2.15.0
                      Variant: Vertical
                      Properties:
                        BorderColor: =RGBA(245, 245, 245, 1)
                        Items: =Table(CustomGallerySample,CustomGallerySample,CustomGallerySample)
                        TemplatePadding: =0
                        TemplateSize: =100
                      Children:
                        - conScollColumns:
                            Control: GroupContainer@1.3.0
                            Variant: AutoLayout
                            Properties:
                              BorderColor: =RGBA(214, 221, 224, 1)
                              BorderThickness: =1
                              Height: =Parent.TemplateHeight
                              LayoutDirection: =LayoutDirection.Horizontal
                              RadiusBottomLeft: =0
                              RadiusBottomRight: =0
                              RadiusTopLeft: =0
                              RadiusTopRight: =0
                              Width: =conScollColumns_Title.Width
                              X: =500 + conHorizonScroll.X
                            Children:
                              - TextCanvas3_1:
                                  Control: Text@0.0.51
                                  Properties:
                                    Align: ='TextCanvas.Align'.Center
                                    AlignInContainer: =AlignInContainer.Stretch
                                    Fill: =RGBA(166, 215, 153, 1)
                                    FillPortions: =1
                                    Text: =ThisItem.SampleText
                                    VerticalAlign: =VerticalAlign.Middle
                              - TextCanvas3_2:
                                  Control: Text@0.0.51
                                  Properties:
                                    Align: ='TextCanvas.Align'.Center
                                    AlignInContainer: =AlignInContainer.Stretch
                                    Fill: =RGBA(255, 184, 174, 1)
                                    FillPortions: =1
                                    Text: =ThisItem.SampleHeading &" " & ThisItem.SampleText
                                    VerticalAlign: =VerticalAlign.Middle
                              - TextCanvas3_7:
                                  Control: Text@0.0.51
                                  Properties:
                                    Align: ='TextCanvas.Align'.Center
                                    AlignInContainer: =AlignInContainer.Stretch
                                    Fill: =RGBA(180, 214, 250, 1)
                                    FillPortions: =1
                                    Text: =ThisItem.SampleHeading &" " & ThisItem.SampleText
                                    VerticalAlign: =VerticalAlign.Middle
                              - TextCanvas3_10:
                                  Control: Text@0.0.51
                                  Properties:
                                    Align: ='TextCanvas.Align'.Center
                                    AlignInContainer: =AlignInContainer.Stretch
                                    Fill: =RGBA(156, 99, 207, 0.9)
                                    FillPortions: =1
                                    Text: ="Sampleling Text"
                                    VerticalAlign: =VerticalAlign.Middle
                                    Weight: ='TextCanvas.Weight'.Regular
                              - TextCanvas3_11:
                                  Control: Text@0.0.51
                                  Properties:
                                    Align: ='TextCanvas.Align'.Center
                                    AlignInContainer: =AlignInContainer.Stretch
                                    Fill: =RGBA(180, 214, 250, 1)
                                    FillPortions: =1
                                    Text: ="Sampleling Text"
                                    VerticalAlign: =VerticalAlign.Middle
                                    Weight: ='TextCanvas.Weight'.Regular
                        - conFreezeColumns:
                            Control: GroupContainer@1.3.0
                            Variant: AutoLayout
                            Properties:
                              BorderColor: =RGBA(214, 221, 224, 1)
                              BorderThickness: =1
                              Fill: =RGBA(174, 208, 221, 1)
                              Height: =Parent.TemplateHeight
                              LayoutDirection: =LayoutDirection.Horizontal
                              RadiusBottomLeft: =0
                              RadiusBottomRight: =0
                              RadiusTopLeft: =0
                              RadiusTopRight: =0
                              Width: =conFreezeColumnsTitle.Width
                            Children:
                              - TextCanvas3:
                                  Control: Text@0.0.51
                                  Properties:
                                    Align: ='TextCanvas.Align'.Center
                                    AlignInContainer: =AlignInContainer.Stretch
                                    FillPortions: =1
                                    Text: =ThisItem.SampleHeading
                                    VerticalAlign: =VerticalAlign.Middle
                  - Container10:
                      Control: GroupContainer@1.3.0
                      Variant: AutoLayout
                      Properties:
                        FillPortions: =0
                        Height: =12
                        LayoutDirection: =LayoutDirection.Vertical
                        LayoutOverflowX: =LayoutOverflow.Scroll
                      Children:
                        - conHorizonScroll:
                            Control: GroupContainer@1.3.0
                            Variant: AutoLayout
                            Properties:
                              AlignInContainer: =AlignInContainer.Start
                              FillPortions: =0
                              Height: =12
                              LayoutDirection: =LayoutDirection.Horizontal
                              LayoutMinWidth: =2000
                              Width: =conFreezeColumnsTitle.Width + conScollColumns_Title.Width + 12
Enter fullscreen mode Exit fullscreen mode

So that's how to make a freeze pane in PowerApps Canvas. If you would like to get notified every new blog, you can subscribe below.

Top comments (0)