Swift and SwiftUI tutorials for Swift Developers

How to Display Web Content in SwiftUI Using WebView

A complete step-by-step tutorial in Xcode

For many years, embedding web content inside a SwiftUI app required using WKWebView through UIViewRepresentable or NSViewRepresentable. While powerful, that approach was complex, verbose, and not aligned with the declarative philosophy of SwiftUI.

With iOS 26 and macOS 26, Apple introduced a new native view called WebView, which allows you to display web pages, HTML, and interactive content directly inside a SwiftUI view in a simple, declarative, and cross-platform way.

In this tutorial you will learn how to use WebView to:

  • Load web pages
  • Display local HTML
  • Intercept links
  • Show loading indicators
  • Integrate web navigation into modern SwiftUI apps

All using Xcode and SwiftUI, without UIKit or AppKit wrappers.


1. What is WebView in SwiftUI?

WebView is a view introduced in SwiftUI for iOS 26, macOS 26, and visionOS 3 that wraps the WebKit engine in a fully declarative API.

This means you can now do something as simple as:

WebView(url: URL(string: "https://www.apple.com")!)

and get a fully functional web browser inside your app.

It is designed to integrate with:

  • SwiftUI navigation (NavigationStack)
  • Reactive state (@State@Observable)
  • Security and privacy
  • The app sandbox

2. Creating the project in Xcode

Let’s start from scratch.

  1. Open Xcode 18 or later
  2. Choose File → New → Project
  3. Select iOS App
  4. Set:
    • Product Name: SwiftUIWebViewDemo
    • Interface: SwiftUI
    • Language: Swift
    • Minimum OS: iOS 26

Click Create.


3. Importing WebKitUI

In iOS 26 and macOS 26, WebView lives in a new module:

import SwiftUI
import WebKitUI

Open ContentView.swift and add this import.


4. Displaying a basic web page

Let’s create the first example: showing a website.

struct ContentView: View {
    var body: some View {
        WebView(url: URL(string: "https://developer.apple.com")!)
            .ignoresSafeArea()
    }
}

Run the app.

You will see Apple Developer’s website displayed inside your app, with scrolling, links, videos, and JavaScript working.

This is a huge leap forward compared to earlier versions.


5. Using NavigationStack with WebView

Let’s integrate it into a real SwiftUI navigation flow.

struct ContentView: View {
    var body: some View {
        NavigationStack {
            WebView(url: URL(string: "https://www.swift.org")!)
                .navigationTitle("Swift")
                .navigationBarTitleDisplayMode(.inline)
        }
    }
}

Now WebView behaves like any other SwiftUI view.


6. Loading dynamic content

In real apps, you rarely want a fixed URL. Let’s use state:

struct ContentView: View {
    @State private var url = URL(string: "https://www.apple.com")!

    var body: some View {
        VStack {
            WebView(url: url)

            Button("Go to Swift") {
                url = URL(string: "https://www.swift.org")!
            }
        }
    }
}

When the URL changes, WebView updates automatically.

This is pure SwiftUI reactivity.


7. Displaying local HTML

You can also display HTML generated by your app.

let html = """
<html>
<head>
<style>
body { font-family: -apple-system; padding: 40px; }
h1 { color: blue; }
</style>
</head>
<body>
<h1>Hello SwiftUI WebView</h1>
<p>This is local HTML content.</p>
</body>
</html>
"""

Then:

WebView(html: html)

This is perfect for:

  • Documentation
  • Terms and conditions
  • Offline articles
  • AI-generated content

8. Showing a loading indicator

WebView exposes a progress binding:

struct ContentView: View {
    @State private var progress = 0.0

    var body: some View {
        VStack {
            ProgressView(value: progress)

            WebView(
                url: URL(string: "https://www.apple.com")!,
                progress: $progress
            )
        }
    }
}

This lets you display a native loading bar.


9. Intercepting links

You can control what happens when the user taps a link.

WebView(
    url: URL(string: "https://www.apple.com")!,
    onNavigate: { request in
        if request.url?.host == "youtube.com" {
            return .cancel
        }
        return .allow
    }
)

This is extremely useful for:

  • Preventing navigation outside your app
  • Opening certain links in Safari
  • Implementing deep links

10. JavaScript ↔ SwiftUI communication

One of the most powerful features of WebView is its native JavaScript bridge.

WebView(
    html: html,
    messageHandler: { message in
        print("JS sent:", message)
    }
)

From JavaScript:

window.swiftui.postMessage("Hello from JS");

This enables very powerful hybrid apps.


11. Reader mode, privacy, and sandboxing

WebView inherits all WebKit protections:

  • Tracker blocking
  • App-isolated cookies
  • Process isolation
  • Camera and microphone permissions

You can also enable reader mode:

WebView(url: url, readerMode: .enabled)

12. Using WebView on macOS 26

The same API works on macOS:

WebView(url: URL(string: "https://www.apple.com")!)
    .frame(minWidth: 800, minHeight: 600)

This makes it trivial to build cross-platform web-powered apps.


13. Building a mini browser

Let’s build a tiny browser:

struct BrowserView: View {
    @State private var urlString = "https://www.apple.com"

    var body: some View {
        VStack {
            TextField("URL", text: $urlString)
                .textFieldStyle(.roundedBorder)
                .padding()

            if let url = URL(string: urlString) {
                WebView(url: url)
            }
        }
    }
}

You now have a working browser in under 30 lines of code.


14. Real-world use cases

WebView is ideal for:

  • Documentation
  • Online stores
  • Blogs
  • Admin dashboards
  • Hybrid apps
  • OAuth login
  • Chatbots

15. Best practices

  • Always use HTTPS
  • Validate URLs before loading
  • Use onNavigate for security
  • Avoid loading untrusted content
  • Don’t recreate WebView unnecessarily

16. WebView vs WKWebView

Old (WKWebView)New (WebView)
UIViewRepresentableNative SwiftUI
DelegatesClosures
Verbose codeDeclarative
UIKit onlyiOS + macOS

Conclusion

The introduction of WebView in iOS 26 and macOS 26 marks a turning point for SwiftUI development. For the first time, Apple provides a clean, modern, declarative way to integrate the web into native apps.

You can now combine:

  • Native SwiftUI UI
  • Dynamic web content
  • JavaScript
  • WebKit security

All with very little code.

If you know SwiftUI and HTML, you can now build professional hybrid apps with a truly native user experience.

If you have any questions about this article, please contact me and I will be happy to help you 🙂. You can contact me on my X profile or on my Instagram profile.

Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Article

How to Build a Video Player in SwiftUI Using AVKit

Next Article

How to use Rich Text Editing with TextView and AttributedString in SwiftUI

Related Posts