Live Chat

We'll need to share your messages (and your email address if you're logged in) with our live chat provider, Drift. Here's their privacy policy.

If you don't want to do this, you can email us instead at


Some components can contain other components. We call these containers. (A Form is also a container.)

Five Label components in a ColumnPanel (with the Card Role)

Label components in a ColumnPanel with the Material Design Theme’s card Role applied.

The best way to see how each container behaves is to experiment - drop a container into a Form and drop several TextAreas into it. Play around and see how many ways you can arrange things.

Controlling Containers from code

You can add any component to a container in Python by calling the method add_component(component, container_properties…).

For example, the following code sets up an XYPanel that is 400x400 pixels, adds it to the current Form, and then adds two components to it:

xyp = XYPanel(width=400, height=400)

lbl = Label(text="Hello")
xyp.add_component(lbl, x=10, y=10)

btn = Button(text="Click me!")
xyp.add_component(btn, x=10, y=100)

To remove a component from its parent container, call its remove_from_parent() method.


Alternatively, you can remove all components from a particular container by calling clear() on the container:


To get a list of all components currently in the container, call get_components():

components = my_container.get_components()
print(f"{len(components)} components")

To raise an event on all children of a component without referencing the children directly, call raise_event_on_children():

my_container.raise_event_on_children("x-custom-event", foo=42)

For more on adding, removing and getting components within containers, see the Containers overview.

Container Properties

Container Properties are properties that control the relationship between a component and the container it is in; the argument names and their meanings are specific to the type of container. They are visible in the Properties panel in the Anvil Editor.

Container Properties are visible at the bottom
of the Properties Panel.

Container Properties are visible at the bottom
of the Properties Panel.

They can also be passed as keyword arguments to add_component. For example, Data Row Panels inside a Data Grid have a pinned property that determines whether the Data Row Panel is visible on every page of a paginated Data Grid:

self.data_grid_1.add_component(DataRowPanel(), pinned=True)

ColumnPanel ColumnPanel Toolbox icon

Properties | Events

This container allows you to drag and drop components into rows and columns. The ColumnPanel is the default layout for Anvil Forms.

Components added at runtime using the add_component method will each be added to their own row. In this respect, the ColumnPanel behaves the same as the LinearPanel at runtime. There are no special arguments to pass to add_component.

Like the LinearPanel, the ColumnPanel will expand to fit its contents.

Components in a ColumnPanel have several container properties, which can be set in the Properties dialog:

  • full_width_row: When True, this row of components will stretch to the full width of the screen. (Default: False)
  • row_background: Set to a CSS color for the background of this row. Note that the background stretches to the full with of the browser. (Default: None)
cp = ColumnPanel(background='yellow')

# Add a TextBox to the Column Panel and give it the full_width_row container property
cp.add_component(TextBox(text='enter some text', full_width_row=True))

FlowPanel FlowPanel Toolbox icon

Properties | Events

This container allows you to display components in lines with wrapping. Each component will only take up the horizontal space that it needs.

Some components, like Buttons, dictate their own width when placed inside FlowPanels, based on their content. For components like TextBoxes, that don’t have a width specified by their content, you can drag the handle to set the width you require.

fp = FlowPanel(align="center", spacing="small")

# A button determines its own width
fp.add_component(Button(text="Click me"))

# You set the width of a TextBox explicitly
fp.add_component(TextBox(), width=100)

If a component doesn’t fit on the same row as the previous component, it will wrap onto a new line.

To control the space between components, set the spacing property of the FlowPanel.

Like many other containers, the FlowPanel will expand vertically to fit its contents.

By default, components are added at the end of a FlowPanel. If you pass an index parameter to add_component(), the component will be inserted at the specified position. Index 0 is the first element in the panel, 1 is the second, etc.

fp = FlowPanel()
# Display the label to the left of the button:
fp.add_component(Label(text="Click here:"), index=0)

DataRowPanel DataRowPanel Toolbox icon

Properties | Events

For full documentation on the DataRowPanel, see the section on Data Grids

The DataRowPanel is a special Anvil container, designed to work inside the DataGrid component. In particular, DataRowPanels inherit the column-based layout of their parent DataGrids, so they can arrange their child components appropriately. There are two main features of DataRowPanels that differentiate them from other Anvil containers:

  • DataRowPanels have a ‘slot’ for each column of their parent Data Grid, meaning other Anvil components can be dropped into particular columns. They also behave like LinearPanels, in that components placed outside the column-specific slots will take up the full width of the container. This is useful for section headers and other advanced layouts.
  • DataRowPanels can automatically display data in the column-based layout of their parent DataGrid. This is done by setting the item property of the DataRowPanel to a dictionary with the same keys as the data_keys of the Data Grid columns.

For more information, see the documentation for the DataGrid component, or our DataGrid Tutorials

LinearPanel LinearPanel Toolbox icon

Properties | Events

This container arranges its child components vertically, each filling the whole width of the panel by default.

It doesn’t require any extra arguments for add_component: each component is added to the bottom of the LinearPanel.

lp = LinearPanel()
lp.add_component(Button(text="Click me"))

The LinearPanel will expand vertically to fit its contents.

By default, components are added at the end of a LinearPanel. If you add an index parameter to the add_component() call, the component will be added at that index. Index 0 is the first element in the panel, 1 is the second, etc.

# self.linear_panel_1 is a LinearPanel

# This label will be added above the Button.
lp.add_component(Label(text="Label"), index=0)

XYPanel XYPanel Toolbox icon

Properties | Events

This container allows its child components to be placed at a specific position inside the container. Positions are measured in pixels from the top-left of the panel. To help with positioning components, you can get the width of an XYPanel by calling the get_width() function.

Arguments to add_component:

  • x: How far across the component is from the left-hand edge
  • y: How far down the component is from the top edge
xy_panel = XYPanel(width=400, height=400)

btn = Button(text="Click me!")
xy_panel.add_component(btn, x=10, y=100)

GridPanel GridPanel Toolbox icon

Properties | Events

This container lays out components on a grid. Each row has twelve columns, and a component can span multiple columns. Components occupying the same columns in different rows will be aligned.

gp = GridPanel()

                 row="MyRow", col_xs=0, width_xs=2)

                 row="MyRow", col_xs=2, width_xs=6)

                 row="MyOtherRow", col_xs=3, width_xs=2)

Arguments to add_component:

  • row: The name of the row to which this component will be added. If this is the first component with this row name, a new row will be created at the bottom of the GridPanel.
  • col_xs: What’s the first column this component occupies? (0-11, default 0)
  • width_xs: How many columns does this component occupy? (1-12, default 12)
When adding multiple components to the same row of a GridPanel in code, components must be added left-to-right.