Jetpack Compose Spacer

If you've ever built a layout in Jetpack Compose and needed a clean, predictable gap between two elements, the Jetpack Compose's Spacer composable is the tool for the job. The Jetpack Compose Spacer is a dedicated empty layout element whose only purpose is to take up space, and once you understand how Jetpack Compose's Spacer works, adding consistent gaps to a Row, a Column, or a Box becomes almost effortless. A Jetpack Compose Spacer doesn't draw anything and doesn't hold any content of its own — it simply reserves room, which makes the Jetpack Compose's Spacer one of the most predictable spacing tools available to developers working anywhere in the Jetpack ecosystem.

In this blog, you'll learn exactly what the Jetpack Compose Spacer composable does, how to size a Jetpack Compose's Spacer with different modifiers, how to make a Jetpack Compose Spacer flexible so it grows to fill leftover space, and how the Jetpack Compose's Spacer fits into a real layout. Every example below is self-contained, so you can paste it straight into an online Kotlin compiler that supports Jetpack Compose and see the Jetpack Compose Spacer composable in action.

What Is the Jetpack Compose Spacer Composable

The Jetpack Compose's Spacer composable is a function that Compose provides specifically to create blank space in a layout. Unlike Row, Column, or Box, the Jetpack Compose Spacer does not accept a content lambda — it has nothing to draw and nothing to arrange. The entire job of a Jetpack Compose's Spacer is described by a single parameter, and Jetpack's own layout composables all follow this same modifier-driven sizing convention.

Here's the basic signature of the Jetpack Compose Spacer composable:

kotlin
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

@Composable
fun BasicSpacerExample() {
    Spacer(modifier = Modifier.width(24.dp))
}

When this code runs, Compose creates an invisible layout node that occupies twenty four density-independent pixels of horizontal space and nothing else. Notice that the Jetpack Compose's Spacer takes only one parameter, modifier, and that parameter defaults to Modifier with no size at all. That detail matters: a Jetpack Compose Spacer with no size modifier attached collapses to zero width and zero height, so it becomes invisible and has no effect on your layout. Every time you reach for a Jetpack Compose's Spacer, pair it with a sizing modifier such as width, height, or size, otherwise the empty space composable does nothing. Whichever spacer modifier you choose, Compose measures it during the same layout pass as every other child.

Adding Horizontal Space With Modifier.width

The most common place to use a Jetpack Compose horizontal spacer is inside a Row, where elements sit side by side and you want a consistent gap between them. Modifier.width tells the Jetpack Compose Spacer exactly how wide that gap should be, measured in dp.

kotlin
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

@Composable
fun HorizontalSpacerRow() {
    Row {
        Text("Username")
        Spacer(modifier = Modifier.width(16.dp))
        Text("Password")
    }
}

Running this composable places two text labels in a horizontal row with a fixed sixteen dp gap sitting between them. Because the Jetpack Compose horizontal spacer only defines a width, Compose ignores its height inside a Row — the row's own height still comes from its tallest child. This is why a Jetpack Compose's Spacer sized with width is the natural choice whenever you're laying out icons, buttons, or labels next to each other and want the same visual rhythm every time. This mirrors how every other Jetpack layout primitive expects size to be declared through a modifier rather than a parameter.

Adding Vertical Space With Modifier.height

Flip the scenario around and you get the Jetpack Compose vertical spacer pattern, which is used inside a Column to separate stacked elements. Instead of width, attach Modifier.height to the Jetpack Compose Spacer.

kotlin
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

@Composable
fun VerticalSpacerColumn() {
    Column {
        Text("Order confirmed")
        Spacer(modifier = Modifier.height(20.dp))
        Text("Your items will ship within two business days")
    }
}

