diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1b4190422a11..b34f6f3e1cb1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- Fix `haml` pre-processing ([#17051](https://github.com/tailwindlabs/tailwindcss/pull/17051))
+- Ensure classes between `>` and `<` are properly extracted ([#17094](https://github.com/tailwindlabs/tailwindcss/pull/17094))
## [4.0.12] - 2025-03-07
diff --git a/crates/oxide/src/extractor/boundary.rs b/crates/oxide/src/extractor/boundary.rs
index 4e0f22089505..78f9d3184a90 100644
--- a/crates/oxide/src/extractor/boundary.rs
+++ b/crates/oxide/src/extractor/boundary.rs
@@ -73,6 +73,12 @@ enum Class {
// ^
// ```
#[bytes(b'}')]
+ // XML-like languages where classes are inside the tag, e.g.:
+ // ```
+ // from-blue-900 to-cyan-200
+ // ^
+ // ```
+ #[bytes(b'>')]
Before,
// Clojure and Angular like languages, e.g.:
@@ -109,6 +115,12 @@ enum Class {
// In this case there is some JavaScript embedded in an string in PHP and some of the quotes
// need to be escaped.
#[bytes(b'\\')]
+ // XML-like languages where classes are inside the tag, e.g.:
+ // ```
+ // from-blue-900 to-cyan-200
+ // ^
+ // ```
+ #[bytes(b'<')]
After,
#[fallback]
diff --git a/crates/oxide/src/extractor/mod.rs b/crates/oxide/src/extractor/mod.rs
index 5a9de6922fff..b7114f9c0501 100644
--- a/crates/oxide/src/extractor/mod.rs
+++ b/crates/oxide/src/extractor/mod.rs
@@ -922,6 +922,32 @@ mod tests {
}
}
+ // https://github.com/tailwindlabs/tailwindcss/issues/17088
+ #[test]
+ fn test_fluid_template_syntax() {
+ let input = r#"
+
+
+ from-blue-900 to-cyan-200
+ from-cyan-600 to-teal-200
+ from-blue-300 to-cyan-100
+
+
+ "#;
+
+ assert_extract_candidates_contains(
+ input,
+ vec![
+ "from-blue-900",
+ "to-cyan-200",
+ "from-cyan-600",
+ "to-teal-200",
+ "from-blue-300",
+ "to-cyan-100",
+ ],
+ );
+ }
+
// https://github.com/tailwindlabs/tailwindcss/issues/16982
#[test]
fn test_arbitrary_container_queries_syntax() {