From 0571ac5d30d809a31557116d9c037717bc1bae39 Mon Sep 17 00:00:00 2001 From: Bramus Date: Thu, 4 Jun 2026 16:12:57 +0200 Subject: [PATCH 01/11] Remove duplicate description --- css-navigation-1/Overview.bs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/css-navigation-1/Overview.bs b/css-navigation-1/Overview.bs index f6fed32a3a9..31e1c5e3d57 100644 --- a/css-navigation-1/Overview.bs +++ b/css-navigation-1/Overview.bs @@ -44,7 +44,7 @@ url: https://drafts.csswg.org/css-view-transitions-1/#capture-the-image

Declaring named URL patterns: the ''@route'' rule

The @route rule -is an at-rule that associates a name with a [=URL pattern=]. +is an at-rule that associates an author-defined name with a [=URL pattern=]. This name can be referenced in ''@navigation'' rules and in '':active-navigation()'' pseudo-classes. @@ -77,10 +77,6 @@ If a rule has both a valid <> and a valid <> then it is ignored. -This rule associates an author-defined keyword with a URL pattern, -so that any URL that matches one of the URL patterns -matches the route named by the keyword. - The ''@route'' rule can be defined in one of two ways: : with the pattern descriptor From 4083c2d63f2234eef8a7b48ec2acf85dabe21d16 Mon Sep 17 00:00:00 2001 From: Bramus Date: Thu, 4 Jun 2026 16:14:45 +0200 Subject: [PATCH 02/11] Add FIXME to disambigue wording --- css-navigation-1/Overview.bs | 1 + 1 file changed, 1 insertion(+) diff --git a/css-navigation-1/Overview.bs b/css-navigation-1/Overview.bs index 31e1c5e3d57..fa878160588 100644 --- a/css-navigation-1/Overview.bs +++ b/css-navigation-1/Overview.bs @@ -71,6 +71,7 @@ Any other descriptors are ignored. <> = base-url : stylesheet | document | <> + If two valid descriptors in a single rule have the same name, the last one is used and the others are ignored. If a rule has both a valid <> From 7b366b457b135d355d0f0edb68962015ea3ccda0 Mon Sep 17 00:00:00 2001 From: Bramus Date: Thu, 4 Jun 2026 19:42:21 +0200 Subject: [PATCH 03/11] Change example to have the URL be different from the name --- css-navigation-1/Overview.bs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/css-navigation-1/Overview.bs b/css-navigation-1/Overview.bs index fa878160588..b96c2337576 100644 --- a/css-navigation-1/Overview.bs +++ b/css-navigation-1/Overview.bs @@ -123,18 +123,18 @@ but it could also be added back later if we need it. Either this rule:
 @route --movie-list {
-  pattern: url-pattern("/movie-list");
+  pattern: url-pattern("/movies");
 }
 
or this rule:
 @route --movie-list {
-  pathname: "/movie-list";
+  pathname: "/movies";
 }
 
