LazyRow in Jetpack Compose — what it is, properties and how it works

Author: IT Sectr Published: 2026-06-29 Reading time: 10 min

LazyRow — is a composable function in Jetpack Compose for creating horizontal lists with lazy loading of elements. Unlike Row, LazyRow creates only visible elements and reuses them during horizontal scrolling. According to Google Android Documentation, 2025, LazyRow is the horizontal counterpart of LazyColumn and is effective for carousels, galleries and horizontal menus in mobile applications.

Key Takeaways

  • LazyRow — a horizontal Jetpack Compose list with lazy loading, creating only visible elements during horizontal scrolling.
  • horizontalArrangement manages the horizontal positioning of elements, while contentPadding adds padding at the container edges.
  • LazyListState tracks the horizontal scroll position and provides programmatic control via animateScrollToItem.
  • LazyRow is efficient for image carousels, category lists, horizontal galleries and tabs in mobile interfaces.
  • contentType and key optimize element reuse in LazyRow, reducing recomposition during scrolling.

What is LazyRow in Jetpack Compose

LazyRow — is a composable function implementing a horizontal scrollable list with lazy loading of elements. Unlike Row, which renders all child elements simultaneously, LazyRow creates only elements visible in the viewport.

LazyRow works on the same principle as LazyColumn, but arranges elements horizontally. When scrolling left or right, elements that exit the viewport are reused to display new ones. This is critically important for galleries with many images or long category lists.

According to Android Developers Blog, 2024, LazyRow uses the same LazyList architecture as LazyColumn, including LazyListState, a reuse mechanism via Pool, and support for different element types. Maximum efficiency is achieved with fixed element height.

Basic LazyRow signature

LazyRow accepts parameters modifier, state, contentPadding, reverseLayout, horizontalArrangement and verticalAlignment. Content is defined via DSL functions items and item, similar to LazyColumn.

kotlin
@Composable
fun SimpleLazyRow() {
    val items = (1..50).toList()
    LazyRow(
        modifier = Modifier.fillMaxWidth().height(100.dp),
        horizontalArrangement = Arrangement.spacedBy(8.dp),
        contentPadding = PaddingValues(start = 16.dp, end = 16.dp)
    ) {
        items(items) { item ->
            Box(
                modifier = Modifier.size(80.dp).background(Color.Gray)
            ) {
                Text(text = "$item", modifier = Modifier.align(Alignment.Center))
            }
        }
    }
}

LazyRow properties: horizontalArrangement and contentPadding

horizontalArrangement manages the distribution of elements along the horizontal axis inside LazyRow. The same Arrangement values are available as in Row: Start, Center, End, SpaceBetween, SpaceEvenly, SpaceAround and spacedBy with custom spacing.

contentPadding adds padding at the edges of the LazyRow container. Unlike Modifier.padding, contentPadding is taken into account during scrolling: the first element will have padding from the left edge, the last — from the right edge. According to Material Design Guidelines, 2025, contentPadding is required for carousels and galleries so that the first and last elements do not stick to the screen edge.

verticalAlignment aligns elements vertically inside LazyRow. By default, Alignment.Top is used. To center elements of different heights, use Alignment.CenterVertically, which is useful for carousels with images of different aspect ratios.

LazyRow parameters table

ParameterDescriptionDefault value
horizontalArrangementHorizontal distribution of elementsArrangement.Start
contentPaddingPadding at container edgesPaddingValues(0.dp)
verticalAlignmentVertical alignmentAlignment.Top
reverseLayoutReverse element orderfalse
userScrollEnabledEnable user scrollingtrue

Horizontal scroll management with LazyListState

LazyListState for LazyRow works identically to LazyColumn: it tracks the first visible element, offset and overall scroll position. The state is created via rememberLazyListState() and passed to the state parameter.

Programmatic scroll control of LazyRow is done with the same methods: animateScrollToItem for smooth animation and scrollToItem for instant scrolling. Both are called inside a coroutine. This is useful for carousels with "Left/Right" buttons or for automatic scrolling.

According to Android Developers, 2024, LazyRow also supports SnapFlingBehavior — behavior for fast scrolling that stops at the nearest element rather than between elements. This creates a "snap" effect familiar to carousels and galleries.