This snippet stacks two lines of text with twenty dp of vertical breathing room between them. A Jetpack Compose vertical spacer behaves the same way as its horizontal counterpart, just on the opposite axis — inside a Column, the Jetpack Compose's Spacer's height reserves the gap while its width is effectively ignored because a Column measures each child's own width separately. Developers reach for a Jetpack Compose Spacer constantly when building forms, cards, and list items where text needs consistent vertical rhythm instead of being crammed together. Jetpack's Column and Row share this same measurement model, which keeps spacing behavior predictable across both axes.

Sizing a Spacer in Both Directions With Modifier.size

Sometimes a gap needs both a width and a height, especially inside a Box where children can overlap in two dimensions. Modifier.size lets a single call configure both measurements on a Jetpack Compose's Spacer at once.

kotlin
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

@Composable
fun BoxedSpacerExample() {
    Box {
        Spacer(modifier = Modifier.size(width = 40.dp, height = 40.dp))
    }
}

Modifier.size accepts either a single dp value that applies to both dimensions, or separate width and height arguments like the example above. This gives the Jetpack Compose Spacer a fixed forty by forty dp footprint, which is handy when reserving room for something that loads later, like an image or an avatar placeholder, without the surrounding layout jumping around once that content appears. Jetpack's Box composable measures children independently on both axes, which is exactly why a two-dimensional size call is necessary here.

Creating a Flexible Jetpack Compose Spacer With Modifier.weight

So far every Jetpack Compose's Spacer has had a fixed size, but a Jetpack Compose Spacer becomes far more powerful when paired with the weight modifier inside a Row or Column. A weighted Jetpack Compose's Spacer doesn't reserve a fixed number of dp — instead, it expands to consume whatever space is left over after every other sibling has been measured.

kotlin
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier

@Composable
fun WeightedSpacerRow() {
    Row(modifier = Modifier.fillMaxWidth()) {
        Text("Left label")
        Spacer(modifier = Modifier.weight(1f))
        Text("Right label")
    }
}

Because the spacer weight modifier claims all of the remaining horizontal space, "Left label" gets pushed to the start of the row and "Right label" gets pushed all the way to the end, with the Jetpack Compose Spacer invisibly stretching between them. This only works inside a RowScope or ColumnScope, since weight is an extension function defined on those scopes rather than on Modifier generally. Nest two weighted Jetpack Compose's Spacer elements around a single element and that element ends up centered, because each spacer weight modifier claims an equal share of the leftover room on either side. Jetpack introduced the weight modifier specifically to solve proportional space distribution without manual pixel math.

Practical Use Case: Jetpack Compose Spacer Width Height in a Toolbar Row

Let's put several of these ideas together in a scenario you'll run into constantly: a toolbar that needs a title on the left, a flexible gap in the middle, and an action icon fixed to the right. Working out the Jetpack Compose Spacer width height combination for a layout like this is a great way to see the Jetpack Compose's Spacer earning its keep.

kotlin
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