define an ''@route'' rule that associates the name --movie-list -with the URL "/movie-list" resolved relative to the style sheet. +with the URL "/movies" resolved relative to the style sheet. NOTE: The bracing syntax also allows for future expansion if needed. From 771e1f34fdb2e015c44cb9f032b0e0031fa5fbf2 Mon Sep 17 00:00:00 2001 From: Bramus Date: Thu, 4 Jun 2026 19:42:42 +0200 Subject: [PATCH 04/11] Add prose and example to clarify how `url-pattern()` patterns work --- css-navigation-1/Overview.bs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/css-navigation-1/Overview.bs b/css-navigation-1/Overview.bs index b96c2337576..18c1dffb76d 100644 --- a/css-navigation-1/Overview.bs +++ b/css-navigation-1/Overview.bs @@ -15,6 +15,7 @@ Abstract: This module contains conditional CSS rules for styling conditioned on @@ -163,6 +164,35 @@ which can be used to match URLs. This function represents the [=URL pattern=] resulting from invoking [=create a URL pattern for url-pattern()=] with its string argument. +The syntax used in the ''url-pattern()'' function follows that of [=URL Pattern=]. +It is a [=pattern string=] directly based on the syntax used by +the popular path-to-regexp JavaScript library. + +
+Pattern strings can contain capture groups, which by default match the shortest possible string, +up to a component-specific separator (/ in the pathname, . in the hostname). + +For example, the pathname pattern "/movies/:id" +will match "/movies/123" +but not "/movies/123/cast". + +A regular expression enclosed in parentheses can also be used instead, +so the pathname pattern "/blog/:id(\\d+)" +will match "/movies/123" +but not "/movies/css". + +You may also omit the name of the capture group by using only a regular expression, +for example "/blog/(\\d+)". + +A group can also be made optional by using the ? modifier or by wrapping it in braces. +For example, the patterns "/movies/:id?" and "/movies{/:id}" +will match both "/movies" and "/movies/123" (but not "/movies/"). + +A full wildcard * can also be used to match as much as possible, +as in the pattern "/*/movies". +This too can be given a name, for example "/*lang/movies". +
+ The steps of the create a URL pattern for url-pattern() algorithm, given a string arg and an optional baseURLSpecifier From 2ecaf489081607d3389a06361be342bb8529ef60 Mon Sep 17 00:00:00 2001 From: Bramus Date: Thu, 4 Jun 2026 19:43:24 +0200 Subject: [PATCH 05/11] Add `url-pattern()` examples that have capture groups --- css-navigation-1/Overview.bs | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/css-navigation-1/Overview.bs b/css-navigation-1/Overview.bs index 18c1dffb76d..74281310d31 100644 --- a/css-navigation-1/Overview.bs +++ b/css-navigation-1/Overview.bs @@ -226,6 +226,58 @@ which can be ''document'', ''stylesheet'', or a URL, is: +
+This rule: +
+@route --movie-detail {
+  pattern: url-pattern("/movies/:id");
+}
+
+defines an ''@route'' rule that associates +the name --movie-detail +with any URL that matches the [=URL pattern=] /movies/:id. + +Any of the following URLs (relative to the style sheet) match: + +
    +
  • /movies/123
  • +
  • /movies/456
  • +
  • /movies/something
  • +
+ +These URLs will not match: + +
    +
  • /movies/123/ — The trailing slash is not matched by the pattern
  • +
  • /movies/456/extra — The /extra is not matched by the pattern
  • +
+
+ +
+To have the --movie-details route +match only numeric :id values, +define the route eiter as: + +
+@route --movie-detail {
+  pattern: url-pattern("/movies/:id(\\d+)");
+}
+
+ +or as: + +
+@route --movie-detail {
+  pattern: url-pattern("/movies/(\\d+)");
+}
+
+ +This way, /movies/something won’t be matched by the route. + +NOTE: Even though the capture groups are not currently exposed, +it is recommended to give the capture groups a name for future use. +
+
Should the default always be ''stylesheet''? For use of ''url-pattern()'' in ''@navigation'', From 271dce56b65a39af80d3738a0f135215bab2333b Mon Sep 17 00:00:00 2001 From: Bramus Date: Thu, 4 Jun 2026 19:46:19 +0200 Subject: [PATCH 06/11] Move <> section to the top --- css-navigation-1/Overview.bs | 60 ++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/css-navigation-1/Overview.bs b/css-navigation-1/Overview.bs index 74281310d31..f91d4c212a4 100644 --- a/css-navigation-1/Overview.bs +++ b/css-navigation-1/Overview.bs @@ -42,6 +42,36 @@ url: https://drafts.csswg.org/css-view-transitions-1/#capture-the-image

Defining URL patterns in CSS

+

The <> value type

+ +
+<> = <> | <> | <>
+<> = <>
+
+ +A <> is defined to +match a [=/URL=]-or-null input if input is non-null, and: + +
+ +: the <> is a <> +:: [=URL pattern/match|match a URL pattern=] is non-null given + urlPattern as + the [=URL pattern=] represented by the ''@route'' rule referenced by the name and + input as input. + +: the <> is a <> +:: [=URL pattern/match|match a URL pattern=] is non-null given + urlPattern as + the [=URL pattern=] represented by the function (see + [=create a URL pattern for url-pattern()=]) and + input as input. + +: the <> is a <> +:: The given [=/URL=] [=url/equals=] input. + +
+

Declaring named URL patterns: the ''@route'' rule

