Open Closed

Blazor Server – Delayed ABP/LeptonX CSS Loading Causing Initial Render Flash / Black Screen #10579


User avatar
0
pareeks@gccontractor.org created

We are currently experiencing an issue related to initial page load styling in a Blazor Server application using LeptonX theme. To better demonstrate the behavior, I tested under Slow 4G network throttling, where the issue becomes clearly visible.

Issue Description Before applying any optimizations, the application exhibited a Flash of Unstyled Content (FOUC) during initial load. The layout and styles appeared with a noticeable flash (https://screenapp.io/app/v/KEO2mHHQOm). I implemented several optimizations on our side as well, this reduced the impact, but a slight flash was still noticeable.

Analysis & Findings After investigation, this behavior appears to be primarily caused by delayed loading/injection of ABP/LeptonX CSS, rather than an issue in our application code. I found a similar issue discussed here: https://abp.io/support/questions/4809/Stylesheets-are-loaded-very-late https://gist.github.com/realLiangshiwei/70e19e34389ce7e567b5078a42db230a

Workaround Applied I applied the suggested workaround by adding: <leptonx-theme-appearance />

Current Behavior (After Fix) After applying this:

Concern While the workaround improves styling consistency, the black screen introduces a different UX issue (perceived delay before content appears).

Questions

  • Are there any recommended approaches to Avoid both FOUC and black screen, and improve perceived loading performance?
  • Has this issue been addressed or improved in newer ABP/LeptonX versions?
Markdown supported.
Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)