kotlin
@Composable
fun CarouselWithSnap() {
    val listState = rememberLazyListState()
    val scope = rememberCoroutineScope()
    val items = listOf("A", "B", "C", "D", "E")

    Column {
        LazyRow(
            state = listState,
            flingBehavior = SnapFlingBehavior(listState),
            horizontalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            items(items) { item ->
                Card(modifier = Modifier.width(150.dp)) {
                    Text(text = item, modifier = Modifier.padding(16.dp))
                }
            }
        }

        Row(modifier = Modifier.fillMaxWidth()) {
            Button(onClick = {
                scope.launch {
                    listState.animateScrollToItem(0)
                }
            }) { Text("To start") }
        }
    }
}

Use cases of LazyRow in interfaces

The first example — LazyRow for an image gallery with previews. Each element is a Box with an image and a caption. LazyRow efficiently handles dozens and hundreds of images, loading only visible ones.

kotlin
@Composable
fun ImageGallery(images: List<String>) {
    LazyRow(
        contentPadding = PaddingValues(start = 16.dp, end = 16.dp),
        horizontalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        items(images, key = { it }) { url ->
            AsyncImage(
                model = url,
                contentDescription = "Image",
                modifier = Modifier.size(120.dp)
            )
        }
    }
}

The second example — LazyRow for a category list with icons. Categories are displayed as chips, and the user can scroll them horizontally. LazyRow with spacedBy and contentPadding creates spacing between categories and at the edges.

kotlin
@Composable
fun CategoryChips(categories: List<String>) {
    LazyRow(
        contentPadding = PaddingValues(horizontal = 16.dp),
        horizontalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        items(categories, key = { it }) { category ->
            AssistChip(
                onClick = {},
                label = { Text(category) }
            )
        }
    }
}

LazyRow vs Row: when to choose which

The choice between LazyRow and Row depends on the number of elements. Row is suitable for 5–10 elements that are always visible on screen. LazyRow is essential when there are many elements or their count is dynamic.

Row renders all elements at once, causing delays with a large number of elements. LazyRow renders only visible ones, making it preferable for scrollable lists. According to Android Developers Blog, 2024, the threshold is approximately 10 elements: if there are more elements, use LazyRow.

LazyRow also supports animations, SnapFlingBehavior and grouping via separators, making it more flexible for complex interfaces. Row is simpler and does not require LazyListState, but is not optimized for long lists.

  • Row — for 5–10 static elements without scrolling
  • LazyRow — for 10+ elements with horizontal scrolling
  • LazyRow — for carousels, galleries, dynamic lists

Frequently Asked Questions

How is LazyRow different from LazyColumn?

LazyRow scrolls horizontally and arranges elements left to right, while LazyColumn scrolls vertically top to bottom. Both use the same principles of lazy loading, LazyListState and DSL items functions.

How to add SnapFlingBehavior to LazyRow?

Pass SnapFlingBehavior(listState) to the flingBehavior parameter of LazyRow. SnapFlingBehavior forces LazyRow to stop at the nearest element rather than between elements, creating a snapping effect for carousels.

How to make LazyRow with infinite scrolling?

Track the last visible element via LazyListState.layoutInfo and load new data when the last element approaches the end of the list. For circular scrolling, use a custom implementation with element duplication.

Can LazyRow be used inside LazyColumn?

Yes, LazyRow can be nested inside LazyColumn. This is a standard pattern for creating complex pages with horizontal carousels inside a vertical list. Each LazyRow must have a fixed height for proper operation.

How to detect that LazyRow has scrolled to the end?

Use LazyListState.layoutInfo.visibleItemsInfo and compare the index of the last visible element with the total count minus one. When these values match, LazyRow is at the end of the list.

Summary

  • LazyRow — a horizontal list with lazy loading, creating only visible elements and reusing them during scrolling for efficient handling of large data.
  • horizontalArrangement manages horizontal distribution of elements, while contentPadding adds padding at the edges for correct Material Design display.
  • LazyListState provides programmatic scroll control via animateScrollToItem and supports SnapFlingBehavior for snapping to elements.
  • LazyRow is efficient for image carousels, galleries, category lists, tabs and horizontal menus in mobile interfaces.
  • contentType and key are the main optimization tools that reduce recomposition and improve element reuse in LazyRow.
  • Row is suitable for 5–10 static elements, LazyRow — for dynamic or long horizontal lists with scrolling.
  • LazyRow can be nested inside LazyColumn to create complex layouts with horizontal carousels inside a vertical list.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also