Syncfusion Blazor chart getting clipped

Hi all,


I'm running into a frustrating issue with Syncfusion Blazor charts. Sometimes it renders fine but often times it gets clipped. Also, when I resize the browser window using the maximize/restore button, or when I move the browser window from my laptop screen to an external monitor (or vice versa), the chart gets clipped and is not fully visible. 


- See it in action in the attached screen recording. As you can see the Hour Ending 24 is visible for a split of a second and then gets clipped out. 

- The chart is inside a simple flex column layout with `Width="100%"` and a fixed `Height`.

- The issue is reproducible as is. Also it can be seen when maximizing/restoring the browser or dragging it between screens.


Q1. What is causing this? 

Q2. Is there a CSS/layout trick or Syncfusion setting I’m missing to make the chart always render correctly?


I’ve attached a screen recording and the full code below so you can reproduce the problem.


Thanks for your help in resolving this issue!


Attachment: chartclippingbug_596b2b69.gif

4 Replies

AK Ashish Khanal April 14, 2026 11:05 PM UTC

Repro Code:


@page "/ChartClippingRepro"

@using Syncfusion.Blazor.Buttons
@using Syncfusion.Blazor.DropDowns
@using Syncfusion.Blazor.Calendars
@using Syncfusion.Blazor.Charts
@using Syncfusion.Blazor.Spinner

<style>
    .test-report-container {
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        display: flex;
        flex-direction: column;
        gap: 16px;
        margin-bottom: 24px;
    }

    .test-chart .e-chart text {
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    }

    .e-btn {
        padding: 0 24px;
        font-size: 1.1rem;
        min-width: 180px;
    }

    .test-title {
        text-align: center;
        width: 100%;
        margin: 16px 0;
    }

    .test-controls-row {
        display: flex;
        flex-direction: row;
        gap: 18px;
        background: #f6fafd;
        border-radius: 8px;
        padding: 16px 18px;
        /* Allows wrapping on small screens */
        flex-wrap: wrap;
    }

    .test-controls-row label {
        font-size: 1.1rem;
        font-weight: 600;
        margin-bottom: 0.375rem;
        color: #101010;
    }

    .test-controls {
        display: flex;
        flex-direction: column;
        min-width: 180px;
        flex: 1 1 0;
        min-height: 75px; /* Reserve enough space for label, input, and validation */
    }

    .test-controls-actions {
        display: flex;
        flex-direction: row;   /* Ensure buttons are in a row */
        gap: 12px;
        align-items: center;
        flex-wrap: wrap;
        margin-top: 5px; /*To align the buttons vertically*/
        /* min-height: 75px; */
    }

    .test-chart {

    }

    @@media (max-width: 900px) {

        .test-controls{
            min-height: 0; /* Remove the forced height */
        }

        .test-controls-actions {
            flex-direction: column;   /* Stack buttons vertically */
            width: 100%;
            align-items: stretch;     /* Make children (buttons) stretch to full width */
        }
    }
</style>

<PageTitle>TestApp</PageTitle>

<h4 class="test-title">Chart Clipping Repro</h4>

