docs

Supported Web Features

Overview of supported web features and browser APIs in Ultralight.

On this page

Ultralight is a custom fork of WebKit (really, just the "WebCore" and "JavaScriptCore" modules) that began in 2014.

The latest version (2.0) is based off a build of WebKit from 2023, and most modern web features work as you would expect in recent Safari versions.

WebKit / Safari Version

Ultralight 2.0 tracks WebKit 615.1.18 (Safari 16.4). The version is readable at runtime through WebKitVersionString().

Each row below marks a feature Supported, Partial (it works with a caveat in the notes), or Not available.

HTML

Feature Status Notes
HTML5 parsing and elements Supported Works as it does in Safari.
Web components (custom elements, shadow DOM, <slot>) Supported
<dialog> and <details> Supported
contenteditable Supported
<input type="file"> Partial Opens no picker (File and FileReader work).
loading="lazy" on images Not available Ignored, so every image loads right away.
The popover attribute Not available Arrived after this WebKit generation.
MathML Not available
Date, time, month, week, and color inputs Not available They act as plain text inputs.
<datalist> Not available Shows nothing.
Spell checking Not available spellcheck has no effect.

CSS

Feature Status Notes
Flexbox Supported
Grid and subgrid Supported
Custom properties Supported
Container queries Supported
Cascade layers Supported
Nesting Supported
:has() Supported
Filters and backdrop filters Supported
Blend modes Supported
image-rendering: pixelated and crisp-edges Supported Scaled images and pixel art keep hard pixel edges instead of being smoothed.
Transitions and animations Supported
prefers-color-scheme Supported Follows the scheme your app reports (see Dark Mode and Color Schemes).
(hover: ...) and (pointer: ...) media queries Partial They report no pointing device at all: (hover: hover) and (pointer: fine) never match, (hover: none) and (pointer: none) do. Don't gate a desktop layout on them— a responsive framework can end up serving its touch layout.
Image cursors (cursor: url(...)) Partial Ignored, though named cursors reach your app.
Smooth scrolling Not available scroll-behavior: smooth and the behavior: 'smooth' option jump straight to the target.
hyphens: auto Not available Never hyphenates.
View transitions Not available Arrived after this WebKit generation.
Anchor positioning Not available Arrived after this WebKit generation.
@scope Not available Arrived after this WebKit generation.
text-wrap: balance Not available Arrived after this WebKit generation.

Fonts and Images

Feature Status Notes
@font-face web fonts Supported TrueType, OpenType, WOFF, and WOFF2.
Variable fonts Supported font-weight, font-stretch, font-style, and font-variation-settings.
PNG, JPEG, GIF, WebP, BMP, and ICO images Supported
SVG Supported Inline and as an image.
.dds textures in <img> and CSS Supported See Compressed Textures.
Textures straight from your app Supported See Displaying Custom Textures.
AVIF and JPEG XL images Not available They don't decode.

JavaScript

The Free edition has JIT disabled (JavaScript may execute slower). The editions are covered in Editions and Feature Macros.

Feature Status Notes
ES2022 Supported
The ES2023 array additions Supported
ES modules and dynamic import() Supported
Web Workers Supported
Secure contexts on local pages Supported Pages loaded from file:// URLs are secure contexts, and so is HTML loaded from a string with a file:// base URL. Without one, that HTML is about:blank, which is not, and secure-context-only APIs such as crypto.randomUUID() and navigator.locks disappear— so pass a base URL.
Switching JavaScript off per View Supported The page still lays out and animates, and your app drives it from native code (see Embedded and Device UI).
Object.groupBy, the RegExp v flag, Temporal Not available Anything later than the Safari 16.4 level.
WebAssembly Not available Pick the JavaScript build of any library that offers one.
SharedArrayBuffer Not available
Shared workers Not available
Service workers Not available
requestIdleCallback() Not available Schedule background work with setTimeout() or requestAnimationFrame().

Canvas and Graphics

