Row & Column

Row and Column are the most fundamental layout widgets. They allow you to arrange multiple child widgets in a flexible way, either horizontally or vertically. Mastering them is the key to building almost any user interface.
The Row widget arranges its children horizontally.
The Column widget arranges its children vertically.
Core Concepts
1. Main Axis vs. Cross Axis
The core concept to understand when working with Row
and Column
is the axis direction:
Main Axis: The primary direction of arrangement. For a Row, it's horizontal. For a Column, it's vertical.
Cross Axis: The direction perpendicular to the main axis. For a Row, it's vertical. For a Column, it's horizontal.
The Main and Cross axes for Row and Column widgets. All alignment and sizing properties operate based on these two axes.
2. Static vs. Dynamic Children
A Row
or Column
can be populated with widgets in two ways. You can add a fixed number of widgets individually in the builder (Static Children), or you can generate a list of widgets from a data source (Dynamic Children). This flexibility allows you to build both fixed layouts and data-driven, repeating lists.
Learn more about Static and Dynamic Children here.
Common Properties
The properties for Row
and Column
are identical and determine how their children are positioned and sized.
Main Axis Alignment
This property defines how the free space is distributed between children along the main axis.


Start
Places children at the beginning of the main axis.
Center
Places children in the middle of the main axis.
End
Places children at the end of the main axis.
Space Between
Distributes children evenly, with no space at the start or end.
Space Around
Distributes children evenly, with half the spacing at the start and end as between them.
Space Evenly
Distributes children with equal spacing between all items, including at the start and end.
Cross Axis Alignment
This property defines how children are positioned relative to each other along the cross axis.


Start
Aligns children to the beginning of the cross axis.
Center
Aligns children to the center of the cross axis.
End
Aligns children to the end of the cross axis.
Stretch
Stretches each child to fill the available space along the cross axis.
Main Axis Size
This property determines how much space the Row
or Column
should occupy along its main axis.

Max
fills available space, while Min
shrinks to fit its children.Max
The widget expands to fill all available space along its main axis. This is the default.
Min
The widget shrinks to fit the combined size of its children along the main axis.
Scrollable
If the content of a Row
or Column
exceeds its available space, enabling the Scrollable
property will allow users to scroll through the content. This is essential for creating scrollable lists or carousels.
Spacing
These properties allow you to add fixed spacing along the main axis, offering an alternative to using Main Axis Alignment
for space distribution.

Item Spacing
The amount of empty space to place between each child widget along the main axis.
Start Spacing
The amount of empty space to place before the first child widget along the main axis.
End Spacing
The amount of empty space to place after the last child widget along the main axis.
Children: Static vs. Dynamic
You can populate a Row
or Column
with child widgets in two ways:
1. Static Children
Add a fixed number of child widgets directly in the builder. Each child you add will appear in the widget tree, and its properties can be configured individually. This is ideal for layouts where the number of items is known and doesn't change.
2. Dynamic Children
To generate children from a list of data, you can use the Data Source
property. This turns the Row
or Column
into a powerful list builder.
Enable the
Data Source
toggle in the properties panel.Provide data by either entering a fixed
JsonArray
in the JSON editor or binding it to an expression that returns aJsonArray
(e.g., from an API call or App State).Add a single child widget to the
Row
orColumn
. This widget acts as a template that will be repeated for each item in the data source.Inside this template child, use the
currentItem
variable to access the data for each item.If your data is a list of objects (e.g.,
[{"name": "Apple"}, {"name": "Banana"}]
), access properties with dot notation:${currentItem.name}
.If your data is a list of simple values (e.g.,
["Apple", "Banana"]
),currentItem
refers to the value itself:${currentItem}
.
This is perfect for building small, repeating UI elements like a row of filter chips, a list of user avatars, or a set of feature icons.
Important Note on Performance
While enabling Scrollable
on a Row
or Column
with dynamic children works, it is not optimized for long or infinite lists. The Row
and Column
widgets build all their children at once, which can cause performance issues with large datasets.
For displaying long, scrollable lists of data, it is highly recommended to use the ListView or GridView widgets, as they are specifically designed to build items lazily as they scroll into view.
Controlling Child Size: Expanded & Flexible
When you have static children inside a Row
or Column
, you can control how they occupy the remaining space along the main axis. After placing children, you can find the Children Flex section in the properties panel of the Row
or Column
itself. Here, you can individually configure the expansion type for each child.
Expansion Types
Expanded
Tight
Forces the child to fill all remaining empty space along the main axis. If multiple children are set to Tight
, the space is divided according to their Flex Value
.
Flexible
Loose
Allows the child to expand into the remaining space, but does not force it to. The child will grow no larger than its flex value allows, but can be smaller if its content is smaller.
None
None
The child takes up only its intrinsic (natural) size. It will not be expanded or flexed. This is the default.
Flex Value
When you set a child's expansion Type
to Loose
or Tight
, the Flex Value
(a number) determines its share of the remaining space relative to its siblings.
A child with
Flex Value: 2
will take up twice as much space as a sibling withFlex Value: 1
.If all expanded children have
Flex Value: 1
, they will share the space equally.A child with
Flex Value: 2
will take up twice as much space as a sibling withFlex Value: 1
.If all expanded children have
Flex Value: 1
, they will share the space equally.
Expanded vs. Flexible: A Deeper Dive
While both Expanded
and Flexible
use the Flex Value
to claim a share of the remaining space, their behavior is fundamentally different. Understanding this difference is crucial for mastering layouts.
The Key Difference: Forcing vs. Allowing
Expanded (
Tight
) forces a child to fill the space. It's a rigid rule. The child's own intrinsic size is ignored, and it expands to occupy the full share of remaining space defined by itsFlex Value
.Flexible (
Loose
) allows a child to fill the space. It's a flexible rule. The child can grow up to its share of the remaining space, but if its content is smaller, it will only take up the space it needs.
Here’s a summary of what each can do that the other cannot:
Feature
Expanded (Tight
)
Flexible (Loose
)
Behavior
Forces the child to fill its share of remaining space.
Allows the child to fill its share of remaining space, but doesn't force it.
Sizing
The child's size is determined by the Flex Value
and remaining space. Its own content size is ignored.
The child's size is the smaller of its content size and its allocated flex space.
What it can do
Force a small widget (like an icon) to grow and occupy a large area.
Allow a widget to be smaller than its potential flex space if its content doesn't need it.
When to Use Each
Use
Expanded
(Tight
) when:You need to divide the screen into proportional sections that always fill the available space (e.g., a 70/30 split for a main content area and a sidebar).
You want a specific widget to take up all the leftover space in a
Row
orColumn
, pushing other widgets to the edges.You are creating a layout where the components must stretch to fit, regardless of their content size.
Example: A
Row
with twoExpanded
children will always cause them to fill the full width of theRow
.Use
Flexible
(Loose
) when:You want a widget (like a
Text
widget) to have room to grow if its content is long, but you don't want to force it to be huge if the content is short.You have a widget with a natural size, but you want it to expand slightly if there's extra space, without taking over the layout.
You want to give a widget a "max-width" or "max-height" that is proportional to the remaining space.
Example: In a
Row
, aButton
withFlexible
will keep its normal size if there's no extra space, but will expand to fill some of the remaining space if theRow
is wider than its children.
Default Properties
The Row and Column widgets support all Default Properties, such as Visibility
, Padding
, Margin
, and Background Color
.
Last updated