The @route rule @@ -300,36 +330,6 @@ to serialize f's contents. NOTE: This is defined this way because {{URLPattern}} intentionally does not provide a serialization. -

The <> value type

- -
-<> = <> | <> | <>
-<> = <>
-
- -A <> is defined to -match a [=/URL=]-or-null input if input is non-null, and: - -
- -: the <> is a <> -:: [=URL pattern/match|match a URL pattern=] is non-null given - urlPattern as - the [=URL pattern=] represented by the ''@route'' rule referenced by the name and - input as input. - -: the <> is a <> -:: [=URL pattern/match|match a URL pattern=] is non-null given - urlPattern as - the [=URL pattern=] represented by the function (see - [=create a URL pattern for url-pattern()=]) and - input as input. - -: the <> is a <> -:: The given [=/URL=] [=url/equals=] input. - -
- From 084f5a98adc595e3be252252e16e6b31b658aad3 Mon Sep 17 00:00:00 2001 From: Bramus Date: Thu, 4 Jun 2026 19:46:56 +0200 Subject: [PATCH 07/11] Extend :link-to() example to also include url() and named route variants --- css-navigation-1/Overview.bs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/css-navigation-1/Overview.bs b/css-navigation-1/Overview.bs index f91d4c212a4..71e21bd5bd5 100644 --- a/css-navigation-1/Overview.bs +++ b/css-navigation-1/Overview.bs @@ -339,7 +339,6 @@ This specification defines a new that matches link elements that link to a certain URL.
- A simple example of a '':link-to()'' selector is this one, which matches any links that link to the site's homepage: @@ -349,6 +348,28 @@ which matches any links that link to the site's homepage: } +Because there is no dynamic part in the homepage URL, +you can also pass in a <> directly: + +
+:link-to(url("/")) {
+  font-weight: bold;
+}
+
+ +Passing in a named route is also possible: + +
+@route --homepage {
+  pattern: url-pattern("/");
+}
+
+:link-to(--homepage) {
+  font-weight: bold;
+}
+
+ +All three variants here match the same elements.
The '':link-to()'' pseudo-class takes a single argument, a <>, From 805d36cd13e9bcd64706284a6880c2158ae66a6c Mon Sep 17 00:00:00 2001 From: Bramus Date: Thu, 4 Jun 2026 19:58:08 +0200 Subject: [PATCH 08/11] Move `:active-navigation()` example --- css-navigation-1/Overview.bs | 106 +++++++++++++++++------------------ 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/css-navigation-1/Overview.bs b/css-navigation-1/Overview.bs index 71e21bd5bd5..6f63392a13d 100644 --- a/css-navigation-1/Overview.bs +++ b/css-navigation-1/Overview.bs @@ -385,6 +385,53 @@ functional pseudo-class that matches link elements that link to a certain URL that is related to a navigation that is currently active. +The '':active-navigation()'' pseudo-class takes a single argument, a <>, +and the pseudo-class matches any element where: +* the element matches '':any-link'' +* the target of the link matches the <>, as defined below. + +
+<> =
+  <>? [ <> | link-href ]?
+<> = at | with | from | to
+
+ +ISSUE: Should we use ''at''/''with''/''from''/''to'' or +''current''/''other''/''from''/''to''? + +An <> matches the target linkTarget of the link when +the following steps return true: +1. Let navigationURL be + the [=current navigation URL=] of the document given the <> in <> (default ''with''). + +1. If navigationURL is null, return false. +1. If ''link-href'' is present, or a <> is not provided: + 1. Return true if linkTarget [=url/equals=] navigationURL; Otherwise false. + +1. If a <> is present: + 1. Let targetMatchResult be the result of + [=URL pattern/match|matching a URL pattern=] + given urlPattern and linkTarget. + + 1. Let navigationMatchResult be the result of + [=URL pattern/match|matching a URL pattern=] given + urlPattern and navigationURL. + + 1. If navigationMatchResult or targetMatchResult is null, return false. + + 1. For each property prop of {{URLPatternResult}} that is a + {{URLPatternComponentResult}}: + + 1. If {{URLPatternComponentResult/groups}} of prop of + targetMatchResult is not equal to + {{URLPatternComponentResult/groups}} of prop of + navigationMatchResult, + then return false. + + ISSUE: Need to formally define equality of ordered maps. + + 1. Return true. +
A an example of the '':active-navigation()'' pseudo-class @@ -404,13 +451,13 @@ by matching the relevant parts of the navigation URL to the link URL. navigation: auto; } -@route --movie-details-with-id { - /* match URLs like /en/movie/123 which is the English page +@route --movie-detail { + /* match URLs like /en/movies/123 which is the English page about a movie with ID 123. Be careful to specify the language part with a "*" but the ID part with a named :id parameter so that matching will require equal IDs but allow differences of language. */ - pattern: url-pattern("/*/movie/:id"); + pattern: url-pattern("/*/movies/:id"); } /* capture the overall area representing the movie, and a @@ -421,19 +468,19 @@ by matching the relevant parts of the navigation URL to the link URL. movie we are currently navigating to or from. (lang can be different, though.) - This depends on the --movie-details-with-id route + This depends on the --movie-detail route declaring the ID but not the language with a named parameter, and the use of the 'with' keyword. This means that both the of the link and the other URL of the current navigation match the URL pattern defined by - the "@route --movie-details-with-id" rule, and that the + the "@route --movie-detail" rule, and that the id named group from both matches be the same. (However, the URLs can be different because the * part of the match, containing the language, can be different.) */ .movie-container:has( - > .movie-title:active-navigation(with --movie-details-with-id)) { + > .movie-title:active-navigation(with --movie-detail)) { view-transition-name: movie-container; @@ -448,53 +495,6 @@ by matching the relevant parts of the navigation URL to the link URL.
-The '':active-navigation()'' pseudo-class takes a single argument, a <>, -and the pseudo-class matches any element where: -* the element matches '':any-link'' -* the target of the link matches the <>, as defined below. - -
-<> =
-  <>? [ <> | link-href ]?
-<> = at | with | from | to
-
- -ISSUE: Should we use ''at''/''with''/''from''/''to'' or -''current''/''other''/''from''/''to''? - -An <> matches the target linkTarget of the link when -the following steps return true: -1. Let navigationURL be - the [=current navigation URL=] of the document given the <> in <> (default ''with''). - -1. If navigationURL is null, return false. -1. If ''link-href'' is present, or a <> is not provided: - 1. Return true if linkTarget [=url/equals=] navigationURL; Otherwise false. - -1. If a <> is present: - 1. Let targetMatchResult be the result of - [=URL pattern/match|matching a URL pattern=] - given urlPattern and linkTarget. - - 1. Let navigationMatchResult be the result of - [=URL pattern/match|matching a URL pattern=] given - urlPattern and navigationURL. - - 1. If navigationMatchResult or targetMatchResult is null, return false. - - 1. For each property prop of {{URLPatternResult}} that is a - {{URLPatternComponentResult}}: - - 1. If {{URLPatternComponentResult/groups}} of prop of - targetMatchResult is not equal to - {{URLPatternComponentResult/groups}} of prop of - navigationMatchResult, - then return false. - - ISSUE: Need to formally define equality of ordered maps. - - 1. Return true. - NOTE: Some of the design discussion for this feature has been in w3c/csswg-drafts#13163. From f49ca8ddd634a2586cfd061e64fac1c7e2c9db28 Mon Sep 17 00:00:00 2001 From: Bramus Date: Thu, 4 Jun 2026 20:00:32 +0200 Subject: [PATCH 09/11] Add simple :active-navigation() example --- css-navigation-1/Overview.bs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/css-navigation-1/Overview.bs b/css-navigation-1/Overview.bs index 6f63392a13d..25e7c53e26f 100644 --- a/css-navigation-1/Overview.bs +++ b/css-navigation-1/Overview.bs @@ -434,6 +434,36 @@ the following steps return true:
+The difference between '':link-to()'' and '':active-navigation()'' +is that the latter is only active while a navigation is in progress. + +Consider this example: + +
+@route --homepage {
+  pattern: url-pattern("/");
+}
+
+:link-to(--homepage) {
+  color: lime;
+}
+
+:active-navigation(--homepage) {
+  color: hotpink;
+}
+
+ +Links that link to the --homepage get a lime color. +When navigating to or from the --homepage, +their color changes to hotpink for as long as the animation is active. + +Once the navigation has completed, the '':active-navigation()'' +selector no longer applies, and those links revert back to lime. + +
+ +
+ A an example of the '':active-navigation()'' pseudo-class is this example which creates a view transition between a item in a list that contains a link (in this document) From 698151aecbb1ea9c19d9c1b127194de089345e1b Mon Sep 17 00:00:00 2001 From: Bramus Date: Thu, 4 Jun 2026 20:25:11 +0200 Subject: [PATCH 10/11] Add :active-navigation example with <> --- css-navigation-1/Overview.bs | 91 ++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/css-navigation-1/Overview.bs b/css-navigation-1/Overview.bs index 25e7c53e26f..dea2dab1ab1 100644 --- a/css-navigation-1/Overview.bs +++ b/css-navigation-1/Overview.bs @@ -464,6 +464,97 @@ selector no longer applies, and those links revert back to lime.
+In the following examples, all links that link to the --movie-detail route, +get a lime color when a navigation is in progress. + +
+@route --movie-detail {
+  pattern: url-pattern("/movies/:id");
+}
+
+:active-navigation(--movie-detail) {
+  color: lime;
+}
+
+ +By adding the following selectors that use a <>, +the behavior changes a bit. + +
+:active-navigation(from --movie-detail) {
+  color: hotpink;
+}
+
+:active-navigation(to --movie-detail) {
+  color: yellow;
+}
+
+ +When navigating from /movies/1 to /movies/2: + +
    +
  • + Links that link to the --movie-detail route + with any :id + get a lime color + during the navigation. +
  • +
  • + Links that link to the --movie-detail route + whose target is /movies/1 + (the “from” page) + get a hotpink color + during the navigation. +
  • +
  • + Links that link to the --movie-detail route + whose target is /movies/2 + (the “to” page) + get a yellow color + during the navigation. +
  • +
+ +When navigating from /movies/2 to /: + +
    +
  • + Links that link to the --movie-detail route + with any :id + get a lime color + during the navigation. +
  • +
  • + Links that link to the --movie-detail route + whose target is /movies/3 + (the “from” page) + get a hotpink color + during the navigation. +
  • +
+ +When navigating from / to /movies/3: + +
    +
  • + Links that link to the --movie-detail route + with any :id + get a lime color + during the navigation. +
  • +
  • + Links that link to the --movie-detail route + whose target is /movies/3 + (the “to” page) + get a yellow color + during the navigation. +
  • +
+ +
+ +
+ A an example of the '':active-navigation()'' pseudo-class is this example which creates a view transition between a item in a list that contains a link (in this document) From 064e09acbbd7a91e528d0f329800ef82e9c55741 Mon Sep 17 00:00:00 2001 From: Bramus Date: Fri, 5 Jun 2026 10:32:25 +0200 Subject: [PATCH 11/11] Cater for `url()` including the querystring and the hash when matching --- css-navigation-1/Overview.bs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/css-navigation-1/Overview.bs b/css-navigation-1/Overview.bs index dea2dab1ab1..59edfa7eeb4 100644 --- a/css-navigation-1/Overview.bs +++ b/css-navigation-1/Overview.bs @@ -348,8 +348,20 @@ which matches any links that link to the site's homepage: } +Passing in a named route is also possible: + +
+@route --homepage {
+  pattern: url-pattern("/");
+}
+
+:link-to(--homepage) {
+  font-weight: bold;
+}
+
+ Because there is no dynamic part in the homepage URL, -you can also pass in a <> directly: +you might be tempted to pass in a <> directly:
 :link-to(url("/")) {
@@ -357,19 +369,21 @@ you can also pass in a <> directly:
 }
 
-Passing in a named route is also possible: +However, url("/") won't match URLs such as +/#scroll-to-here or /?utm_id=something +so it is recommended to use the <> +or <> variants, or use the following alternative:
 @route --homepage {
-  pattern: url-pattern("/");
+  pathname: "/";
+  base-url: document;
 }
 
 :link-to(--homepage) {
   font-weight: bold;
 }
 
- -All three variants here match the same elements.
The '':link-to()'' pseudo-class takes a single argument, a <>,