Frontend Development 8 min read

Implementing a Waterfall Layout with Flex in a Uni‑App

This article explains how to create a two‑column waterfall (masonry) layout in a Uni‑App using Flexbox, covering the visual design, CSS styling, data handling, dynamic loading, height calculation, and tab‑switch integration with complete code examples.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Implementing a Waterfall Layout with Flex in a Uni‑App

The author introduces a waterfall (masonry) layout, describing its characteristic uneven multi‑column appearance and continuous data loading as the page scrolls.

Using Flexbox, the layout is built with a parent <view class="blessing-con"> that distributes two child containers ( blessing-con-half ) side by side. The HTML structure is:

<view class="blessing-con">
<view class='blessing-con-half'>
<view id="leftHalf">
<view class="blessing-con-half-item" :class="bgColor[index % 3]" v-for="(item, index) in newBlessingWordsList1" :key="index">
<view class="item-con"></view>
</view>
</view>
</view>
<view class='blessing-con-half'>
<view id="rightHalf">
<view class="blessing-con-half-item" :class="bgColor[(index + 1) % 3]" v-for="(item, index) in newBlessingWordsList2" :key="index">
<view class="item-con"></view>
</view>
</view>
</view>
</view>

The accompanying CSS defines the flex container and item styles, for example:

.blessing-con {
padding: 32rpx 20rpx;
display: flex;
justify-content: space-between;
height: 1100rpx;
overflow-y: auto;
}
.blessing-con-half {
width: 320rpx;
height: 100%;
}
.blessing-con-half-item {
width: 100%;
display: flex;
flex-direction: column;
margin: 0 0 24rpx;
}

Data is stored in two arrays ( newBlessingWordsList1 and newBlessingWordsList2 ) representing the left and right columns. The component fetches items from an API via the asynchronous method getBlessingWall :

async getBlessingWall(type = 0) {
let res = await api.blessingWall({ activityId: this.activityId, pageNum: this.pageWallNum, pageSize: this.pageWallSize });
// process response, update lists, set hasWallNext, etc.
}

When more data is needed, handlerMore increments the page number and calls getBlessingWall(1) . A timer started by start() iterates through the fetched list, adding items one by one to the combined list and then distributing them to the shorter column based on current heights:

start() {
clearInterval(this.timer);
this.timer = setInterval(() => {
// add next item to left or right list depending on heights
}, 10);
}

The height of each column is obtained with Uni‑App’s selector query in getHei(item) , which compares leftHeight and rightHeight and pushes the item to the appropriate array.

getHei(item) {
const query = uni.createSelectorQuery().in(this);
query.select('#leftHalf').boundingClientRect(res => {
this.leftHeight = res.height;
const query1 = uni.createSelectorQuery().in(this);
query1.select('#rightHalf').boundingClientRect(dataRight => {
this.rightHeight = dataRight.height || 0;
if (this.leftHeight <= this.rightHeight) {
this.newBlessingWordsList1.push(item);
} else {
this.newBlessingWordsList2.push(item);
}
}).exec();
}).exec();
}

The component also handles tab switching; only when the second tab is active does it start the height‑balancing timer, ensuring the DOM elements exist before measurement.

In conclusion, the author demonstrates a functional waterfall layout using Flexbox in a Uni‑App, notes that other implementation methods exist, and invites readers to follow for future updates.

frontendJavaScriptCSSFlexboxuni-appWaterfall Layout
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.