diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9364c49..d41ae02 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@
   [#278](https://github.com/lambda-fairy/maud/issues/278)
 - Provide Tide support.
   [#280](https://github.com/lambda-fairy/maud/pull/280) 
+- Provide Axum support.
+  [#284](https://github.com/lambda-fairy/maud/pull/284)
 
 ## [0.22.2] - 2021-01-09
 
diff --git a/docs/content/web-frameworks.md b/docs/content/web-frameworks.md
index 0eb52d0..a48d8ca 100644
--- a/docs/content/web-frameworks.md
+++ b/docs/content/web-frameworks.md
@@ -177,3 +177,40 @@ async fn main() -> tide::Result<()> {
     Ok(())
 }
 ```
+
+# Axum
+
+Axum support is available with the "axum" feature:
+
+```toml
+# ...
+[dependencies]
+maud = { version = "*", features = ["axum"] }
+# ...
+```
+
+This adds an implementation of `IntoResponse` for `Markup`/`PreEscaped<String>`.
+This then allows you to use it directly as a response!
+
+```rust,no_run
+use maud::{html, Markup};
+use axum::prelude::*;
+
+async fn hello_world() -> Markup {
+    html! { 
+        h1 { "Hello, World!" } 
+    }
+}
+
+#[tokio::main]
+async fn main() {
+    // build our application with a single route
+    let app = route("/", get(hello_world));
+
+    // run it with hyper on localhost:3000
+    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
+        .serve(app.into_make_service())
+        .await
+        .unwrap();
+}
+```
\ No newline at end of file
diff --git a/doctest/Cargo.toml b/doctest/Cargo.toml
index 25d575f..a06e4cf 100644
--- a/doctest/Cargo.toml
+++ b/doctest/Cargo.toml
@@ -8,11 +8,13 @@ edition = "2018"
 actix-web = "3"
 ammonia = "3"
 iron = "0.6"
-maud = { path = "../maud", features = ["actix-web", "iron", "rocket", "tide"] }
+maud = { path = "../maud", features = ["actix-web", "iron", "rocket", "tide", "axum"] }
 pulldown-cmark = "0.8"
 rocket = "0.4"
 rouille = "3"
 tide = "0.16"
+tokio = { version = "1.9.0", features = ["rt", "macros", "rt-multi-thread"] }
+axum = "0.1.3"
 
 [dependencies.async-std]
 version = "1.9.0"
diff --git a/maud/Cargo.toml b/maud/Cargo.toml
index eb04fb5..ed67fef 100644
--- a/maud/Cargo.toml
+++ b/maud/Cargo.toml
@@ -25,6 +25,7 @@ rocket = { version = ">= 0.3, < 0.5", optional = true }
 futures-util = { version = "0.3.0", optional = true, default-features = false }
 actix-web-dep = { package = "actix-web", version = ">= 2, < 4", optional = true, default-features = false }
 tide = { version = "0.16.0", optional = true }
+axum = { version = "0.1.3", optional = true }
 
 [dev-dependencies]
 trybuild = { version = "1.0.33", features = ["diff"] }
diff --git a/maud/src/lib.rs b/maud/src/lib.rs
index 96d7c9d..b30e1e3 100644
--- a/maud/src/lib.rs
+++ b/maud/src/lib.rs
@@ -253,3 +253,26 @@ mod tide_support {
         }
     }
 }
+
+#[cfg(feature = "axum")]
+mod axum_support {
+    use crate::PreEscaped;
+    use alloc::string::String;
+    use axum::{
+        body::Body,
+        http::{header, HeaderValue, Response, StatusCode},
+        response::IntoResponse,
+    };
+
+    impl IntoResponse for PreEscaped<String> {
+        fn into_response(self) -> Response<Body> {
+            let mut res = Response::new(Body::from(self.0));
+            *res.status_mut() = StatusCode::OK;
+            res.headers_mut().insert(
+                header::CONTENT_TYPE,
+                HeaderValue::from_static("text/html; charset=utf-8"),
+            );
+            res
+        }
+    }
+}