The HTML <model> element, previously only available on visionOS, now comes to iOS, iPadOS, and macOS Safari in iOS 27. It allows web developers to embed interactive 3D USDZ models natively in HTML with no JavaScript library required.
โข No external libraries needed โ unlike model-viewer, the <model> element is a native browser primitive rendered directly by the platform, reducing page weight and complexity
โข Single markup works across all Apple platforms โ iPhone, iPad, Mac, and Vision Pro with stereoscopic rendering, including AR Quick Look on iOS/iPadOS via a simple <a rel="ar"> wrapper
โข Future-proof web standard โ Apple is actively contributing the spec to W3C, and a polyfill bridges non-supporting browsers today
A WKWebView-based SwiftUI app that loads an inline HTML page using the native <model> element to display a USDZ file with orbit interaction, a ready-state spinner, and an AR Quick Look link.
import SwiftUI
import WebKit
struct ModelElementDemoView: View {
var body: some View {
ModelWebView()
.ignoresSafeArea()
.navigationTitle("3D Product")
}
}
struct ModelWebView: UIViewRepresentable {
func makeUIView(context: Context) -> WKWebView {
let config = WKWebViewConfiguration()
config.allowsInlineMediaPlayback = true
let webView = WKWebView(frame: .zero, configuration: config)
webView.scrollView.isScrollEnabled = false
let html = buildHTML()
// Load with a file base URL so relative USDZ paths resolve correctly
// In production, replace with a real server URL hosting your .usdz
webView.loadHTMLString(html, baseURL: Bundle.main.bundleURL)
return webView
}
func updateUIView(_ uiView: WKWebView, context: Context) {}
private func buildHTML() -> String {
"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Mallet</title>
<style>
body { margin: 0; background: #f2f2f7; display: flex;
flex-direction: column; align-items: center;
justify-content: center; height: 100vh; }
model { width: 320px; height: 320px;
background-color: #ffffff;
border-radius: 16px; }
#spinner { font-size: 14px; color: #888;
margin-top: 12px; }
#ar-link { margin-top: 16px; font-family: -apple-system;
color: #007aff; text-decoration: none;
font-size: 16px; }
</style>
</head>
<body>
<!-- Native <model> element: no JS library required -->
<!-- stagemode="orbit" enables touch-to-rotate interaction -->
<model id="myModel"
src="mallet.usdz"
stagemode="orbit">
<!-- Fallback image for unsupported browsers -->
<img src="mallet-thumbnail.jpg"
alt="Camping Mallet"
width="320" height="320">
</model>
<div id="spinner">Loading 3D model...</div>
<!-- AR Quick Look on iOS/iPadOS: wrap in <a rel="ar"> -->
<a id="ar-link" href="mallet.usdz" rel="ar"
style="display:none">View in AR โ</a>
<script>
const model = document.getElementById('myModel');
const spinner = document.getElementById('spinner');
const arLink = document.getElementById('ar-link');
// ready promise resolves when the model is fully loaded
model.ready
.then(() => {
spinner.textContent = 'Tap and drag to rotate';
arLink.style.display = 'inline';
})
.catch(() => {
spinner.textContent = 'Failed to load model.';
});
</script>
</body>
</html>
"""
}
}
#Preview {
NavigationStack {
ModelElementDemoView()
}
}Background color on <model> is always opaque โ transparent backgrounds are not supported. The stagemode="orbit" attribute slightly rescales the model to prevent clipping during rotation. entityTransform requires stagemode to be removed or set to 'none'. USDZ is the recommended format for best cross-platform quality.
AR Quick Look requires an ARKit-capable device. Stereoscopic rendering is exclusive to visionOS. Polyfill required for non-Safari/non-Apple browsers.
More iOS 27 APIs land every week.
Get notified when new capabilities are published โ no noise, just signal.