razorbootstrap-5ui-virtualization

How to virtualize a responsive Bootstrap grid?


A Bootstrap grid can wrap its columns into rows when the viewport width is smaller than a configured breakpoint. This changes the row height and interferes with Razor virtualization which wants to know the height of the virtualized elements. How can I make virtualization play nicely with a responsive grid?

I thought about using Bootstrap display classes to display one virtualized grid for widths above the breakpoint and an entirely different one for widths below it. I haven't tried this yet because I'm too new to Bootstrap and Razor to be confident in any solution even if it appeared to work.


Solution

  • Using Bootstrap display classes to display different virtualized grids depending on display size "works" in the sense that Virtualize doesn't spam errors in the console. But this exhibits a problem that may have no general solution. When the content switches between 3 columns and 1 column, the browser maintains its absolute scroll position rather than its relative scroll position. So if you're looking at item 300 in 3-column mode and you narrow the viewport, you'll be looking at item 100.

    I may just live with this for now. My main goal is to support mobile and desktop browsers, and I don't expect desktop users to resize their browser that often.

    @page "/virtualize"
    
    <!-- 3 columns at or above md -->
    <div class="container d-none d-md-block">
        <Virtualize Items="Rows" Context="row" ItemSize="100">
            <div class="row" style="height: 100px">
                @foreach(var i in row)
                {
                    <div class="col-4">
                        <div style="width: 100%; height: 100%; border: solid;">
                            @i
                        </div>
                    </div>
                }
            </div>
        </Virtualize>
    </div>
    
    <!-- 1 column below md -->
    <div class="container d-block d-md-none">
        <Virtualize Items="Items" Context="i" ItemSize="100">
            <div class="row" style="height: 100px">
                <div class="col-12">
                    <div style="width: 100%; height: 100%; border: solid;">
                        @i
                    </div>
                </div>
            </div>
        </Virtualize>
    </div>
    
    @code {
        private List<int> Items => Enumerable.Range(1, 1000).ToList();
        private List<int[]> Rows => Items.Chunk(3).ToList();
    }