Skip to content

Instantly share code, notes, and snippets.

@kothawadepranali
Created November 8, 2025 09:12
Show Gist options
  • Select an option

  • Save kothawadepranali/8d842a8bd5fa3b36d1fd1c58397f421b to your computer and use it in GitHub Desktop.

Select an option

Save kothawadepranali/8d842a8bd5fa3b36d1fd1c58397f421b to your computer and use it in GitHub Desktop.
πŸŽ‰ ServiceNow Seasonal Emoji Widget β€” Add a touch of festive animation to your Service Portal with pure CSS & JavaScript!

πŸŽ‰ ServiceNow Seasonal Emoji Widget

Bring festive energy to your ServiceNow Service Portal with this lightweight widget!
It displays falling seasonal emojis (πŸŽƒ ❄️ 🍁 πŸŽ†) that change automatically based on the month β€” adding fun, motion, and seasonal charm to your portal 🎊

Built entirely with HTML + CSS + JavaScript, this widget is easy to integrate and 100% client-side.


✨ Features

  • 🌦️ Automatic month detection β€” emojis switch seasonally
  • πŸ’¨ Smooth animations β€” natural falling & swaying effects
  • 🧩 No external libraries β€” pure CSS & JS
  • ♻️ DOM cleanup β€” removes emojis after animation to stay lightweight
  • 🎨 Customizable β€” change emoji sets, fall speed, size, or count

βš™οΈ How It Works

It dynamically creates multiple .faller elements positioned randomly across the viewport.

Each emoji:

  • Uses CSS keyframes fall (vertical motion) and sway (horizontal drift)
  • Moves down the screen naturally while gently swaying side-to-side
  • Fades out gracefully once the fall animation completes
  • Gets removed from the DOM after animation ends to keep things clean and performant

Example Logic

if (month === 10) { emojis = ["πŸŽƒ", "πŸ‘»", "πŸ‚"]; }   // October  
else if (month === 11) { emojis = ["🍁", "πŸ‚"]; }    // November  
else if (month === 12) { emojis = ["❄️", "β˜ƒοΈ"]; }   // December  
else if (month === 1)  { emojis = ["πŸŽ†", "πŸŽ‰"]; }    // January

🧩 How to Use in ServiceNow

Follow these steps to add the widget to your Service Portal:

  1. Navigate to Service Portal β†’ Widget Editor
  2. Click β€œCreate a new widget”
    • Example name: Seasonal Emoji Effect
  3. Copy and paste:
    • The <style> section β†’ into the CSS field
    • The <div> section β†’ into the HTML Template field
    • The <script> section β†’ into the Client Script field
  4. Save your widget
  5. Add it to your Service Portal homepage or any desired page layout
  6. Refresh the page β€” enjoy your seasonal animation! πŸŽ‰

πŸ’‘ For testing, you can override the current month to preview different seasons:

var month = 12; // Force December emojis

🧠 Customization Options

Option Description Example
emojis Change emoji sets by month Valentine’s β†’ πŸ’–πŸŒΉπŸ’˜
animation-duration Adjust fall speed 10–15s recommended
font-size Control emoji size Default: 1.5em
.faller:nth-of-type() Adjust number of falling emojis Add/remove for more or fewer emojis

πŸ“š Technical Notes

βœ… 100% client-side β€” no backend dependencies
βœ… Works across Chrome, Edge, Firefox, Safari
βœ… Mobile and tablet friendly
βœ… Automatically removes finished animations for performance
βœ… No external scripts or libraries required


🧩 Example Folder Structure (if using GitHub repo)

servicenow-seasonal-emoji-widget/
β”œβ”€β”€ README.md
β”œβ”€β”€ demo/
β”‚   └── demo.gif
└── servicenow-seasonal-emoji-widget.html

🀝 Contribute

Got creative ideas for new seasonal effects?
Fork or copy this Gist and try your own:

  • πŸŽ„ Christmas sparkle effect
  • πŸ’– Valentine hearts fall
  • 🌸 Spring blossoms theme
  • πŸ•ΆοΈ Summer vibes animation

Let’s make ServiceNow portals more fun and engaging together! πŸš€


πŸ‘‹ Connect

If you try this widget or adapt it for your own ServiceNow portal, tag me on LinkedIn β€”
I’d love to see how you’ve brought seasonal flair to your Service Portal!

⭐ If you found this useful, star or share this Gist so others can add seasonal magic to their portals too!

