Description: Prevent Flash of Unstyled/Uninitialized Content (FOUC) by using x-cloak to hide elements until Alpine.js has finished initializing them.
When you use Alpine.js to conditionally show or hide elements (e.g., with x-show or x-if), or to render content dynamically, there can be a brief moment before Alpine.js takes control. During this tiny window, the browser might render the elements in their raw, pre-Alpine state. This can lead to a "flash" where content appears and then quickly disappears or changes, which is visually jarring for users. The x-cloak directive is designed to solve this specific problem.
x-cloak attribute:
This is a simple attribute you add to any HTML element you want to protect from FOUC. Alpine.js will automatically remove this attribute from the element once it has fully initialized that element and its children.
For example: <div x-show="isVisible" x-cloak>Content</div>
CSS rule [x-cloak] { display: none !important; }:
This CSS rule is crucial and must be included in your stylesheet or <style> tags. It targets any element that currently has the x-cloak attribute and hides it using display: none. The !important declaration helps ensure this rule takes precedence over other display styles until Alpine removes the x-cloak attribute.
[x-cloak] { display: none !important; }
How it works together:
x-cloak to an HTML element.x-cloak attribute is present.x-cloak, it finishes its setup for that element (e.g., evaluating x-show, x-if, etc.).x-cloak attribute.[x-cloak] { display: none !important; } no longer applies, and the element's visibility is now solely controlled by Alpine.js directives or other CSS.The necessary CSS rule is missing: If you add x-cloak to your elements but forget to include the [x-cloak] { display: none !important; } CSS rule, x-cloak will have no effect. The elements might still flash because there's no CSS instruction to hide them before Alpine initializes and removes the attribute.
x-cloak is for Alpine's initialization, not general loading states: Its primary purpose is to manage the initial paint before Alpine takes over. It ensures that elements controlled by Alpine (like those with x-show or x-if) don't appear briefly in their default, unmanaged state. It's not intended as a general solution for hiding content while waiting for data from API calls. For API loading states, you'd typically use a dedicated reactive property (e.g., isLoading) in your Alpine component and control visibility with x-show="!isLoading". However, x-cloak can be (and often is) used on the same element as x-show="!isLoading" to prevent the FOUC before Alpine even evaluates the isLoading state.
This example demonstrates how x-cloak prevents an element, which is conditionally shown with x-show,
from briefly appearing (flashing) before Alpine.js fully initializes it.
The panel below is initially set to be hidden (showPanel is false).
It uses both x-show="showPanel" and x-cloak.
Thanks to x-cloak and the associated CSS rule, you should not see it flash on page load.
🎉 This panel is now visible!
It was protected by x-cloak during Alpine's initialization phase. Now, its visibility is controlled by the showPanel state and x-show.
On very fast connections or simple pages, FOUC might be hard to notice even without x-cloak.
However, on complex applications, slower devices, or when Alpine.js initializes many components,
x-cloak becomes essential for a smooth user experience.
The key is that x-cloak provides a reliable way to prevent this flash, regardless of these factors.
If you were to remove x-cloak from the panel above AND remove the global CSS rule for [x-cloak] (or if Alpine was significantly delayed), you *might* see the green panel briefly appear and then disappear as Alpine sets x-show="false".