<div class="test-report-container">
    @if (EditContext != null)
    {
        <EditForm EditContext="@EditContext">
            <DataAnnotationsValidator />
            <div class="test-controls-row">
                <div class="test-controls">
                    <label>Date</label>
                    <SfDatePicker TValue="DateTime?"
                        @bind-Value=@InputModel.Date
                        Min=@MinDate
                        Max=@MaxDate
                        AllowEdit="false"
                        ShowClearButton="true"/>
                    <ValidationMessage For="@(() => InputModel.Date)" />
                </div>
                <div class="test-controls">
                    <label>Region</label>
                    <SfDropDownList TValue="string"
                                    TItem="string"
                                    DataSource="@Regions"
                                    @bind-Value="InputModel.Region"
                                    Placeholder="Select region" />
                    <ValidationMessage For="@(() => InputModel.Region)" />
                </div>
                <div class="test-controls-actions">
                    <SfButton IsPrimary="true" OnClick="OnRefreshAsync" Disabled="@IsBusy" type="button">
                        @if (IsBusy && InputModel.Action == MyPageAction.Refresh)
                        {
                            <span class="spinner-border spinner-border-sm" role="status" aria-label="Refreshing"></span>
                            <span>Refreshing...</span>
                        }
                        else
                        {
                            <span>Refresh</span>
                        }
                    </SfButton>
                </div>
            </div>
        </EditForm>
    }
    else
    {
        <div>Loading controls...</div>
    }

    @if (MyForecasts.Count > 0)
    {
        <div class="test-chart">
            <SfChart Title="@ChartTitle1" Width="100%" Height="400px">
                <ChartTitleStyle TextOverflow="Syncfusion.Blazor.Charts.TextOverflow.Wrap"></ChartTitleStyle>
                <ChartArea>
                    <ChartAreaBorder Width="0"></ChartAreaBorder>
                </ChartArea>
                <ChartMargin Right="10" />
                <ChartEvents OnAxisLabelRender="ChartAxisLabelRender"
                                OnDataLabelRender="ChartDataLabelRender"
                                SharedTooltipRender="ChartSharedTooltipRender">
                </ChartEvents>
                <ChartPrimaryXAxis ValueType="Syncfusion.Blazor.Charts.ValueType.Double"
                                    IntervalType="Syncfusion.Blazor.Charts.IntervalType.Auto"
                                    Title="Hour Ending"
                                    Interval="1" />

                <ChartPrimaryYAxis Title="MWs" LabelFormat="N0">
                    <ChartAxisMajorTickLines Width="0"></ChartAxisMajorTickLines>
                    <ChartAxisLineStyle Width="0"></ChartAxisLineStyle>
                </ChartPrimaryYAxis>

                <ChartSeriesCollection>
                    <!-- Stacked Area Series (order: bottom to top) -->
                    <ChartSeries DataSource="@MyForecasts"
                                    XName="HourEnding"
                                    YName="Wind"
                                    Name="Wind"
                                    Type="Syncfusion.Blazor.Charts.ChartSeriesType.StackingArea"
                                    Fill="#00B050"
                                    Opacity="0.7" />

                    <ChartSeries DataSource="@MyForecasts"
                                    XName="HourEnding"
                                    YName="Solr"
                                    Name="Solr"
                                    Type="Syncfusion.Blazor.Charts.ChartSeriesType.StackingArea"
                                    Fill="#FFD600"
                                    Opacity="0.7" />
                </ChartSeriesCollection>
                <ChartLegendSettings Visible="true" />
                <ChartTooltipSettings Enable="true" Shared="true" />
            </SfChart>
        </div>
        <div class="test-chart">
            <SfChart Title="@ChartTitle2" Width="100%" Height="400px">
                <ChartTitleStyle TextOverflow="Syncfusion.Blazor.Charts.TextOverflow.Wrap"></ChartTitleStyle>
                <ChartArea>
                    <ChartAreaBorder Width="0"></ChartAreaBorder>
                </ChartArea>
                <ChartMargin Right="10" />
                <ChartEvents OnAxisLabelRender="ChartAxisLabelRender"
                                OnDataLabelRender="ChartDataLabelRender"
                                SharedTooltipRender="ChartSharedTooltipRender">
                </ChartEvents>
                <ChartPrimaryXAxis ValueType="Syncfusion.Blazor.Charts.ValueType.Double"
                                    IntervalType="Syncfusion.Blazor.Charts.IntervalType.Auto"
                                    Title="Hour Ending"
                                    Interval="1" />
                <ChartPrimaryYAxis Title="MWs" LabelFormat="N0">
                    <ChartAxisMajorTickLines Width="0"></ChartAxisMajorTickLines>
                    <ChartAxisLineStyle Width="0"></ChartAxisLineStyle>
                </ChartPrimaryYAxis>

                <ChartSeriesCollection>
                    <ChartSeries DataSource="@MyForecasts"
                                    XName="HourEnding"
                                    YName="Solr"
                                    Name="Solr"
                                    Type="Syncfusion.Blazor.Charts.ChartSeriesType.Line"
                                    Width="2"
                                    Fill="#FF4070"
                                    DashArray="5,2" />

                    <ChartSeries DataSource="@MyForecasts"
                                    XName="HourEnding"
                                    YName="Wind"
                                    Name="Wind"
                                    Type="Syncfusion.Blazor.Charts.ChartSeriesType.Line"
                                    Width="2"
                                    Fill="#A3D233"
                                    DashArray="5,2" />
                </ChartSeriesCollection>
                <ChartLegendSettings Visible="true" />
                <ChartTooltipSettings Enable="true" Shared="true" />
            </SfChart>
        </div>
    }
    else if (IsBusy)
    {
        <div>Loading charts...</div>
    }
    else
    {
        <div>No chart data available.</div>
    }

    <SfSpinner Visible="@IsBusy"></SfSpinner>
