|
| 1 | +# Explainer: The revert-rule Keyword |
| 2 | + |
| 3 | +## Authors |
| 4 | + |
| 5 | +@andruud |
| 6 | + |
| 7 | +## Introduction |
| 8 | + |
| 9 | +CSS has built-in mechanisms for falling back to a previously specified value whenever an invalid value is encountered. For example: |
| 10 | + |
| 11 | +```css |
| 12 | +div.basic { |
| 13 | + display: block; |
| 14 | +} |
| 15 | +div.fancy { |
| 16 | + display: fancy; |
| 17 | +} |
| 18 | +``` |
| 19 | + |
| 20 | +Given `<div class="basic fancy">`, and assuming that `fancy` is not (yet) a valid `display` type in your user agent, the `display: fancy` declaration is simply ignored; we effectively fall back to `display: block`. |
| 21 | + |
| 22 | +This fallback functionality depends on declarations being recognized as valid or invalid at _parse time_. With the proliferation of |
| 23 | +[arbitrary substitution functions](https://drafts.csswg.org/css-values-5/#arbitrary-substitution), however, this is no longer possible, since values containing such functions are assumed to be valid at that time. For example, say we want to make `display` `fancy` conditionally |
| 24 | +based on a custom property: |
| 25 | + |
| 26 | +```css |
| 27 | +div.basic { |
| 28 | + display: block; |
| 29 | +} |
| 30 | +div.fancy { |
| 31 | + display: if(style(--enable-fancy): fancy); |
| 32 | +} |
| 33 | +``` |
| 34 | + |
| 35 | +If `--enable-fancy` is _not_ set here, we do not fall back to `block`; it instead becomes [invalid at computed value time](https://drafts.csswg.org/css-values-5/#invalid-at-computed-value-time), and ultimately the property's initial value (`inline`). While you could provide your fallback as an `else:block` branch to the `if()` function, this requires providing the `block` value explicitly; you lose the flexibility inherent in the behavior of falling back to whatever you would otherwise get (without knowing the details). |
| 36 | + |
| 37 | +## Solution: The `revert-rule` Keyword |
| 38 | + |
| 39 | +The `revert-rule` keyword allows authors to dynamically revert back to the previous rule in the [sorting order](https://drafts.csswg.org/css-cascade-5/#cascade-sort) |
| 40 | +determined by css-cascade: |
| 41 | + |
| 42 | +```css |
| 43 | +div.basic { |
| 44 | + display: block; |
| 45 | +} |
| 46 | +div.fancy { |
| 47 | + display: if(style(--enable-fancy): fancy; else: revert-rule); |
| 48 | +} |
| 49 | +``` |
| 50 | + |
| 51 | +When `--enable-fancy` is not set, the `revert-rule` in the `else` branch effectively eliminates the declaration, and reverts back to whatever value would otherwise win the cascade for `display`. In this simple case, that is `block` from `div.basic`, but in a more complicated example, the reverted-to value could vary based on a number of CSS style rules and conditionals. |
| 52 | + |
| 53 | +## Future Extensions |
| 54 | + |
| 55 | +It's worth noting that it's already possible to effectively get `revert-rule`-like behavior by wrapping declarations in an anonymous layer and using `revert-layer` instead: |
| 56 | + |
| 57 | +```css |
| 58 | +div.fancy { |
| 59 | + @layer { |
| 60 | + display: if(style(--enable-fancy): fancy; else: revert-layer); |
| 61 | + } |
| 62 | +} |
| 63 | +``` |
| 64 | + |
| 65 | +The `revert-rule` keyword may therefore be seen as an author convenience to achieve what can currently be achieved with anonymous layers and the `revert-layer` keyword. |
| 66 | + |
| 67 | +Although this is already valuable enough from an ergonomic perspective, the higher-level CSS concepts that could be unblocked by `revert-rule`'s underlying behavior are perhaps more exciting: |
| 68 | + |
| 69 | + - A conditional `@if` block rule, [Issue 12909](https://github.com/w3c/csswg-drafts/issues/12909). |
| 70 | + - Additive styling via an equivalent functional notation (`revert-rule()`). For example, `div { --foo: revert-rule(--foo) bar; }` would append `bar` to the previous value of `--foo`. |
| 71 | + |
| 72 | +## Security and Privacy Considerations |
| 73 | + |
| 74 | +There are no known security or privacy concerns. The `revert-rule` is functionally equivalent to behavior that is already possible in a more verbose way (see previous section). |
| 75 | + |
| 76 | +## Resources |
| 77 | + |
| 78 | +- [CSS Values 5 Specification](https://drafts.csswg.org/css-cascade-5/#valdef-all-revert-rule) |
| 79 | +- [Issue 10443](https://github.com/w3c/csswg-drafts/issues/10443) (original proposal) |
0 commit comments