🎮 How to Properly Prepare Graphics for Web Games and Applications
Overview
When a beginner developer creates a web game or an interface, they usually think only about making the image look beautiful. This is an understandable mistake. The user sees graphics, so it feels like appearance is the most important thing.
But the real performance of a web application depends on much more than beauty.
Poorly prepared graphics can cause:
- slow page loading
- high mobile traffic usage
- lags on weak devices
- unnecessary RAM usage
- increased CPU load
- increased GPU load
- extra HTTP requests
- high server load
- slowdowns even with a good internet connection
- poor project scalability
Good graphics architecture is not just “compressing images”. It is an engineering approach.
Let's go through the main principles.
1. Vector and Raster Graphics Are Different Tools
The first thing to understand is simple: not all graphics are the same.
Raster graphics are made of pixels.
Examples of raster formats:
- PNG
- JPEG
- WebP
- AVIF
If you enlarge a raster image too much, it loses quality.
Example:
You have an icon with a size of 32×32 pixels.
If you stretch it to 300×300, the result will be blurry and ugly.
Raster graphics work well for:
- game sprites
- characters
- game objects
- backgrounds
- textures
- artistic illustrations
- complex detailed graphics
Now let's look at vector graphics.
A vector image is not a set of pixels. It is a mathematical description of lines, curves, and shapes.
A typical example:
SVG
The advantage:
A vector image can be scaled almost infinitely without losing quality.
Vector graphics are excellent for:
- logos
- simple UI icons
- buttons
- diagrams
- interface elements
- simple decorative elements
A very common mistake:
“SVG is always better because it scales.”
This is wrong.
SVG is not magic.
If an SVG contains a complex scene with many paths, curves, and effects, the browser has to calculate and render all that geometry.
This can be much more expensive than simply displaying a ready image.
So the rule is simple:
- simple interface graphics → vector
- complex artistic game graphics → raster
The correct question is not “what is more modern?”, but “what is cheaper to render?”.
2. If the Browser Can Build It Itself — Do Not Send an Image
This is one of the most underestimated principles.
Before creating a graphic file, ask yourself:
Do I really need an image here?
A modern browser can do a lot by itself.
It can efficiently build:
- buttons
- borders
- rounded corners
- shadows
- gradients
- lines
- geometric shapes
- loading indicators
- text
- many simple icons
Bad solutions:
- button.webp
- shadow.png
- gradient.webp
- spinner.gif
- text_as_image.png
Why is this bad?
Because an image requires:
- a separate HTTP request
- network transfer
- decoding
- memory storage
- cache management
Browser built-in capabilities already exist for free.
Example.
Bad:
using PNG for a button with a background and rounded corners.
Correct:
using CSS:
- border-radius
- background
- linear-gradient
- box-shadow
Example with text.
A very bad practice:
making text as an image.
Why?
- it cannot be selected
- it cannot be searched
- it is bad for accessibility
- it is bad for SEO
- it is hard to localize
- it scales poorly
But there is an important nuance.
Do not turn this rule into a religion.
Sometimes browser rendering can be more expensive.
For example, when a decorative block is built using:
- many CSS layers
- blur
- filter
- masks
- complex SVG
In that case, a ready optimized bitmap can be faster.
The main principle:
do not send over the network what the browser can efficiently build itself.
3. Choose the Right Format
There is no universal best format.
Each format solves its own task.
PNG
Use it when you need:
- lossless graphics
- transparency
- pixel art
- sharp edges
- exact preservation of details
Disadvantage:
PNG is often very heavy.
WebP
In practice, this is one of the best universal choices for most web projects.
Advantages:
- transparency
- good compression
- much smaller than PNG
- good browser support
- support for lossy and lossless modes
Good for:
- sprites
- UI
- icons
- game objects
- most decorative elements
AVIF
AVIF provides even stronger compression.
But there are disadvantages:
- heavier decoding
- higher load on weak devices
- the benefit is not always worth it
Sometimes a small file loads quickly but decodes slowly.
JPEG
Use JPEG only for:
- photographs
- large background images
- photo content
Do not use JPEG for:
- UI
- transparent objects
- sprites
- icons
4. Do Not Store Images Larger Than Needed
This is one of the most common mistakes.
You have a button that is displayed as 64×64.
But the designer exported it as 2048×2048.
What happens?
The browser:
- downloads a huge file
- decodes it
- stores it in memory
- then scales it down to a small size
This is an absolutely meaningless waste of resources.
The correct approach:
the file size should be close to the real display size.
Bad:
1024×1024 → displayed as 48×48
Good:
64×64 → displayed as 64×64
5. Consider HiDPI / Retina
Modern displays have high pixel density.
So an image that looks normal on an old monitor can look blurry on a modern device.
A typical approach:
- 1x version
- 2x version
Example:
icon.webp
icon@2x.webp
But this does not mean that you should blindly double everything.
Look at real usage.
6. Crop Empty Space
Transparent space is still data.
Mistake:
a character occupies 100×100, but is exported as 1000×1000 with transparent borders.
Problems:
- larger file
- more memory usage
- the GPU processes more data
- alpha blending becomes heavier
A transparent pixel is not free.
7. Combine Small Assets
A very common mistake:
storing dozens of small files.
For example:
- king.webp
- queen.webp
- rook.webp
- bishop.webp
- pawn.webp
Why is this bad?
Because every file is a separate request.
Even if the file is small.
Every request includes:
- DNS
- TCP/TLS
- HTTP headers
- server-side processing
- cache checks
- browser bookkeeping
- decode startup
100 files of 5 KB can be worse than one 500 KB file.
Useful solutions:
- sprite sheets
- atlases
- combined assets
8. Polling Kills Server Performance
This is a very important architectural point.
Suppose the client makes:
GET /check_status
every 2 seconds.
If you have 1000 players:
500 requests per second
If each client separately asks for:
- timer
- chat
- notifications
- inventory
- game state
you already get thousands of requests.
Even if the responses are small, every request starts:
- routing
- authentication
- session handling
- database access
- SQL execution
- JSON serialization
This is expensive.
Bad:
- /get_timer
- /get_chat
- /get_state
- /get_notifications
Better:
/game_sync
Even better:
- WebSocket
- SSE
API architecture affects performance no less than graphics.
9. Runtime Memory Is More Important Than File Size
This is a very important point that beginners often do not understand.
File:
100 KB WebP
After decoding:
it can occupy megabytes of memory.
Why?
The GPU does not work with a compressed file.
The GPU works with raw texture data.
Downloaded file size and real memory consumption are different things.
10. Lossy and Lossless
Lossless:
- perfect quality
- large size
Lossy:
- small quality loss
- huge size savings
For many game assets, the visual difference is almost invisible.
You should not fanatically use lossless everywhere.
11. Do Not Force the Browser to Constantly Scale Images
If an image is constantly being scaled:
- the CPU works more
- the GPU works more
- rendering becomes heavier
This is especially critical for:
- canvas
- animations
- realtime rendering
12. Preload Important Assets
Bad scenario:
the player triggers an explosion effect for the first time.
And only at that moment the file starts loading.
Result:
freeze
Correct:
preload before the match starts.
13. Use Caching
Without caching, the browser will repeatedly load the same resources.
Use:
- Cache-Control
- versioned filenames
- immutable caching
Example:
piece.8f3c1.webp
14. Power-of-Two Textures
Classic sizes:
- 64×64
- 128×128
- 256×256
- 512×512
Today this is not always required.
But sometimes it is useful for:
- mipmaps
- GPU optimization
- compatibility
15. Separate Source Files and Production Assets
Do not send users:
- PSD
- Krita project files
- huge PNG files
- designer source files
Pipeline:
source → export → optimize → deploy
16. Animation Also Costs Resources
Frame-by-frame animation:
more expensive.
Transform animation:
usually cheaper.
For example:
- translate()
- scale()
- rotate()
These are often better than constantly changing a bitmap.
17. Measure, Do Not Guess
Not:
“I think it is faster.”
Check it.
Tools:
- Chrome DevTools
- Network
- Performance
- Lighthouse
- Memory profiler
18. Final Thoughts: Graphics Optimization Is Architecture, Not Just Images
The main beginner mistake:
thinking that graphics optimization simply means reducing image size.
In reality, the correct process starts much earlier.
You need to ask the right questions:
- Do I need an image at all?
- Can the browser build this element itself?
- Do I need vector or raster?
- Which format should I choose?
- How many HTTP requests will this create?
- How will this affect polling?
- What load will this create on the server?
- How much memory will it occupy after decoding?
- How will it affect the CPU?
- How will it affect the GPU?
- How will it behave on mobile devices?
A fast web game is not a set of beautiful pictures.
It is competent system engineering.
