Seasonal and event themes for your FiveM loading screen

9 min read5 sections · 4 questions answered
Short answer

Keep one loading screen and switch its theme by date: a small JavaScript table of date ranges picks the background, accent colour, music and headline. Store only the assets for active themes, compress them like any other background, draw snow or particles on a single lightweight canvas, and use the theme to announce events and updates.

A loading screen that changes with the seasons tells players the server is alive and cared for. A snowy December, an orange October or a countdown to a big update all cost little — as long as the theme switch is automatic and the extra assets do not slow down every join.

A simple theme calendar

PeriodTheme ideaAccent
DecemberSnow, lights, winter city shotsIcy blue or red
Late OctoberHalloween, fog, night shotsOrange
SummerBeach, Vespucci, sunsetsWarm yellow
Server anniversaryThrowback screenshots, thank-you messageYour brand colour
Big update weekTeaser of the new featureYour brand colour

Switching by date

theme.js
const THEMES = [
  { name: 'winter', from: '12-01', to: '12-31', bg: 'img/winter.webp', accent: '#7cc4ff', title: 'Happy holidays from Los Santos' },
  { name: 'halloween', from: '10-20', to: '11-01', bg: 'img/halloween.webp', accent: '#ff7a1a', title: 'Something is out there tonight…' },
];
const DEFAULT = { name: 'default', bg: 'img/city.webp', accent: '#4f8cff', title: 'Welcome to the city' };

function pickTheme(now = new Date()) {
  const md = String(now.getMonth() + 1).padStart(2, '0') + '-' + String(now.getDate()).padStart(2, '0');
  return THEMES.find((t) => md >= t.from && md <= t.to) || DEFAULT;
}

const theme = pickTheme();
document.documentElement.style.setProperty('--accent', theme.accent);
document.querySelector('.bg').style.backgroundImage = `url(${theme.bg})`;
document.querySelector('.title').textContent = theme.title;

The date comes from the player’s own clock, which is fine for themes. Ranges that cross New Year (for example 12-20 to 01-05) need two entries or a small extra check.

Keeping the download small

Everything in the loading screen resource is downloaded before it can show, and changed files are downloaded again. Compress seasonal backgrounds to WebP (a 1920×1080 image usually fits in 200–500 KB), remove themes you no longer use, and prefer one looping video over several. Sizes and formats are covered in image sizes and assets and loading screen performance.

Snow and particle effects

snow.js — one canvas, capped particles
const c = document.querySelector('#snow');
const ctx = c.getContext('2d');
const flakes = Array.from({ length: 120 }, () => ({ x: Math.random(), y: Math.random(), r: 1 + Math.random() * 2, s: 0.0006 + Math.random() * 0.0012 }));
let w = 0, h = 0;

function frame() {
  if (w !== innerWidth || h !== innerHeight) { w = c.width = innerWidth; h = c.height = innerHeight; }
  ctx.clearRect(0, 0, w, h);
  ctx.fillStyle = 'rgba(255,255,255,0.8)';
  for (const f of flakes) {
    f.y += f.s; if (f.y > 1) f.y = 0;
    ctx.beginPath(); ctx.arc(f.x * c.width, f.y * c.height, f.r, 0, Math.PI * 2); ctx.fill();
  }
  requestAnimationFrame(frame);
}
frame();

Using themes for announcements

  • A countdown or date for a holiday event.
  • A “new this week” line during an update.
  • Seasonal rules reminders (for example snow driving).
  • Links to your Discord event channel in the theme headline.

Music follows the same rules as always — only use tracks you have the right to play; see music and copyright.

Common questions

How do I make a Christmas loading screen for FiveM?

Add a winter theme (background, accent colour, headline, optional snow canvas) and switch to it by date in your loading screen’s JavaScript.

Can the theme change automatically?

Yes. Compare the current month and day with a table of date ranges when the page loads.

Do seasonal assets slow down joining?

Only if they are large. Every file is downloaded by every player, so compress images and remove unused themes.

Will a snow effect hurt performance?

Not if you use one canvas and cap the particle count. The page is removed when loading finishes, so the animation ends with it.

Want a loading screen you never have to debug?

Build it in the browser, export once, and edit it whenever — no HTML, no re-uploads.

Start free

More guides