@Composable
fun ToolbarWithSpacer() {
    Row(
        modifier = Modifier.fillMaxWidth().padding(12.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        Text("Dashboard")
        Spacer(modifier = Modifier.weight(1f))
        Icon(imageVector = Icons.Filled.Settings, contentDescription = "Settings")
        Spacer(modifier = Modifier.width(12.dp))
    }
}

This toolbar uses two Jetpack Compose Spacer elements doing two different jobs. The first is a weighted Jetpack Compose's Spacer that pushes the settings icon to the far end of the row, while the second is a small fixed-width Jetpack Compose Spacer that keeps the icon from sitting flush against the row's edge. Combining a flexible Jetpack Compose's Spacer with a fixed-size Jetpack Compose Spacer in the same layout is an extremely common pattern once you start building real toolbars, headers, and list rows. Patterns like this show up constantly across real Jetpack-based Android apps, from settings screens to dashboards.

Other Ways to Size and Use a Jetpack Compose Spacer

Beyond width, height, size, and weight, a handful of smaller details are worth knowing about the Jetpack Compose's Spacer that don't each need their own section.

  • Design system spacing scale: most teams don't pick random dp values for every Jetpack Compose Spacer — they standardize on a small scale like 4.dp, 8.dp, 16.dp, and 24.dp so spacing stays consistent across the whole app.
  • Multiple spacers in one container: nothing stops you from placing several Jetpack Compose's Spacer elements of different sizes inside the same Row or Column when different pairs of elements need different amounts of compose layout spacing.
  • Spacer versus a padding modifier: a padding modifier adds space around an existing element, while a Jetpack Compose Spacer is its own separate empty element sitting between two others — reach for a Jetpack Compose's Spacer when the gap itself needs to be independently sized or made flexible with weight.
  • Compose ui gap for equal distribution: pairing a fixed Jetpack Compose Spacer with a weighted one, as shown in the toolbar example, is how many layouts create an equal compose ui gap on either side of a centered element without hardcoding pixel math.
  • Where the spacing scale comes from: Jetpack's Material Design guidelines are actually where most of these dp spacing conventions originate.
kotlin
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

@Composable
fun MultipleSpacersExample() {
    Column {
        Text("Step 1: Enter details")
        Spacer(modifier = Modifier.height(8.dp))
        Text("Step 2: Confirm order")
        Spacer(modifier = Modifier.height(24.dp))
        Text("Step 3: Track shipment")
    }
}

This column shows two different dp spacing Jetpack Compose values in the same layout: a tight eight dp gap between closely related steps, and a wider twenty four dp gap before the final step to visually group the first two together. Stacking several sized Jetpack Compose's Spacer elements like this is one of the simplest ways to build a sense of visual hierarchy without touching padding on any individual text element.

Comparing the Jetpack Compose Spacer Modifiers Side by Side

ModifierAxis affectedTypical containerBehavior
Modifier.width(dp)Horizontal onlyRowReserves a fixed horizontal gap
Modifier.height(dp)Vertical onlyColumnReserves a fixed vertical gap
Modifier.size(dp)BothBoxReserves a fixed width and height together
Modifier.weight(f)Whichever axis the parent lays out onRow or ColumnExpands to fill all remaining leftover space

Each row in this table maps to one of the sizing approaches a Jetpack Compose Spacer supports, and picking the right one usually comes down to whether an android compose spacer example needs a fixed gap or a flexible one that adapts to the available room. Jetpack has kept these four modifiers stable across every stable release, so the table above holds regardless of version.

Complete Working Example

Here's a full, self-contained example that combines a fixed vertical Jetpack Compose's Spacer, a fixed horizontal Jetpack Compose Spacer, and a weighted Jetpack Compose's Spacer inside one small profile card layout, so you can see the Jetpack Compose Spacer composable handling several jobs at once.

kotlin
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MaterialTheme {
                Surface {
                    ProfileCardWithSpacers()
                }
            }
        }
    }
}

@Composable
fun ProfileCardWithSpacers() {
    Column(modifier = Modifier.fillMaxWidth().padding(16.dp)) {
        Text("Jordan Lee")
        Spacer(modifier = Modifier.height(4.dp))
        Text("Product Designer")
        Spacer(modifier = Modifier.height(20.dp))
        Row(
            modifier = Modifier.fillMaxWidth(),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text("Followers: 128")
            Spacer(modifier = Modifier.weight(1f))
            Text("Following")
            Spacer(modifier = Modifier.width(8.dp))
            Text("54")
        }
    }
}

When this activity runs, the name and job title stack with a small four dp gap between them, a larger twenty dp gap separates that block from the stats row below, and inside the stats row a weighted Jetpack Compose's Spacer pushes the follower count to one side and the following count to the other while a small eight dp Jetpack Compose Spacer keeps the two numbers from touching. Together these three spacers show how a single Jetpack Compose's Spacer composable, sized in three different ways, handles nearly every spacing job in a Compose layout. Building layouts this way is a good example of the composition-first mindset Jetpack encourages throughout its libraries.