Feature Status Notes
Canvas 2D Supported Including Path2D, roundRect(), conic gradients, ImageBitmap, and toBlob().
imageSmoothingEnabled and imageSmoothingQuality Supported Turning smoothing off keeps hard pixel edges when scaling. 'high' applies a higher-quality filter when enlarging. 'low' and 'medium' use the default.
OffscreenCanvas Supported On the page and in workers.
The canvas filter property Partial Works unless your app switches canvas filters off. Reference filters like url(#id) draw unfiltered.
Canvas readback on a GPU-rendered View Partial getImageData() throws, toDataURL() returns data:,, and putImageData() does nothing. Create the context with getContext('2d', { willReadFrequently: true }) and all three work. CPU-rendered Views are unaffected.
WebGL Not available getContext('webgl') returns null. Draw 3D content in your engine and show it on the page as a custom texture (see Displaying Custom Textures).
WebGPU Not available

Media

Feature Status Notes
HTML5 video and audio Partial Pro edition and higher, from the WebM container with VP9 video and Opus audio (in lower editions media playback isn't available). See Media and Audio.
autoplay Supported Works without a user gesture.
The controls attribute Supported
<track> subtitles Supported
Media Source Extensions Not available An HLS or DASH player won't work— point the element at a WebM file instead.
Web Audio Not available
WebRTC and getUserMedia() Not available
DRM (Encrypted Media) Not available
Picture-in-picture Not available
WebCodecs Not available

Networking

Feature Status Notes
fetch() and XMLHttpRequest Supported Requests go over HTTP/1.1 or HTTP/2.
Streaming response bodies Supported
EventSource Supported
WebSocket Supported
Content Security Policy Supported Enforced.
Downloads Partial A file the server sends as an attachment, or one the page can't display, reaches your app as a download (see Downloads and Network Control). An <a download> link just navigates.
navigator.sendBeacon() Not available Send analytics with fetch() while the page is alive.

Storage and Crypto

Feature Status Notes
Cookies Supported They live in the View's session (see Sessions and Site Data).
localStorage and sessionStorage Supported In the View's session.
IndexedDB Supported In the View's session.
BroadcastChannel Supported
navigator.locks Supported
crypto.getRandomValues() and crypto.randomUUID() Supported
crypto.subtle Not available Hashing and signing need a JavaScript library.
The Cache API Not available
navigator.storage Not available
CompressionStream Not available

Forms and Input

Feature Status Notes
Mouse, wheel, keyboard, and pointer events Supported From the input your app forwards (see Mouse and Scroll Input and Keyboard Input).
The Gamepad API Supported From the controllers your app forwards (see Gamepad Input).
Form validation Partial An invalid control blocks the submission. invalid fires on each bad control and the first takes focus, but no message bubble is drawn, so style :invalid or show your own text (see Forms and Inputs).
Touch events Not available Use pointer events.
HTML drag and drop Not available draggable never starts a drag. Use pointer events.

Clipboard

Feature Status Notes
Copy and cut Supported From script and the keyboard.
Script-initiated paste Partial Works only during a click or key press and only when your app's clipboard policy allows it (see Text Editing and the Clipboard).
Text and HTML on the clipboard Supported
Images and files on the clipboard Not available
navigator.clipboard Not available Use document.execCommand().

The Window and Devices

Feature Status Notes
devicePixelRatio Supported Reflects the View's scale.
window.screen Partial Reports zero for its size, so size your layout from innerWidth / innerHeight or viewport units.
window.open() and target="_blank" Partial They open a new View only when your app provides one, and window.open() returns null otherwise (see Handling View Events).
alert(), confirm(), and prompt() Not available alert() shows nothing, confirm() returns false, and prompt() returns null. Build dialogs in the page or natively (see Popups and Dialogs).
beforeunload prompts Not available beforeunload never asks.
window.print() Not available
requestFullscreen() Not available Your app owns the window (see Windows, Monitors, and DPI).
requestPointerLock() Not available
Notification Not available
navigator.geolocation Not available
Permissions, Web Share, wake locks, Payment Request, Web Authentication, speech, WebXR Not available
Assistive technology Not available Pages are not exposed to screen readers (ARIA attributes parse but reach nothing).

Checking for a Feature

Feature-detect the usual way, with typeof, 'x' in navigator, or CSS.supports(). A missing API is simply undefined, with no other message.

JavaScript
if ('requestIdleCallback' in window)
  requestIdleCallback(saveDraft);
else
  setTimeout(saveDraft, 0);