Blazor supports virtualization but items need to have same height. For most cases it's okay, but for example for chats where amount of messages can be high and messages have different heights due to word wrapping default blazor Virtualize component is not enough. Is there an easy way to implement virtualization for items with different sizes? I don't care about correct scroll thumb position relative to all items, I can live with thumb tracking only loaded messages.
-
No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes.Panagiotis Kanavos– Panagiotis Kanavos2025-09-24 08:42:14 +00:00Commented Sep 24 at 8:42
-
You didn't explain what you actually want to do anyway. There may be other components that do what you want. For example this React demo for a Fluent UI 2 DetailsList uses variable-length items. AG-Grid also does this, but renders and buffers rows before they get displayed.Panagiotis Kanavos– Panagiotis Kanavos2025-09-24 08:59:40 +00:00Commented Sep 24 at 8:59
-
@PanagiotisKanavos I want to virtualize chat messages where every message element could have variable height due to word wrapping.GeorgeKarlinzer– GeorgeKarlinzer2025-09-24 11:15:21 +00:00Commented Sep 24 at 11:15
-
@GeorgeKarlinzer You can use Intersection Observer API.GH DevOps– GH DevOps2025-09-24 13:39:34 +00:00Commented Sep 24 at 13:39
-
1"due to word wrapping default blazor Virtualize component is not enough.". Take a look at my quick demo at github.com/ShaunCurtis/SO79773436. [Polite] What am I missing?MrC aka Shaun Curtis– MrC aka Shaun Curtis2025-09-24 18:24:35 +00:00Commented Sep 24 at 18:24
|
Show 2 more comments
1 Answer
It should work. Here's some demo code that shows it working. Blazor Server template with Global Interactivity.
Home with Virtualize:
@page "/"
<PageTitle>Home</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<Virtualize ItemsProvider="this.GetRows" >
<div class="m-2 p-2 border border-1">@context.Value</div>
</Virtualize>
@code {
private ValueTask<ItemsProviderResult<Message>> GetRows(ItemsProviderRequest request)
=> new(new ItemsProviderResult<Message>( TestDataProvider.Messages.Skip(request.StartIndex).Take(request.Count),TestData.Messages.Count));
}
The data provider
public record Message(string Value);
public static class TestDataProvider
{
public static readonly List<Message> Messages =
new()
{
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("@PanagiotisKanavos I want to virtualize chat messages where every message element could have variable height due to word wrapping."),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("You didn't explain what you actually want to do anyway. There may be other components that do what you want. For example this React demo for a Fluent UI 2 DetailsList uses variable-length items. AG-Grid also does this, but renders and buffers rows before they get displayed"),
new Message("@IvanStoev thank you very much, that did it. I simply did not notice the existing List of SystemLicenses for Customer, which brought up the problem.. Thanks a lot! "),
new Message("@PanagiotisKanavos I want to virtualize chat messages where every message element could have variable height due to word wrapping."),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("ddddd"),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("@PanagiotisKanavos I want to virtualize chat messages where every message element could have variable height due to word wrapping."),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("You didn't explain what you actually want to do anyway. There may be other components that do what you want. For example this React demo for a Fluent UI 2 DetailsList uses variable-length items. AG-Grid also does this, but renders and buffers rows before they get displayed"),
new Message("@IvanStoev thank you very much, that did it. I simply did not notice the existing List of SystemLicenses for Customer, which brought up the problem.. Thanks a lot! "),
new Message("@PanagiotisKanavos I want to virtualize chat messages where every message element could have variable height due to word wrapping."),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("ddddd"),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("@PanagiotisKanavos I want to virtualize chat messages where every message element could have variable height due to word wrapping."),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("You didn't explain what you actually want to do anyway. There may be other components that do what you want. For example this React demo for a Fluent UI 2 DetailsList uses variable-length items. AG-Grid also does this, but renders and buffers rows before they get displayed"),
new Message("@IvanStoev thank you very much, that did it. I simply did not notice the existing List of SystemLicenses for Customer, which brought up the problem.. Thanks a lot! "),
new Message("@PanagiotisKanavos I want to virtualize chat messages where every message element could have variable height due to word wrapping."),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("ddddd"),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("ddddd"),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("@PanagiotisKanavos I want to virtualize chat messages where every message element could have variable height due to word wrapping."),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("You didn't explain what you actually want to do anyway. There may be other components that do what you want. For example this React demo for a Fluent UI 2 DetailsList uses variable-length items. AG-Grid also does this, but renders and buffers rows before they get displayed"),
new Message("@IvanStoev thank you very much, that did it. I simply did not notice the existing List of SystemLicenses for Customer, which brought up the problem.. Thanks a lot! "),
new Message("@PanagiotisKanavos I want to virtualize chat messages where every message element could have variable height due to word wrapping."),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("ddddd"),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("ddddd"),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("@PanagiotisKanavos I want to virtualize chat messages where every message element could have variable height due to word wrapping."),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("You didn't explain what you actually want to do anyway. There may be other components that do what you want. For example this React demo for a Fluent UI 2 DetailsList uses variable-length items. AG-Grid also does this, but renders and buffers rows before they get displayed"),
new Message("@IvanStoev thank you very much, that did it. I simply did not notice the existing List of SystemLicenses for Customer, which brought up the problem.. Thanks a lot! "),
new Message("@PanagiotisKanavos I want to virtualize chat messages where every message element could have variable height due to word wrapping."),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("ddddd"),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("ddddd"),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("@PanagiotisKanavos I want to virtualize chat messages where every message element could have variable height due to word wrapping."),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("You didn't explain what you actually want to do anyway. There may be other components that do what you want. For example this React demo for a Fluent UI 2 DetailsList uses variable-length items. AG-Grid also does this, but renders and buffers rows before they get displayed"),
new Message("@IvanStoev thank you very much, that did it. I simply did not notice the existing List of SystemLicenses for Customer, which brought up the problem.. Thanks a lot! "),
new Message("@PanagiotisKanavos I want to virtualize chat messages where every message element could have variable height due to word wrapping."),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("ddddd"),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("ddddd"),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("@PanagiotisKanavos I want to virtualize chat messages where every message element could have variable height due to word wrapping."),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("You didn't explain what you actually want to do anyway. There may be other components that do what you want. For example this React demo for a Fluent UI 2 DetailsList uses variable-length items. AG-Grid also does this, but renders and buffers rows before they get displayed"),
new Message("@IvanStoev thank you very much, that did it. I simply did not notice the existing List of SystemLicenses for Customer, which brought up the problem.. Thanks a lot! "),
new Message("@PanagiotisKanavos I want to virtualize chat messages where every message element could have variable height due to word wrapping."),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("ddddd"),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("ddddd"),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("@PanagiotisKanavos I want to virtualize chat messages where every message element could have variable height due to word wrapping."),
new Message("@GeorgeKarlinzer You can use Intersection Observer API. "),
new Message("No - it it was easy, you wouldn't have to ask for it. UI virtualization works by replacing placeholders with data. You need to know the size of the placeholder in advance. The perf benefits come because the page doesn't have to create or destroy elements, or recompute the layout due to changing sizes."),
new Message("You didn't explain what you actually want to do anyway. There may be other components that do what you want. For example this React demo for a Fluent UI 2 DetailsList uses variable-length items. AG-Grid also does this, but renders and buffers rows before they get displayed"),
};
}
3 Comments
Panagiotis Kanavos
Does this work if the first 10-20 items are small ones? I actually checked the source code when commenting. The component creates placeholders with a specific size. Although I admit I took the OP's word that the display isn't working properly and didn't test it.
MrC aka Shaun Curtis
I didn't actually try, I just put together the demo as a starting point to see what was happening. You probably need to optimize
OverscanCount to get it right.Brian Parker
If you try and scroll a large dataset with variable size items, it will cause a mess, especially on a laggy connections. You may get away with it with small data amounts.