Description: Understand and use x-if (template added/removed from DOM) or x-show (CSS display: none;) appropriately. x-if is generally better for expensive or rarely shown content because it avoids rendering and initializing the content until needed, and cleans it up when hidden. x-show is better for frequently toggled content as it simply hides/shows elements already in the DOM, preserving their state and avoiding re-initialization costs.
x-if="expression"
The x-if directive conditionally renders a block of HTML. It achieves this by completely adding the content to or removing it from the Document Object Model (DOM) based on the truthiness of the provided JavaScript expression.
true, the content (defined within a <template> tag) is rendered and inserted into the DOM. Alpine components and x-init directives within this block are initialized.false, the content is entirely removed from the DOM. This means any state within that block is lost, and Alpine components are destroyed (triggering cleanup logic if defined).x-show="expression"
The x-show directive toggles the visibility of an element by manipulating its CSS display property (typically between its default display value and none). The element always remains part of the DOM.
true, the element is visible.false, the element is hidden (style="display: none;" is applied).x-if would be detrimental.<template> tag (for x-if)
The x-if directive must be used on an HTML <template> tag. This tag acts as an inert container for the HTML structure that AlpineJS will conditionally manage.
<template> is not rendered by the browser initially.x-if condition changes.<template x-if="isLoggedIn"><p>Welcome back!</p></template>x-if requires a <template> tag:
A frequent error is forgetting to wrap the content for x-if within a <template> tag. Applying x-if directly to an element like a <div> is incorrect and will not work as intended for conditionally rendering a block of HTML. AlpineJS needs the <template> to know what structure to add or remove.
Correct: <template x-if="condition"><div>Content</div></template>
Incorrect: <div x-if="condition">Content</div>
x-if are destroyed and re-initialized; x-show preserves state:
This is a critical distinction with significant implications for performance, state management, and component behavior:
x-if:
false, any Alpine components, x-init directives, or JavaScript state within the <template> are destroyed and removed from the DOM.true again, everything is re-created and re-initialized from scratch. This means init() functions (or x-init expressions) run again, and any previous state (like user input in a form field within the x-if block) is lost.x-show:
x-show is first processed).display is set to none, but the element, its child components, and their state (e.g., data, form input values) remain intact in memory and in the DOM.x-if can improve initial page load if the conditional content is complex and not immediately needed. x-show is faster for subsequent toggles of already-rendered content.init() / x-init): Code in x-init within an x-if block will execute every time the block is shown. For x-show, it generally runs only once.x-show. If a fresh state is required each time, or if the component is expensive to keep in memory, x-if is more appropriate.Alpine.destroyCallback): Cleanup logic associated with components inside an x-if block will be triggered each time the block is removed from the DOM.
This example demonstrates the differences between x-if and x-show.
Pay attention to the "Initialization Counter" and the text you type into the input fields.
Also, check your browser's console for log messages.
x-ifThis content is rendered with x-if.
It's ADDED to or REMOVED from the DOM.
Initialization Counter:
Last Initialized:
Text in this input will be LOST when this block is hidden and re-shown, as the element is destroyed and recreated.
x-if content is currently REMOVED from the DOM.
x-showThis content is controlled by x-show.
It's ALWAYS in the DOM, hidden/shown with CSS display: none.
Initialization Counter: (should remain 1)
Last Initialized:
Text in this input will be PRESERVED when this block is hidden and re-shown, as the element is only hidden via CSS.
x-show content is currently HIDDEN (display: none).