Description: Efficiently show or hide elements by toggling their `display` CSS property (usually between `display: none;` and its original display value) based on a boolean condition.
x-show="expression".
expression is a JavaScript expression that evaluates to a boolean (true or false). This expression typically references a reactive data property defined in your Alpine component.
true, Alpine.js removes the inline style="display: none;" attribute from the element. This makes the element visible, reverting to its default display type (e.g., block, inline-block) or any display type set by your CSS.
false, Alpine.js adds an inline style="display: none;" attribute to the element, effectively hiding it and removing it from the document's layout flow.
<div x-data="{ isOpen: true }">
<button @click="isOpen = !isOpen">Toggle</button>
<p x-show="isOpen">This paragraph is visible when isOpen is true.</p>
</div>
Works with x-transition for animations:
x-show toggles visibility instantaneously.
x-show with x-transition directives. Alpine.js provides CSS classes that are applied during different phases of the transition (entering and leaving).
x-transition:enter: Applied during the entire enter phase.x-transition:enter-start: Applied at the beginning of the enter phase.x-transition:enter-end: Applied at the end of the enter phase.x-transition:leave: Applied during the entire leave phase.x-transition:leave-start: Applied at the beginning of the leave phase.x-transition:leave-end: Applied at the end of the leave phase.x-transition (default fade and scale), x-transition.opacity, x-transition.scale.
<div x-data="{ open: false }">
<button @click="open = !open">Toggle Content</button>
<div x-show="open"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0 transform scale-90"
x-transition:enter-end="opacity-100 transform scale-100"
x-transition:leave="transition ease-in duration-300"
x-transition:leave-start="opacity-100 transform scale-100"
x-transition:leave-end="opacity-0 transform scale-90">
Animated content!
</div>
</div>
Elements still occupying space when hidden with x-show if not display: none (Misconception Clarification):
This is a common point of confusion. x-show works by adding an inline style style="display: none;" to the element when it's hidden. This CSS property correctly removes the element from the document's layout flow, meaning it does not occupy any space.
If you observe an element still affecting layout when hidden with x-show, it's likely due to:
!important that override the inline display: none;. For example, if your stylesheet has .my-element { display: block !important; }, Alpine's display: none; will be overridden.
display: none; works compared to visibility: hidden;. visibility: hidden; hides the element but it still occupies its space in the layout. x-show uses display: none;, which is usually the desired behavior for toggling visibility and reflowing content.
In standard scenarios, x-show reliably removes the element from the layout flow.
Transitions not working without x-transition directives:
If you apply x-show to an element and expect it to animate smoothly without any additional directives, you'll find it appears and disappears abruptly.
Alpine.js requires you to explicitly define how an element should transition when its visibility is toggled by x-show. This is done using the x-transition family of directives (e.g., x-transition, x-transition:enter, x-transition:leave, etc.). These directives tell Alpine.js which CSS classes to apply during the "enter" (becoming visible) and "leave" (becoming hidden) phases. You then define your transition effects (like opacity, transform, height) using these CSS classes.
Without these x-transition directives, Alpine.js simply toggles the display: none; style, resulting in an immediate change.
Over-using x-show for elements that should be completely removed:
While x-show is excellent for quickly toggling visibility, it's important to understand its behavior: it only hides elements using CSS (display: none;). The element itself, along with its children and any Alpine components or event listeners within it, remains in the DOM.
For situations where:
...the x-if directive might be a more appropriate choice. x-if completely removes the element from the DOM when its condition is false and re-adds it (and re-initializes it) when true.
Choose x-show for frequent, lightweight toggles where the element's presence in the DOM (though hidden) is acceptable. Choose x-if for more significant conditional rendering, especially if performance or accessibility of hidden complex trees is a concern.
This example demonstrates an accordion component. Click on a question to reveal its answer. The visibility of the answer panel is controlled by x-show, and smooth transitions are implemented using x-transition.
x-show toggles the display: none; style. For smooth transitions, you add x-transition directives. These directives apply CSS classes (which you define with Tailwind or custom CSS) during the element's "enter" (becoming visible) and "leave" (becoming hidden) phases. For example, x-transition:enter-start="opacity-0" sets opacity to 0 at the start of the enter transition.
) and Alpine's default x-transition.
Notice how it smoothly fades and scales in and out without needing detailed enter/leave classes.
Active accordion panel ID:
Simple toggle state: