DEV Community

Cover image for The Mystery of the Blank White Screen in Blazor Hybrid (.NET MAUI) and How a Hidden CSS Class Fooled Me!
Md. Injamul Alam
Md. Injamul Alam

Posted on

The Mystery of the Blank White Screen in Blazor Hybrid (.NET MAUI) and How a Hidden CSS Class Fooled Me!

Every developer loves that moment when their app works flawlessly on the desktop emulator. But as software developers, we all know the ultimate truth: "It works on my machine" doesn't mean it will work on the actual physical device.

Recently, while building a premium digital bus ticketing system (JatriChecker) using Blazor Hybrid (.NET MAUI) and Tailwind CSS, I stumbled upon a bizarre bug. The app went from "working perfectly" to a completely frozen, blank white screen on my physical mobile device.

Here is the story of how I debugged it, what went wrong, and how a tiny CSS utility completely blinded the WebView layer.

The Symptom

I was working on adding some smooth, premium iOS/Android native-like bottom sheet animations using custom CSS keyframes (animate-slide-up and animate-fade-in). After a couple of rapid Hot Reloads via the USB debugging cable, boom!

The app launched, but the screen stayed entirely blank and white.

The Initial Debugging Traps (What I Tried First)

When a Blazor Hybrid app goes blank, your instinct as a .NET developer usually takes you to these places:

  1. The Native Build Glitch: I assumed the Android environment or the ADB (Android Debug Bridge) proxy socket had frozen. I did a clean sweep: closed Visual Studio, manually deleted the bin and obj folders, and cold-restarted the ADB server using:
adb kill-server
adb devices
Enter fullscreen mode Exit fullscreen mode
  1. The App Lifecycle Crash: I checked if my newly injected ConnectivityService inside MainLayout.razor was throwing a silent unhandled exception during OnInitializedAsync(). I wrapped it in a tight try-catch block, but still—nothing.

The build succeeded perfectly, but the screen was obstinately white.

The Breakthrough: Inspecting the WebView

Since Blazor Hybrid runs inside a native wrapper using a WebView engine, it won't always throw a C# crash log in your Visual Studio Output window for UI layer problems.

I connected my phone via USB, opened Google Chrome on my PC, and navigated to:
chrome://inspect

Under Remote Target, my device and the web wrapper asset for JatriChecker appeared. I clicked Inspect to open the Chrome Developer Tools Console.

To my absolute surprise, there were zero JavaScript errors. Zero C# exceptions. The DOM tree was fully rendered, the HTML elements were all there, but nothing was showing up!

The Real Culprit: A Tiny Tailwind Utility

I started inspecting the root structure of the application inside index.html (under wwwroot). That's when I found the ghost.

During my layout testing earlier, I had accidentally injected a Tailwind CSS class into the root application mount point:

What it looked like:

<div id="app" class="hidden">Loading...</div>
Enter fullscreen mode Exit fullscreen mode

Why this broke the app:
When a Blazor application boots up, it initially displays whatever is inside <div id="app"> (usually a "Loading..." string or a spinner). Once the Blazor framework assembly finishes initializing, it swaps out that internal content with your actual application layout (like Login.razor or Home.razor).

However, by putting the Tailwind hidden class (which translates to display: none !important;) directly on the wrapper ID itself, the entire container stayed invisible!

Blazor was successfully mounting my premium UI and logic inside the DOM, but the browser engine was strictly told not to display the wrapper box at all.

The Fix & A Better UX Lesson

The fix was as simple as removing that cursed hidden class.

But it got me thinking. Instead of leaving a boring, generic Loading... text that makes you wonder if the app is stuck, why not design a premium loader that seamlessly vanishes once Blazor takes over?

I replaced it with a custom animated Tailwind spinner:

<div id="app" class="min-h-screen flex flex-col items-center justify-center bg-slate-50">
    <div class="flex flex-col items-center space-y-4">
        <div class="w-12 h-12 border-4 border-orange-500/20 border-t-orange-500 rounded-full animate-spin"></div>
        <p class="text-sm font-bold text-slate-400 tracking-wider font-sans">LOADING TICKET CHECKER...</p>
    </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Now, the moment the app boots, a smooth spinner greets the user, and the millisecond Blazor is ready, it swaps it out instantly for the main login layout.

Key Takeaways for Hybrid Developers

  1. Don't just rely on IDE logs: When working with Hybrid architectures (MAUI, Electron, Tauri, Cordova), always keep chrome://inspect or Edge DevTools handy. The UI layer has its own rules.

  2. Watch your Root Containers: Avoid adding layout or visibility modifiers (like hidden, opacity-0, invisible) to your main framework root mounts (#app) unless you are manually controlling them via JS interop.

Have you ever lost hours of debugging to a single line of CSS? Let me know your horror stories in the comments below!

Top comments (0)