markdown-webview
MarkdownWebView
is a surprisingly performant SwiftUI view that renders Markdown content.
I call it surprising because the underlying view is a WKWebView
, yet a SwiftUI scroll view containing a bunch of MarkdownWebView
still scrolls smoothly. A similar looking view built with native SwiftUI views doesn’t have such performance (yet, hopefully).
https://user-images.githubusercontent.com/5054148/231708816-6c992197-893d-4d94-ae7c-2c6ce8d8c427.mp4
Features
Auto-adjusting View Height
The view’s height is always the content’s height.
Text Selection
Dynamic Content
https://user-images.githubusercontent.com/5054148/231708816-6c992197-893d-4d94-ae7c-2c6ce8d8c427.mp4
Syntax Highlighting
Code syntax is automatically highlighted.
- macOS 11 and later
- iOS 14 and later
Installation
Add this package as a dependency.
See the article “Adding package dependencies to your app” to learn more.
Usage
Display Markdown Content
import SwiftUI
import MarkdownWebView
struct ContentView: View {
@State private var markdownContent = "# Hello World"
var body: some View {
NavigationStack {
MarkdownWebView(markdownContent)
}
}
}
Customize Style
The view comes with a default style (CSS files) that suits many use cases.
You can also supply your own stylesheet by setting the customStylesheet
parameter in the initializer.
import SwiftUI
import MarkdownWebView
struct ContentView: View {
@State private var markdownContent = "# Hello World"
private let stylesheet: String? = try? .init(contentsOf: Bundle.main.url(forResource: "markdown", withExtension: "css")!)
var body: some View {
NavigationStack {
MarkdownWebView(markdownContent, customStylesheet: stylesheet)
}
}
}
Handle Links
The view opens links with the default browser by default.
You can handle link activations yourself by setting the onLinkActivation
parameter in the initializer.
import SwiftUI
import MarkdownWebView
struct ContentView: View {
@State private var markdownContent = "# Hello apple.com"
var body: some View {
NavigationStack {
MarkdownWebView(markdownContent)
.onLinkActivation { url in
print(url)
}
}
}
}
Requirement for macOS Apps
The underlying web view loads an HTML string. For the package to work in a macOS app, enable the “Outgoing Connections (Client)” capability.
What it looks like in Xcode

Acknowledgements
Portions of this package may utilize the following copyrighted material, the use of which is hereby acknowledged.
markdown-webview
MarkdownWebView
is a surprisingly performant SwiftUI view that renders Markdown content.I call it surprising because the underlying view is a
WKWebView
, yet a SwiftUI scroll view containing a bunch ofMarkdownWebView
still scrolls smoothly. A similar looking view built with native SwiftUI views doesn’t have such performance (yet, hopefully).https://user-images.githubusercontent.com/5054148/231708816-6c992197-893d-4d94-ae7c-2c6ce8d8c427.mp4
Features
Auto-adjusting View Height
The view’s height is always the content’s height.
Text Selection
Dynamic Content
https://user-images.githubusercontent.com/5054148/231708816-6c992197-893d-4d94-ae7c-2c6ce8d8c427.mp4
Syntax Highlighting
Code syntax is automatically highlighted.Supported Platforms
Installation
Add this package as a dependency.
See the article “Adding package dependencies to your app” to learn more.
Usage
Display Markdown Content
Customize Style
The view comes with a default style (CSS files) that suits many use cases.
You can also supply your own stylesheet by setting the
customStylesheet
parameter in the initializer.Handle Links
The view opens links with the default browser by default.
You can handle link activations yourself by setting the
onLinkActivation
parameter in the initializer.Requirement for macOS Apps
The underlying web view loads an HTML string. For the package to work in a macOS app, enable the “Outgoing Connections (Client)” capability.
What it looks like in Xcode
Acknowledgements
Portions of this package may utilize the following copyrighted material, the use of which is hereby acknowledged.
© 2014 Vitaly Puzrin, Alex Kocharin
© Mathias Bynens
© 2006 Ivan Sagalaev
© 2014-2015 Vitaly Puzrin, Alex Kocharin
© 2016, Revin Guillen
© Sindre Sorhus