14 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    • In ABP Blazor Server + LeptonX, the FOUC you saw is typically caused by theme-appearance/theme CSS being applied only after the Blazor circuit starts and LeptonX determines the active appearance (light/dark/system). Adding <leptonx-theme-appearance /> fixes the FOUC by applying appearance early, but it can also produce a brief black screen because the page background/appearance is set immediately (often to dark) before the rest of the UI/LeptonX layout finishes rendering under slow networks.

    • The practical way to avoid both effects is to make the initial HTML render with a stable background + minimal critical CSS, so the browser never shows an unstyled/incorrect theme, and it never shows a black blank page either.

    What to do (Blazor Server, ABP 9.1.3, LeptonX)

    1. Keep using <leptonx-theme-appearance /> (it’s the correct direction to prevent late theme injection/FOUC).

    2. Add a tiny “critical” inline style (or a very small local CSS loaded before everything else) that:

      • sets html, body background to the expected color (or at least a neutral non-black color),
      • hides the app root until LeptonX appearance is applied, but shows a lightweight placeholder/skeleton instead of a black screen.

      Conceptually:

      • show a placeholder immediately (fast paint),
      • once the theme/appearance class/attribute is applied, reveal the real app.
    3. Ensure your LeptonX/ABP global CSS bundle is emitted as early as possible in the host page (_Host.cshtml / layout). In ABP, this is normally done via the theme’s recommended AbpStyles bundle usage (per the LeptonX Blazor doc). If you’ve customized the host markup, revert to the recommended placement so styles are in <head> and not deferred.

    4. If the “black screen” is specifically because the appearance resolves to dark on first load under throttling, set a deterministic default appearance (e.g., Light) instead of “System”, or persist the user preference and apply it immediately. (This prevents an initial “dark background” paint on devices where system preference is dark.)

    Has it been improved in newer versions?

    No verified source available that explicitly states this specific FOUC vs black-screen behavior was fixed in a particular ABP/LeptonX version. The only verified guidance available is the general LeptonX Blazor integration approach and the known “late styles” discussion you already found.

    Links (validated):

    • https://abp.io/support/questions/4809/Stylesheets-are-loaded-very-late
    • https://abp.io/docs/latest/ui-themes/lepton-x/blazor

    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    pareeks@gccontractor.org created

    I want support team to jump in and help. Need some verified solution/information on this.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    Could you share the following details so we can better assist you?

    1. What ABP version are you using?
    2. Are you using the _Host.cshtml hosting model or the newer App.razor (Blazor Web App) pattern?

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    pareeks@gccontractor.org created
    1. ABP version - 9.1.3
    2. Yes I am using _Host.cshtml
    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    The root cause is that you are using the old _Host.cshtml hosting model with render-mode="Server", which does not have server-side prerendering. This means the page body is empty until the Blazor SignalR circuit is established.

    • Without <leptonx-theme-appearance />: The LeptonX theme variant CSS (dark/dim/light) is loaded dynamically after Blazor connects, causing the FOUC.
    • With <leptonx-theme-appearance />: The theme CSS is loaded in the initial HTML (including background color), but the body content is still empty waiting for Blazor to connect, which causes the black screen.

    ABP 9.x uses the new Blazor Web App pattern with App.razor instead of _Host.cshtml. The new pattern uses @rendermode="InteractiveServer" which has SSR prerendering by default — the initial HTML response already contains both the CSS and the rendered content, so there is no FOUC or black screen.

    Here is the App.razor structure used in ABP 9.x Blazor Server projects with LeptonX:

    I'd recommend creating a fresh ABP 9.1.3 Blazor Server project using ABP CLI or ABP Studio, then compare its structure with your current project. The new project will use App.razor by default and should not have the FOUC / black screen issue. You can use it as a reference to migrate your existing project.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    pareeks@gccontractor.org created

    I migrated to App.razor but still getting the same issue - https://screenapp.io/app/v/L80XhRnWZw Do I still have to use <leptonx-theme-appearance />?

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    pareeks@gccontractor.org created

    Applying <Volo.Abp.AspNetCore.Components.Server.LeptonXTheme.Components.AppearanceStyles /> resolved the issue.

    Could you please share any documentation that can help me optimize App.razor even further? There's still a scope for improvement - https://share.zight.com/d5uq69Kz

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    Glad to hear <AppearanceStyles/> resolved the issue! That's the correct approach for the App.razor hosting model — it renders all LeptonX theme CSS links during SSR prerendering, so the styles are included in the initial HTML response.

    Your current App.razor setup should already match the official ABP template structure:

    <head>
        <AbpStyles BundleName="@BlazorLeptonXThemeBundles.Styles.Global" />
        <link href="YourProject.Blazor.styles.css" rel="stylesheet"/>
        <HeadOutlet @rendermode="InteractiveServer" />
        <AppearanceStyles/>
    </head>
    

    For Blazor Server, the AbpStyles component resolves and renders CSS links at runtime on the server side, so no abp bundle command is needed.

    For further optimization, you can enable bundle & minify mode in production to merge multiple CSS/JS files into fewer requests. Configure it in your module's ConfigureServices:

    Configure<AbpBundlingOptions>(options =>
    {
        options.Mode = BundlingMode.BundleAndMinify;
    });
    

    Some useful references:

    • Migration guide for the new App.razor hosting model: https://abp.io/docs/latest/release-info/migration-guides/abp-8-2-blazor-web-app
    • Bundling & Minification configuration: https://abp.io/docs/latest/framework/ui/mvc-razor-pages/bundling-minification
    • Blazor global scripts & styles: https://abp.io/docs/latest/framework/ui/blazor/global-scripts-styles

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    pareeks@gccontractor.org created

    Hi Thanks!

    According to ABP best practices, should I keep App.razor clean and move all the styles and scripts to MainBlazor Module and minify it using the AbpBundlingOptions?

    I am unable to share my final code here, can I email at <liming.ma@volosoft.com>?

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    The App.razor in the ABP template is already clean — <AbpStyles> and <AbpScripts> just reference a bundle name, and the actual CSS/JS files are managed through BundleContributor in your modules. You don't need to move anything out of App.razor.

    I'd suggest creating a new ABP 9.1.3 Blazor Server project with the same configuration as yours:

    Then compare the new project's App.razor and module configuration with your current project. The new template is the best reference for best practices.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    pareeks@gccontractor.org created

    By default ABP CLI (I have the latest version) creates .NET10 project with App.razor. Should I follow that? If I uninstall and install older ABP CLI version, it gives version compatibility warnings.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    You can just create a new project with your current CLI version:

    abp new BookStore -t app -u blazor-server
    

    The App.razor structure is the same across versions — you can use the new project as a reference to migrate your existing project from _Host.cshtml to App.razor.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    pareeks@gccontractor.org created

    While testing these changes, I encountered a

    System.InvalidOperationException
    Message=JavaScript interop calls cannot be issued at this time. This is because the component is being statically rendered. When prerendering is enabled, JavaScript interop calls can only be performed during the OnAfterRenderAsync lifecycle method.
    

    on full page reloads related to JavaScript interop during prerendering. As a temporary workaround, I have disabled prerendering. Can you help in this?

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    This error happens because the new App.razor model uses SSR prerendering by default. During prerendering, JavaScript interop is not available — it can only be called in OnAfterRenderAsync.

    In your old _Host.cshtml setup with render-mode="Server", there was no prerendering, so JS interop calls in OnInitializedAsync worked fine. After migrating, those same calls will fail during the prerendering phase.

    To help you fix this, could you share the following files:

    1. App.razor
    2. Your Blazor module class (e.g., MyProjectNameBlazorModule.cs)
    3. The full stack trace of the exception
    4. Are you using any third-party Blazor component libraries?

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.8.0-preview. Updated on September 16, 2026, 14:50
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.