<style>
/* Smooth, natural falling animation */
.faller, .faller .inner {
animation-play-state: running;
}
/* Fall animation (vertical) */
@keyframes fall {
0% { transform: translateY(0) translateX(0); opacity: 1; }
100% { transform: translateY(110vh) translateX(60px); opacity: 0.9; }
}
/* Side sway (horizontal) */
@keyframes sway {
0%,100% { transform: translateX(0); }
50% { transform: translateX(60px); }
}
/* Parent container that provides side-sway */
.faller {
position: fixed;
top: -10%;
z-index: 9999;
user-select: none;
pointer-events: none;
cursor: default;
animation-name: sway;
animation-duration: 6s;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite; /* keep swaying while fall runs */
}
/* The falling emoji */
.faller .inner {
animation-name: fall;
animation-timing-function: linear;
animation-iteration-count: 1; /* fall only once */
animation-fill-mode: forwards; /* keep final position when done */
font-size: 1.5em;
transition: opacity 0.9s ease-out; /* fade out when finished */
}
/* Evenly spaced across the viewport (per-faller delays & durations) */
.faller:nth-of-type(1) { left: 2%; animation-delay: 0s; }
.faller:nth-of-type(1) .inner { animation-delay: 1s; animation-duration: 14s; }
.faller:nth-of-type(2) { left: 10%; animation-delay: 1s; }
.faller:nth-of-type(2) .inner { animation-delay: 2s; animation-duration: 13s; }
.faller:nth-of-type(3) { left: 18%; animation-delay: 1.5s; }
.faller:nth-of-type(3) .inner { animation-delay: 3s; animation-duration: 12s; }
.faller:nth-of-type(4) { left: 26%; animation-delay: 2s; }
.faller:nth-of-type(4) .inner { animation-delay: 1s; animation-duration: 15s; }
.faller:nth-of-type(5) { left: 34%; animation-delay: 1s; }
.faller:nth-of-type(5) .inner { animation-delay: 2s; animation-duration: 14s; }
.faller:nth-of-type(6) { left: 42%; animation-delay: 0.5s; }
.faller:nth-of-type(6) .inner { animation-delay: 3.5s; animation-duration: 13s; }
.faller:nth-of-type(7) { left: 50%; animation-delay: 2s; }
.faller:nth-of-type(7) .inner { animation-delay: 4s; animation-duration: 15s; }
.faller:nth-of-type(8) { left: 58%; animation-delay: 1.5s; }
.faller:nth-of-type(8) .inner { animation-delay: 3s; animation-duration: 12s; }
.faller:nth-of-type(9) { left: 66%; animation-delay: 1s; }
.faller:nth-of-type(9) .inner { animation-delay: 5s; animation-duration: 14s; }
.faller:nth-of-type(10) { left: 74%; animation-delay: 2.5s; }
.faller:nth-of-type(10) .inner { animation-delay: 2.5s; animation-duration: 13s; }
.faller:nth-of-type(11) { left: 82%; animation-delay: 1s; }
.faller:nth-of-type(11) .inner { animation-delay: 3.5s; animation-duration: 14s; }
.faller:nth-of-type(12) { left: 90%; animation-delay: 2s; }
.faller:nth-of-type(12) .inner { animation-delay: 2s; animation-duration: 13s; }
.faller:nth-of-type(13) { left: 98%; animation-delay: 0.5s; }
.faller:nth-of-type(13) .inner { animation-delay: 4.5s; animation-duration: 15s; }
</style>
<div id="seasonalEffect" aria-hidden="true"></div>
<script>
(function() {
var month = new Date().getMonth() + 1;
// var month = 12;
var emojis = [];
// Seasonal sets
if (month === 10) { emojis = ["πŸŽƒ", "πŸ‘»", "πŸ‚"]; } // Oct
else if (month === 11) { emojis = ["🍁", "πŸ‚"]; } // Nov
else if (month === 12) { emojis = ["❄️", "β˜ƒοΈ"]; } // Dec
else if (month === 1) { emojis = ["πŸŽ†", "πŸŽ‰"]; } // Jan
if (emojis.length === 0) return; // nothing to show
var container = document.getElementById("seasonalEffect");
for (let i = 0; i < 13; i++) {
const faller = document.createElement("div");
faller.className = "faller";
const inner = document.createElement("div");
inner.className = "inner";
inner.textContent = emojis[i % emojis.length]; // rotate emojis
/* Listen for the fall animation end.
Only react when the finished animation is the 'fall' animation.
*/
inner.addEventListener('animationend', function (e) {
// debug (remove in production)
console.log('animationend for', this.textContent, 'name=', e.animationName);
if (e.animationName !== 'fall') return; // ignore other animations
// stop parent sway so it doesn't keep animating
if (faller && faller.style) faller.style.animationPlayState = 'paused';
// fade out the emoji
this.style.opacity = '0';
// remove the element (parent) after fade completes
setTimeout(function () {
if (faller && faller.parentElement) faller.parentElement.removeChild(faller);
}, 1000); // should match CSS transition time (0.9s)
}, { once: true }); // run once per element
faller.appendChild(inner);
container.appendChild(faller);
}
})();
</script>
@stnl22
Copy link

stnl22 commented Nov 9, 2025

very informative

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment