DEV Community

loading...

Alpine.js: responsive x-cloak

hus_hmd profile image Hussein Al Hammad ・1 min read

When using Alpine.js the x-cloak attribute is removed from DOM elements when Alpine is initialised. As noted in the docs, this makes it useful for hiding elements until Alpine is initialised:

x-cloak attributes are removed from elements when Alpine initializes. This is useful for hiding pre-initialized DOM. It's typical to add the following global style for this to work:

<style>
  [x-cloak] { display: none; }
</style>

You may want to hide pre-initialised DOM on some screen sizes, but not others. A good example for this is the links in a site's navigation bar, which are typically hidden by default on smaller screen sizes, but are always visible on wider screens.

So instead of hiding all elements with the x-cloak attribute, we can hide only the ones whose x-cloak attribute has no value:

[x-cloak=""] { display: none; }
Enter fullscreen mode Exit fullscreen mode

This allows us to target elements whose x-cloak attribute has a value:

[x-cloak="some-value"] { }
Enter fullscreen mode Exit fullscreen mode

So now we can write CSS rules targeting elements whose x-cloak value is mobile, tablet, desktop:

/* always hidden */
[x-cloak=""] { display: none; }

/* hidden on mobile/smaller screens */
@media screen and (max-width: 768px) {
    [x-cloak="mobile"] { display: none; }
}
Enter fullscreen mode Exit fullscreen mode

Discussion (5)

Collapse
makingthings profile image
James Grubb

Hi Hussein. Thanks for this. Could you show how I should set up my HTML using x-cloak? Thanks in advance

Collapse
hus_hmd profile image
Hussein Al Hammad Author

Hi James, you would add x-cloak as an attribute to a HTML element:

<div x-cloak>
    <!-- this element is hidden until Alpine is initialised -->
</div>

If you're following the example in the blog post:

<div x-cloak="mobile"></div>

Here's Alpine.js's documentation, which is really good:
github.com/alpinejs/alpine#x-cloak

Collapse
makingthings profile image
James Grubb

Hi Hussein, thanks so much for getting back to me. I'm being a little slow on the uptake here and really would like to understand the benefits. Please bear with me. Would you mind elaborating a little more on using x-cloak within a media query? I guess in your initial post both your queries returned display: none and I was a little confused as to how to use this

//css
.hidden{
  display: none;
}
[x-cloak=""]{
  display: none;
}
[x-cloak="tablet"]{
  color: red;
}

//html

<div class="wrapper" x-data="{'isOpen' : true}">
  <h1 x-cloak :class="{'hidden': isOpen}">Hello</h1>
  <h2 x-cloak="tablet">World</h2>
</div>


Thread Thread
hus_hmd profile image
Hussein Al Hammad Author

Sure thing. Perhaps the post was light on the possible use-cases for this.

Firstly to recap, x-cloak is an attribute that Alpine.js removes from HTML elements once it is initialised. So you have the following phases:

  1. HTML is rendered in the browser, Alpine.js is yet to initialise. HTML elements still have the x-cloak attribute.
  2. Alpine.js is initialised. Alpine.js removes the x-cloak attribute from HTML elements.

So during (1), [x-cloak=""] styles are applied. During (2), they are no longer applied to the elements because the elements no longer have the x-cloak attribute.

A user with a slow internet connection for instance may view a page in phase (1) for some time. During this time you may not want to hide some elements by default.

Taking the dropdown example from Alpine's docs:

<div x-data="{ open: false }">
    <button @click="open = true">Open Dropdown</button>

    <ul
        x-show="open"
        @click.away="open = false"
    >
        Dropdown Body
        <!-- this ul is visible during phase (1) -->
    </ul>
</div>

If we apply x-cloak to the <ul>, we can hide it during phase (1):

<div x-data="{ open: false }">
    <button @click="open = true">Open Dropdown</button>

    <ul
        x-cloak
        x-show="open"
        @click.away="open = false"
    >
        Dropdown Body
        <!-- this ul is NOT visible during phase (1) -->
    </ul>
</div>

In the example of a dropdown, such a component typically behaves in an identical way across different screen sizes.

However, for some components you may want to have some elements hidden during phase (1) only on some screen sizes. A common example is the main navigation bar of a website where you have the links displayed by default on larger screens, but want to have them hidden on smaller screens. In other words, the initial state for the element is not identical across screen sizes. This is where [x-cloak="mobile"] can be useful.

Note that this is useful if you are toggling display with Alpine (e.g. with x-show):

<div x-show="open" x-cloak="mobile"></div>

If you are using Alpine to toggle CSS classes you may not need this as your CSS may already handle this:

<style>
    @media screen and (max-width: 768px) {
        .example:not(.active) {
            display: none;
        }
    }
</style>

<div class="example" :class="{'active': open}"></div>
Thread Thread
makingthings profile image
James Grubb

Hi Hussein, I realised I did not get to thank you for your follow up post. I really appreciate your time and I am very grateful. Cheers, James.

Forem Open with the Forem app