</div>

@code {
    List<MyForecast> MyForecasts = new();

    MyPageInputModel InputModel = new();
    EditContext? EditContext;
    bool IsBusy;

    // Dates
    DateTime MinDate = DateTime.Today;
    DateTime MaxDate = DateTime.Today.AddDays(1);

    // Chart data
    string ChartTitle1 = string.Empty;
    string ChartTitle2 = string.Empty;

    // Regions
    List<string> Regions = new() { "Reg 1", "Reg 2" };

    // --- Lifecycle Methods ---
    protected override async Task OnInitializedAsync()
    {
        EditContext = new EditContext(InputModel);

        await LoadPageDataAsync();
        UpdateChartTitle();
    }

    // --- Event Handlers ---
    async Task OnRefreshAsync()
    {
        InputModel.Action = MyPageAction.Refresh;
        await LoadPageDataAsync();
        UpdateChartTitle();
        InputModel.Action = MyPageAction.None;
    }

    async Task LoadPageDataAsync()
    {
        IsBusy = true;
        // Simulate an API call
        await Task.Delay(50);

        MyForecasts = new List<MyForecast>
        {
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 1, Region = "Reg 1", Wind = 8927, Solr = 0 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 2, Region = "Reg 1", Wind = 8830, Solr = 0 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 3, Region = "Reg 1", Wind = 8839, Solr = 0 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 4, Region = "Reg 1", Wind = 8790, Solr = 0 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 5, Region = "Reg 1", Wind = 8692, Solr = 0 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 6, Region = "Reg 1", Wind = 8345, Solr = 37 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 7, Region = "Reg 1", Wind = 7938, Solr = 1404 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 8, Region = "Reg 1", Wind = 7698, Solr = 5426 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 9, Region = "Reg 1", Wind = 7697, Solr = 7903 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 10, Region = "Reg 1", Wind = 7691, Solr = 8764 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 11, Region = "Reg 1", Wind = 7582, Solr = 9194 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 12, Region = "Reg 1", Wind = 7514, Solr = 9989 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 13, Region = "Reg 1", Wind = 7674, Solr = 10195 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 14, Region = "Reg 1", Wind = 7558, Solr = 10340 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 15, Region = "Reg 1", Wind = 7586, Solr = 10167 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 16, Region = "Reg 1", Wind = 7400, Solr = 9713 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 17, Region = "Reg 1", Wind = 7174, Solr = 8407 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 18, Region = "Reg 1", Wind = 7392, Solr = 4721 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 19, Region = "Reg 1", Wind = 7115, Solr = 932 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 20, Region = "Reg 1", Wind = 7292, Solr = 3 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 21, Region = "Reg 1", Wind = 7182, Solr = 0 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 22, Region = "Reg 1", Wind = 7096, Solr = 0 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 23, Region = "Reg 1", Wind = 7221, Solr = 0 },
            new() { Date = DateTime.Parse("4/14/2026"), HourEnding = 24, Region = "Reg 1", Wind = 8890, Solr = 0 },
        };

        IsBusy = false;
    }

    void UpdateChartTitle()
    {
        if (InputModel.Date.HasValue)
        {
            ChartTitle1 = $"Chart 1 on {InputModel.Date: ddd, MM/dd/yyyy}";
            ChartTitle2 = $"Chart 2 on {InputModel.Date: ddd, MM/dd/yyyy}";
        }
    }

    // Reference: https://blazor.syncfusion.com/documentation/chart/axis-labels#label-customization-using-event
    void ChartAxisLabelRender(Syncfusion.Blazor.Charts.AxisLabelRenderEventArgs args)
    {
        //args.LabelStyle.Color = "Black";

        if (args.Axis.Name == "PrimaryXAxis")
        {
            // Format X axis label here
        }
        else if (args.Axis.Name == "PrimaryYAxis")
        {
            if (double.TryParse(args.Text.Replace(",", ""), out double value))
            {
                if (Math.Abs(args.Value) >= 1000)
                {
                    args.Text = (value / 1000).ToString("0.#") + "K";
                }
            }
        }
    }

    void ChartDataLabelRender(Syncfusion.Blazor.Charts.TextRenderEventArgs args)
    {
        // Format the value (e.g., 12,345)
        if (double.TryParse(args.Text, out var value))
        {
            args.Text = value.ToString("N0");
        }
    }

    void ChartSharedTooltipRender(SharedTooltipRenderEventArgs args)
    {
        if (args.Data is null || args.Data.Count == 0)
            return;

        args.HeaderText = $"HE {args.HeaderText}";
        var lines = new List<string>();
        foreach (var d in args.Data)
        {
            if (double.TryParse(d.PointY.ToString(), out var value))
                lines.Add($"{d.SeriesName}: {value:N0}");
            else
                lines.Add($"{d.SeriesName}: N/A");
        }
        args.Text = lines;
    }

    // --- Data Models ---
    public class MyPageInputModel
    {
        public MyPageAction Action { get; set; } = MyPageAction.None;
        public DateTime? Date { get; set; } = DateTime.Today;
        public string Region { get; set; } = "Reg 1";
    }

    public class MyForecast
    {
        public DateTime Date { get; set; }
        public int HourEnding { get; set; }
        public string Region { get; set; } = default!;
        public double? Wind { get; set; }
        public double? Solr { get; set; }
    }

    public enum MyPageAction
    {
        None,
        Refresh
    }
}

