Image Assets: SVGs vs. Rasters
Image assets in Gameface should be selected based on the shape of the artwork and the amount of runtime control the UI needs.
Use SVGs for simple scalable graphics, such as icons, logos, dividers, and HUD frames. Use raster images , such as PNGs, for detailed painted artwork, portraits, screenshots, and textures where vector path evaluation would add unnecessary work.
The Asset Format Problem
Section titled “The Asset Format Problem”In a browser prototype, it is common to pick an image format based mainly on visual quality and file size. In a gameface UI, that decision also affects how much work the UI layer performs during layout, rendering, and invalidation.
SVGs and raster images solve different problems:
- SVGs describe shapes mathematically. They stay sharp at different sizes because the renderer draws paths, fills, and strokes at the requested scale.
- Raster images store a fixed grid of pixels. They are better for detailed artwork because the expensive visual detail is already baked into the image file.
The important distinction is that SVG detail is evaluated by the UI renderer, while raster detail is decoded into pixels and then drawn as an image. A simple SVG icon is usually cheap and flexible. A complex SVG illustration with many paths, filters, gradients, or nested groups can become more expensive than a PNG that already contains the same final pixels.
Choosing Between SVGs and Raster Images
Section titled “Choosing Between SVGs and Raster Images”Use SVGs for artwork that is mostly geometric : Icons, flat logos, simple button borders, arrows, separators, and HUD outlines usually benefit from SVG because they scale cleanly across different resolutions and aspect ratios.
Use raster images for artwork that is visually dense : Character portraits, item illustrations, painted backgrounds, screenshots, and textured panels usually belong in PNG, JPEG, or another raster format. These assets contain color variation and detail that would require many vector paths to reproduce.
import Block from '@components/Layout/Block/Block';import Image from '@components/Media/Image/Image';
const InventoryCard = () => { return ( <Block class="inventory-card"> <Image class="item-portrait" src="/assets/items/dragon-armor.png" /> <Image class="rarity-icon" src="/assets/icons/legendary-star.svg" /> </Block> );};<div class="inventory-card"> <!-- Raster image: high-detail painted artwork --> <img class="item-portrait" src="/assets/items/dragon-armor.png" alt="Dragon armor" />
<!-- SVG image: simple scalable UI symbol --> <img class="rarity-icon" src="/assets/icons/legendary-star.svg" alt="Legendary item" /></div>Practical Format Rules
Section titled “Practical Format Rules”For most Gameface UI work, the format decision can be made with a few direct rules:
- Use SVG for icons, simple logos, flat badges, line art, corner decorations, borders, and scalable HUD shapes. And when you need to manipulate the asset at runtime.
- Use PNG for transparent high-fidelity UI art, painted panels, portraits, item art, and alpha-heavy textures.
- Use JPEG only when the asset does not need transparency and compression artifacts are acceptable, such as some large background images (although the use case is very rare).
Mip-Maps (DDS and Engine Textures)
Section titled “Mip-Maps (DDS and Engine Textures)”When images are displayed at a significantly smaller size than their source resolution — for example a downscaled map icon or a UI element rendered in a 3D viewport — the GPU must sample the full-resolution texture down to fewer pixels. Without pre-generated mip-maps, this produces aliasing and sharp edges that look incorrect.
Gameface supports DDS textures with pre-baked mip-maps. If your project integrates Gameface through Unreal Engine, textures exported from Unreal already carry mip-maps natively. Use DDS for any raster asset that will be displayed at variable scale or as part of a 3D UI surface.
Standard PNG and JPEG assets do not carry mip-map data; the engine generates a single mip level at load time. For most HUD and menu assets that are displayed at a fixed size, this is fine.
Working with SVG Assets: External vs. Inline
Section titled “Working with SVG Assets: External vs. Inline”When using SVGs in Gameface or modern web UIs, you should decide how to load them based on your use case. There are two primary strategies for SVG assets: external SVGs and inline SVGs. Understanding when to use each will help you balance performance, maintainability, and flexibility.
When to Use External SVGs
Section titled “When to Use External SVGs”If your SVG does not need to be manipulated at runtime (for example, recolored or animated by the UI), keep it external. This approach minimizes DOM complexity and keeps your structure clean. There are two common external SVG patterns:
<img> element
Section titled “<img> element”Use when the SVG is meaningful to the content or needs to participate in layout like an image. For example, as a button with an Xbox A glyph icon.
import Button from '@components/Basic/Button/Button';import Image from '@components/Media/Image/Image';
const NavButton = () => { return ( <Button class="nav-button"> <Image class="nav-button__icon" src="/assets/icons/xbox-a.svg" /> <span class="nav-button__label">Select</span> </Button> );};<button class="nav-button"> <img class="nav-button__icon" src="/assets/icons/xbox-a.svg" alt="Xbox A button" /> <span class="nav-button__label">Select</span></button>.nav-button { display: flex; align-items: center; gap: 10px; height: 56px; padding: 0 18px;}
.nav-button__icon { width: 24px; height: 24px;}CSS background-image
Section titled “CSS background-image”Use when the SVG is purely decorative and part of the component’s styles. For example, a panel frame with a border.
import BackgroundImage from '@components/Media/BackgroundImage/BackgroundImage';import TextBlock from '@components/Basic/TextBlock/TextBlock';
const QuestPanel = () => { return ( <BackgroundImage src="/assets/ui/panel-frame.svg" class="quest-panel" style={{ width: '520px', padding: '32px' }} > <div class="quest-panel__title">Active Quest</div> <TextBlock>Reach the old watchtower before nightfall.</TextBlock> </BackgroundImage> );};<div class="quest-panel"> <h2>Active Quest</h2> <p>Reach the old watchtower before nightfall.</p></div>.quest-panel { width: 520px; padding: 32px; background-image: url("/assets/ui/panel-frame.svg"); background-repeat: no-repeat; background-size: 100% 100%;}When to Use Inline SVGs
Section titled “When to Use Inline SVGs”Use inline SVG (putting <svg> markup directly in your HTML) only if you need fine-grained control over the SVG’s internal structure at runtime. This is essential for:
- Per-part styling (e.g., recoloring specific paths or elements)
- State-based visuals (e.g., changing only one element within the SVG)
- Adding JavaScript logic to specific parts of the SVG
Example: The canonical inline SVG example - a weapon icon with per-rarity path coloring using CSS custom properties and modifier classes - is covered in full detail in SVG UI Tricks: ViewBox, Strokes, and Fills.
Comparing Approaches
Section titled “Comparing Approaches”The following table summarizes when to use each SVG loading method:
| Approach | Best For | Main Benefit | Main Cost |
|---|---|---|---|
<img src="...svg"> | Static, meaningful icons | Small DOM, simple layout | Can’t style SVG internals |
CSS background-image | Decorative frames & separators | Keeps decoration in CSS | Not semantic, not accessible |
| Inline SVG | Dynamic or stateful vector elements | Rich runtime control | Adds nodes & complexity to DOM |
Gameface SVG Support
Section titled “Gameface SVG Support”Gameface supports SVGs in the most common frontend scenarios:
- Inline in the DOM.
- As a CSS
background-image. - As the source of an
<img>element. - As a border through
border-image-source.
The supported feature set is a subset of SVG 2.0. Standard CSS styling and CSS animations are supported for inline SVG elements.
What is supported
Section titled “What is supported”| Feature | Notes |
|---|---|
| Inline SVG in the DOM | Full CSS styling and CSS/WAAPI animations |
CSS background-image | Cached when content size ≤ 1024×1024 |
<img src="...svg"> | Always cached |
border-image-source | Separate surface per 9-slice section |
@keyframes on SVG properties | Units required for shared CSS/SVG property names (e.g. width) |
| CSS transitions | Supported on all animatable SVG properties |
<use> element | Deprecated in SVG 2.0 but still supported |
What is not supported
Section titled “What is not supported”| Category | Details |
|---|---|
| SMIL animation | <animate>, <animateTransform>, <set> - convert to CSS keyframes |
| Scripting & interactivity | No script execution inside SVG elements |
<foreignObject> | Embedded HTML inside SVG is ignored |
pattern paint server | SVG <pattern> fills are not supported |
vector-effects | Not supported |
paint-order, color-interpolation | Not supported |
<a> and <image> linking elements | Not supported |
| Multimedia | Not supported |
| Conditional processing, metadata, WAI-ARIA | Not supported |
| Full SVG text | Only basic <text> support; <textPath> ignored, <tspan> text treated as part of parent |
stroke-dasharray and stroke-dashoffset
Section titled “stroke-dasharray and stroke-dashoffset”These properties only work on <path> elements. They do not work on <circle>, <rect>, <line>, or other SVG shape primitives. If you need a circular or rectangular progress shape, draw it as a <path>.
CSS vs. SVG property names
Section titled “CSS vs. SVG property names”Several properties share names between CSS and SVG but follow different rules. In SVG attributes, width, height, and font-size may be unitless. In CSS keyframes targeting SVG elements, these values must include units (px, em, etc.) even when the SVG attribute normally does not. SVG-only attributes like x, y, cx, and cy remain unitless.
Here is a practical example of markup that should be avoided in Gameface because it relies on unsupported SVG features:
<svg viewBox="0 0 240 120" xmlns="http://www.w3.org/2000/svg"> <!-- Unsupported: SVG scripting/interactivity --> <script> console.log("SVG script execution"); </script>
<!-- Unsupported: foreignObject --> <foreignObject x="10" y="10" width="220" height="100"> <div xmlns="http://www.w3.org/1999/xhtml">Embedded HTML in SVG</div> </foreignObject>
<!-- Unsupported: SMIL animation --> <circle cx="60" cy="60" r="24" fill="#4ecdc4"> <animate attributeName="r" from="10" to="28" dur="0.8s" repeatCount="indefinite" /> </circle></svg>Before relying on a less common SVG element or attribute, check the official Gameface SVG support table . This is especially important when importing SVGs exported from design tools, because those files can include metadata, masks, clip paths, text nodes, grouped effects, or unsupported paint features that are not visible at first glance.
Recommended Workflow
Section titled “Recommended Workflow”Instead of treating this as a single checklist, make the decision in three short passes: asset type, loading mode, then compatibility validation.
Pass 1: Identify the Asset Type
Section titled “Pass 1: Identify the Asset Type”Start by asking what visual problem the asset solves:
- If it is high-detail artwork (portraits, painted panels, item art), use a raster format.
- If it is geometric UI structure (icons, borders, separators, symbols), use SVG.
Pass 2: Pick the Loading Mode
Section titled “Pass 2: Pick the Loading Mode”Once the asset is SVG, decide how it enters the DOM:
- Use external loading (
<img>or CSSbackground-image) for static visuals. - Use inline SVG only when you must target internal nodes (for example per-path color states, stroke progression, or viewBox-driven effects).
Pass 3: Validate Engine Compatibility
Section titled “Pass 3: Validate Engine Compatibility”Before integrating exported SVGs from design tools:
- Open the SVG and remove editor metadata, hidden groups, and unused nodes.
- Check for unsupported features (for example
<foreignObject>, SMIL tags, scripting blocks). - Cross-check uncommon elements and attributes against the official support table.
© 2026 Coherent Labs. All rights reserved.