TUTORIALLOADING SCREENHTMLCSSNUICUSTOMIZATIONSERVER BRANDINGBEGINNER GUIDEFIVEM LOADING SCREENHOW-TO April 27, 2026 · 12 min read

How to Create a FiveM Loading Screen

Your server’s loading screen is the first thing every player sees. If it’s the default black screen with a progress bar, you’re wasting one of the easiest branding opportunities you have. A custom loading screen takes maybe an hour to build, costs nothing, and immediately makes your server feel more polished.

I’ve built loading screens for my own servers and for clients, and the process is simpler than most people think. It’s just HTML, CSS, and a little JavaScript — no Lua, no framework dependency, nothing fancy. If you can copy and paste code, you can do this.

How FiveM Loading Screens Work

Before touching any code, here’s what’s happening under the hood. When a player connects to your server, FiveM displays a web page while resources download in the background. That web page is your loading screen. It’s rendered using the Chromium Embedded Framework (CEF) — the same tech behind NUI panels in scripts.

This means your loading screen is literally a website. You can use HTML, CSS, JavaScript, images, videos, audio — anything a browser can render. FiveM also provides an adaptive card system that feeds real-time server information (player count, server name, loading progress) into your page.

The loading screen is a standalone resource. It doesn’t depend on ESX, QBCore, Qbox, or any framework. If you’ve never installed a resource before, check out the script installation guide — the process is the same.

Setting Up the Resource

Create a new folder in your server’s resources directory. I’ll call it loadscreen, but name it whatever you want.

resources/
└── loadscreen/
    ├── fxmanifest.lua
    ├── index.html
    ├── style.css
    ├── script.js
    └── assets/
        ├── logo.png
        └── background.jpg

Your fxmanifest.lua is minimal for a loading screen:

fx_version 'cerulean'
game 'gta5'

loadscreen 'index.html'

files {
    'index.html',
    'style.css',
    'script.js',
    'assets/logo.png',
    'assets/background.jpg'
}

The key line is loadscreen 'index.html'. This tells FiveM to use this resource as the loading screen. You don’t use client_script or server_script here — this isn’t a normal resource.

Every file your HTML references must be listed in the files block. If you add a font, a new image, or a music file later, add it to this list. FiveM won’t serve files that aren’t declared here. I’ve seen people spend hours debugging a blank loading screen because they forgot to add their CSS file to the manifest.

Now add it to your server.cfg:

ensure loadscreen

Put it near the top of your config, before your framework and other resources. It doesn’t technically matter where it starts since it runs during the loading phase, but keeping it early is good practice.

Building the HTML

Here’s a clean starting point. Nothing fancy — just a background, logo, server name, and a loading indicator.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>Loading</title>
</head>
<body>
    <div class="overlay">
        <div class="content">
            <img src="assets/logo.png" alt="Server Logo" class="logo">
            <h1 class="server-name">Your Server Name</h1>
            <p class="tagline">The best RP experience in the city.</p>
            <div class="loading-bar-container">
                <div class="loading-bar" id="loadingBar"></div>
            </div>
            <p class="loading-text" id="loadingText">Connecting...</p>
        </div>
    </div>
    <script src="script.js"></script>
</body>
</html>

Nothing groundbreaking. The important stuff is in the CSS and JavaScript.

Styling It

Here’s CSS that gives you a fullscreen background with a centered content block and animated loading bar:

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    width: 100vw;
    height: 100vh;
    overflow: hidden;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background: url('assets/background.jpg') center center / cover no-repeat;
    color: #ffffff;
}

.overlay {
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.6);
    display: flex;
    align-items: center;
    justify-content: center;
}

.content {
    text-align: center;
    max-width: 600px;
    padding: 40px;
}

.logo {
    width: 150px;
    height: auto;
    margin-bottom: 20px;
}

.server-name {
    font-size: 2.5rem;
    font-weight: 700;
    margin-bottom: 8px;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
}

.tagline {
    font-size: 1rem;
    opacity: 0.7;
    margin-bottom: 40px;
}

.loading-bar-container {
    width: 100%;
    height: 4px;
    background: rgba(255, 255, 255, 0.15);
    border-radius: 2px;
    overflow: hidden;
    margin-bottom: 16px;
}

