Spoiler alert: I'm author of Grains.js. If you missed my previous article on Grains.js, please check it out here.
Now I want to show how to use g-class
directive for switching classes dynamically based on state. If you're building interactive UIs with plain HTML and want smooth transitions, animations, or dynamic styling โ without using a full JS framework โ then you'll love how g-class
directive works in Grains.js.
Letโs dive into a real-world example.
Note: It's best to utilize TailwindCSS to use ready-made styles via their classes.
g-class
directive has nothing to do with TailwindCSS, however. It only switches class names based on state. After that, you can use whatever you want.
โจ Animated Notification Example
Weโll build a notification box with:
- Visibility toggle
- Error/success state styles
- Shake animation for emphasis
You can try the live demo here.
You can see updated list of examples at https://github.com/mk0y/grains.js/tree/main/examples.
โ Setup
Add Grains.js and TailwindCSS to your page:
<script defer src="https://mk0y.github.io/grains.js/dist/grains.min.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
Remember, using cdn.tailwindcss.com
is not for production environments. I'm using it only for presentational purposes - you should build your css file instead.
Next, add a simple @keyframes
animation for shake:
<style>
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-5px); }
75% { transform: translateX(5px); }
}
.shake {
animation: shake 0.5s ease-in-out;
}
</style>
๐ง The Markup
<div
g-state="notifications"
g-init='{"isVisible": false, "isError": false, "isShaking": false}'
>
<div
g-class="[
'transform transition-all duration-300 ease-in-out',
'p-4 rounded-lg shadow-lg mb-4',
isVisible && 'translate-y-0 opacity-100',
!isVisible && 'translate-y-4 opacity-0',
isError && 'bg-red-100 text-red-700',
!isError && 'bg-green-100 text-green-700',
isShaking && 'shake'
]"
>
<p class="font-medium">Notification Message</p>
</div>
<div class="space-x-2">
<button g-on:click="toggleVisibility">Toggle Visibility</button>
<button g-on:click="toggleError">Toggle Error State</button>
<button g-on:click="triggerShake">Shake Animation</button>
</div>
</div>
โ๏ธ State Changers
Grains.js uses global pure functions to update state. Hereโs how we control the behavior:
<script>
window.toggleVisibility = (ctx) => {
ctx.set({ isVisible: !ctx.get("isVisible") });
};
window.toggleError = (ctx) => {
ctx.set({ isError: !ctx.get("isError") });
};
window.triggerShake = (ctx) => {
ctx.set({ isShaking: true });
setTimeout(() => ctx.set({ isShaking: false }), 500);
};
</script>
๐ก How g-class Works
- You pass an array of strings or expressions.
- Only truthy values are included in the final class list.
- This makes toggling animations, colors, and layout transitions declarative and simple.
In the example above, when isVisible
is true
, classes like translate-y-0
and opacity-100
are added. When false, it falls back to a faded, translated state โ giving a nice slide/fade transition.
๐ Wrap-Up
The g-class
directive in Grains.js makes conditional styling effortless, and when combined with Tailwind and a few keyframes, you can build delightful UI transitions in plain HTML โ no frameworks or build steps required.
๐ Please let me know what you'd like to change or add as a next feature in the comments.
Thank you!
Top comments (0)