Screenshot:

As you can see HE 24 is clipped out:

Image_2746_1776207882215



KP Karthick Panneerselvam Syncfusion Team April 15, 2026 12:52 PM UTC

Hi Ashish Khanal,

Greetings from Syncfusion.


The chart clipping issue occurs because the X-axis labels (especially the last one, "24") require additional space beyond the default chart plot area. When multiple charts are rendered in a flex column layout, the margin calculation doesn't account for the full label width properly during the initial render cycle.


For this cause Increase Chart Margin

<ChartMargin Right="25" />

Sample : https://blazorplayground.syncfusion.com/htBRXpMeTyOJIhDh

Why This Works:

  1. Label Overflow Space — The right margin provides a buffer zone where axis labels can extend beyond the plot area without being clipped by the SVG viewport boundary

  2. Dynamic Label Sizing — The last X-axis label requires more horizontal space than typical labels. A margin of 25px (vs. the default 10px) gives sufficient clearance for labels to render completely

  3. Multiple Chart Layouts — In flex column layouts with multiple charts, the larger margin ensures consistent rendering across all charts, even before full DOM layout stabilization

Kindly revert us if you have any further concerns.


Regards,

Karthick Panneerselvam



AK Ashish Khanal April 15, 2026 04:19 PM UTC

Hi Karthick,

Your AI generated response is not a good solution, I've already tried it and there are issues with it. So please take a different approach. 

Please forward this to a Senior Engineer on the team. This looks like a bug on the Syncfusion Chart control.


The rendering is fine when the browser doesn't introduce a scroll bar. 

Image_8227_1776269873236


But the margin is squished (the gap between 24 and end of the chart) and the chart overflows when browser introduces a scroll bar.  This appears to be a bug. I expect this to be handled by Syncfusion library. If not provide a good workaround. 

Image_7460_1776269233328



Even if I provide a large margin as a workaround for this bug, the experience is not good when moving the window across different screens because it provided an inconsistent experience. 

Like it'll show properly in one screen with sufficient gap (between 24 and end of the chart) like this:

Image_5624_1776269349155


 But that same gap is squished when moving to another screen, which is not a good UX.

Image_9518_1776269376794


Is a better solution to re-render the chart when it gets the scrollbar? If not, what could be a better solution?

Thank you for your help!



KP Karthick Panneerselvam Syncfusion Team April 16, 2026 07:15 AM UTC

Ashish,

We sincerely apologize for the inconvenience caused.

We have reviewed the reported scenario and identified it as a bug. A defect has been logged for the issue titled “Prevent Chart Clipping When a Scroll Bar Appears”. The fix for this issue will be included in our weekly patch release, which is scheduled to be rolled out on 28th April 2026.

 

Please let us know if you have any concerns.

 

 

Regards,

Karthick Panneerselvam


Loader.
Up arrow icon