.loading-bar {
    width: 0%;
    height: 100%;
    background: linear-gradient(90deg, #4a90d9, #67b8f7);
    border-radius: 2px;
    transition: width 0.3s ease;
}

.loading-text {
    font-size: 0.85rem;
    opacity: 0.6;
}

A few things worth noting. The overflow: hidden on body prevents scrollbars — you don’t want players accidentally scrolling your loading screen. The dark overlay on top of the background image makes text readable regardless of what image you use. And the loading bar is just a div inside a div — JavaScript will handle the width.

Pick a background image that fits your server’s theme. A screenshot from your server works, or grab something from a free stock site. Keep it under 500KB if you can — players are already downloading your resources, don’t make them download a 5MB background on top of that.

Adding Real Loading Progress

FiveM sends loading progress data through a system called adaptive cards. Your JavaScript can listen for these events and update the UI accordingly.

const loadingBar = document.getElementById('loadingBar');
const loadingText = document.getElementById('loadingText');

const handlers = {
    startInitFunction(data) {
        loadingText.textContent = 'Loading game...';
    },

    startDataFileEntries(data) {
        loadingText.textContent = `Loading ${data.count} data files...`;
    },

    performMapLoadFunction(data) {
        loadingText.textContent = 'Loading map...';
    },

    onLogLine(data) {
        // You can parse log lines if you want detailed status
        // Most people just ignore these
    }
};

window.addEventListener('message', (event) => {
    if (handlers[event.data.eventName]) {
        handlers[event.data.eventName](event.data);
    }
});

// Fake progress animation as fallback
// Real progress events from FiveM are inconsistent,
// so a smooth animation feels better than a jumpy bar
let progress = 0;
const progressInterval = setInterval(() => {
    if (progress < 90) {
        progress += Math.random() * 2;
        loadingBar.style.width = Math.min(progress, 90) + '%';
    }
}, 500);

Here’s the honest truth about loading progress: FiveM’s progress events are not linear and they don’t cover 100% of the loading process reliably. The events fire at specific stages (data file loading, map loading, etc.), but there’s no single “you are 47% done” number you can rely on.

That’s why most loading screens — including mine — use a fake progress bar that slowly fills to about 90% and then waits. It feels smooth to the player, which is what actually matters. When loading finishes, FiveM removes the loading screen automatically.

Adding Music

Background music is the most requested loading screen feature. Drop an audio file in your assets folder, declare it in fxmanifest.lua, and add it to your HTML:

<audio id="bgMusic" loop autoplay>
    <source src="assets/music.mp3" type="audio/mpeg">
</audio>

Then in your JavaScript, add a volume control and a mute button:

const music = document.getElementById('bgMusic');
music.volume = 0.3; // Don't blast people's ears

// Optional: add a mute toggle
document.addEventListener('keydown', (e) => {
    if (e.key === 'm' || e.key === 'M') {
        music.muted = !music.muted;
    }
});

Keep the volume low by default. Nothing makes a worse first impression than deafening music when someone joins your server at 2 AM. I set mine to 0.3 and let players mute with M. Some developers add a visible mute button in the UI — that’s even better.

For the audio file itself, keep it under 2MB. Use MP3 format at 128kbps — anything higher is wasted on a loading screen. And pick something that loops cleanly. A track with a hard cut at the loop point sounds amateur.

Important licensing note: don’t use copyrighted music. FiveM servers are public-facing and Cfx.re has cracked down on this before. Use royalty-free music from sites like Pixabay, Uppbeat, or the YouTube Audio Library.

Showing Server Information

You can display dynamic server info using FiveM’s adaptive card data or by hardcoding it. For most servers, hardcoding is fine — your Discord link and server rules don’t change during loading.

But if you want to show live player count or the server name pulled from your config, you can use the handover data FiveM provides:

window.addEventListener('message', (event) => {
    if (event.data.type === 'handover') {
        const serverData = event.data;
        // serverData contains information passed from the server
        // You can display server name, player count, etc.
    }
});

Most server owners just hardcode their info and update it manually when things change. That’s perfectly fine. Don’t over-engineer your loading screen.

A useful addition is showing your server rules or a tips rotation:

const tips = [
    "Use /report to contact staff in-game.",
    "Check our Discord for the latest updates.",
    "New Life Rule: You can't return to where you died.",
    "Always stay in character in RP zones.",
    "Support the server at our Tebex store."
];

let tipIndex = 0;
setInterval(() => {
    tipIndex = (tipIndex + 1) % tips.length;
    loadingText.textContent = tips[tipIndex];
}, 5000);

This keeps players engaged during long loading times and pre-loads them with information they’ll need once they’re in-game.

Common Mistakes and How to Avoid Them

Blank loading screen: 99% of the time this is a missing file in your fxmanifest.lua. Every image, CSS file, JS file, and font must be listed in the files block. Check your F8 console for errors — it’ll tell you exactly which file it couldn’t find.

Loading screen never goes away: This usually means you have a JavaScript error that’s crashing the page. Open your server’s loading screen URL directly in a browser (it shows in your server console when it starts) and check the browser console for errors.

Huge file sizes: I’ve seen loading screens with 20MB background videos. Your loading screen files are downloaded before anything else renders. A 20MB video means players stare at a black screen for an extra 10-30 seconds before your beautiful loading screen even appears. Keep total assets under 2-3MB. If you want a video background, compress it aggressively — 720p at low bitrate looks fine for a background.

Text unreadable on different backgrounds: Always use that dark overlay. If you’re using a video or slideshow background, the overlay ensures text stays readable regardless of what’s behind it. Don’t rely on text shadows alone.

Not testing on slow connections: Your loading screen should look good even before all assets load. Set your background color to something that matches your theme so the transition from blank to loaded isn’t jarring. Add background-color: #1a1a2e (or whatever fits) as a fallback on your body element.

Going Further — Video Backgrounds and Animations

If you want a video background instead of a static image, swap the body background for a video element:

<video autoplay muted loop class="bg-video">
    <source src="assets/background.mp4" type="video/mp4">
</video>
.bg-video {
    position: fixed;
    top: 50%;
    left: 50%;
    min-width: 100%;
    min-height: 100%;
    transform: translate(-50%, -50%);
    z-index: -1;
    object-fit: cover;
}

Keep the video short (15-30 seconds), looping, and compressed. H.264 codec in an MP4 container works everywhere. Aim for 720p resolution and under 2MB file size — you’ll need to drop the bitrate significantly, but remember this is playing behind a dark overlay. Fine detail doesn’t matter.

For CSS animations, subtle is better. A slow fade-in on your content, a gentle pulse on the loading bar, maybe a slight parallax effect. Don’t go overboard with animations — they eat CPU, and the player’s machine is already busy loading your server resources.

.content {
    animation: fadeIn 1.5s ease forwards;
}

@keyframes fadeIn {
    from { opacity: 0; transform: translateY(20px); }
    to { opacity: 1; transform: translateY(0); }
}

.loading-bar {
    animation: pulse 2s ease-in-out infinite;
}

@keyframes pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.7; }
}

Performance Considerations

Your loading screen runs while FiveM is downloading and processing resources. If your loading screen itself is resource-heavy, you’re making loading times worse.

Follow these rules and you’ll be fine. Keep total asset size under 3MB. Avoid heavy JavaScript frameworks — you don’t need React for a loading screen. Don’t run expensive animations or particle effects. Compress images with tools like TinyPNG before adding them. Use CSS animations instead of JavaScript-driven animations where possible.

If you want to go deeper on performance monitoring and optimization in general, the resmon performance guide covers the tools and techniques you’ll use for your entire server, not just the loading screen.

Using Pre-Built Loading Screens

Not everyone wants to build from scratch, and that’s fine. There are free and premium loading screens available. Some of the premium ones on our store and other marketplaces include features like live player counts, staff lists, dynamic backgrounds, and music players with volume sliders — stuff that takes time to build yourself.

You can also check out our free scripts collection for open-source resources you can use as a starting point and modify to fit your needs.

Whether you build or buy, the important thing is that your loading screen matches your server’s branding. A generic loading screen on a server with a custom everything else looks inconsistent.

Connecting It All Together

Your loading screen is part of your server’s first impression pipeline. It works alongside your server setup, your installed scripts, and your overall server branding to create the experience players remember.

If you’re still building out your server, check out the must-have scripts guide for what to install alongside your new loading screen. And if you want to learn how the scripting side works — maybe to add custom features to your loading screen’s JavaScript — the Lua scripting tutorial is a solid place to start, even though loading screens are HTML/JS rather than Lua.

Got questions or want to show off your loading screen? Drop by the YBN Scripts Discord — there’s always people building cool stuff.

YBN
YBN Scripts
FiveM script developer at YBN. Building premium ESX, QBCore & Qbox resources.

Related Posts

Need scripts for your server?

Check out our premium FiveM resources — ESX, QBCore & Qbox supported.

Browse Premium Scripts → Free Scripts →