Skip to content

[css-page-3] Should @page declarations be hoisted? #11272

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
cdoublev opened this issue Nov 25, 2024 · 5 comments
Open

[css-page-3] Should @page declarations be hoisted? #11272

cdoublev opened this issue Nov 25, 2024 · 5 comments
Labels
css-page-3 Current Work

Comments

@cdoublev
Copy link
Collaborator

cdoublev commented Nov 25, 2024

Current version of Chrome and FF hoist declarations in @page:

const sheet = new CSSStyleSheet
sheet.replaceSync(`

  @page {
    @top-left {
      content: "green";
      color: green;
    }
    color: red;
  }

  style {
    @media {
      color: green;
    }
    color: red;
  }

`)

sheet.cssRules[0].cssText; // @page { color: red; @top-left { ...; color: green; } }
sheet.cssRules[1].cssText; // style { @media { color: green } color: red; }

If I am not mistaken, @page (with no page selector) and margin rules have the same specificity. So this might be unexpected, like in style rules.

Should they be wrapped in CSSNestedDeclarations whose style attribute is a CSSPageDescriptors?

@cdoublev cdoublev added the css-page-3 Current Work label Nov 25, 2024
@bramus
Copy link
Contributor

bramus commented Nov 29, 2024

Should they be wrapped in CSSNestedDeclarations whose style attribute is a CSSPageDescriptors?

Seems like a good idea in order to make behavior consistent / predictable.

/ping @andruud

@cdoublev
Copy link
Collaborator Author

@font-feature-values and @function also take declarations and rules as their block contents, but there is no corresponding interface inheriting CSSStyleDeclaration. I guess hoisting declarations is inappropriate in @function.

So the question might be whether CSSNestedDeclarations.style should exist or not.

cdoublev added a commit to cdoublev/css that referenced this issue Dec 19, 2024
Declarations are no longer hoisted or wrapped in a style rule.

Some problem remains...

1. @font-feature-values, @function, @page, can also have declarations
   interleaved with rules, but CSSNestedDeclarations is currently
   associated to style properties. (w3c/csswg-drafts#11272)

2. "}" should be ignored in a "style" attribute value (a declaration
   block) but the algorithm has been replaced with the same algorithm
   than for a block of rules and declarations. (w3c/csswg-drafts#11113)

3. The current text wants declarations interleaved by an invalid at-rule
   or an invalid (qualified) rule error to be separated, but the reason
   is not stated and no browser does this. (w3c/csswg-drafts#11271)

4. The current text clearly has some other minor typos and is not clear
   about whether rules and declaration, or only rules, should be
   returned. (w3c/csswg-drafts#11017)
cdoublev added a commit to cdoublev/css that referenced this issue Dec 19, 2024
Declarations are no longer hoisted or wrapped in a style rule.

Some problem remains...

1. @font-feature-values, @function, @page, can also have declarations
    interleaved with rules, but CSSNestedDeclarations is currently
    associated to style properties. (w3c/csswg-drafts#11272)

2. "}" should be ignored in a "style" attribute value (a declaration
    block) but the algorithm has been replaced with the same algorithm
    than for a block of rules and declarations. (w3c/csswg-drafts#11113)

3. The current text wants declarations interleaved by an invalid at-rule
    or an invalid (qualified) rule error to be separated, but the reason
    is not stated and no browser does this. (w3c/csswg-drafts#11271)

4. The current text clearly has some other minor typos and is not clear
    about whether rules and declaration, or only rules, should be
    returned. (w3c/csswg-drafts#11017)
cdoublev added a commit to cdoublev/css that referenced this issue Dec 19, 2024
Declarations are no longer hoisted or wrapped in a style rule.

Some problem remains...

1. @font-feature-values, @function, @page, can also have declarations
    interleaved with rules, but CSSNestedDeclarations is currently
    associated to style properties. (w3c/csswg-drafts#11272)

2. "}" should be ignored in a "style" attribute value (a declaration
    block) but the algorithm has been replaced with the same algorithm
    than for a block of rules and declarations. (w3c/csswg-drafts#11113)

3. The current text wants declarations interleaved by an invalid at-rule
    or an invalid (qualified) rule error to be separated, but the reason
    is not stated and no browser does this. (w3c/csswg-drafts#11271)

4. The current text clearly has some other minor typos and is not clear
    about whether rules and declaration, or only rules, should be
    returned. (w3c/csswg-drafts#11017)
@andruud
Copy link
Member

andruud commented Jan 14, 2025

cc @mstensho

I agree that not hoisting would be more consistent, especially if it actually matters for the behavior.

but there is no corresponding interface inheriting CSSStyleDeclaration

I do think we're going to need a CSSFooDeclarations for any @foo that accepts declarations in its block contents, exposing just the descriptors that are relevant for that at-rule.

I guess hoisting declarations is inappropriate in @function.

Definitely inappropriate. It's currently specced to use CSSNestedDeclarations, but it doesn't actually work well due to style being the wrong type, as you mentioned.

@mstensho
Copy link
Contributor

It doesn't matter for the behavior. Note that the spec recommends that @page declaration be placed before any margin rules, though.

https://drafts.csswg.org/css-page-3/#margin-at-rules

Page-margin boxes are created by margin at-rules inside the page context. Authors should put these rules after any declarations in the page context as legacy clients may not handle declarations after margin at-rules correctly.

As such, it makes slightly more sense to hoist, than not to hoist. But it shouldn't matter. Specificity isn't an issue here, since what's in @page and what's in @top-left addresses different boxes (page box vs. page margin box).

@page properties apply in the page context, which acts as a parent of any page margin contexts (which are defined by property declarations inside page margin rules). A page margin context may inherit properties from a page context, which in turn may inherit from the document root element.

See https://drafts.csswg.org/css-page-3/#page-model and https://drafts.csswg.org/css-page-3/#page-properties

@cdoublev
Copy link
Collaborator Author

cdoublev commented Mar 7, 2025

It does not matter for the rendering behavior as long as conditional rules are not allowed in @page, which might be useful to avoid repeating multiple @page rules for different conditions:

@page {
  @media print and (width > 21cm) {
    margin: 3cm; /* Applies only if declarations are hoisted */
  }
  margin: 1cm;
}

Now this can remain unspecified and change later if conditional rules are allowed, which would only change the CSSOM behavior.

cdoublev added a commit to cdoublev/css that referenced this issue Mar 7, 2025
Also fixes CSSNestedDeclarations and CSSFontFeatureValuesRule (follow-up of
fc5f64c).

CSS*Declarations represent declarations appearing after a rule and expose a
style attribute as a subclass of CSSStyleDeclaration, defined with the
descriptors or properties allowed in the parent rule.

CSSPageDeclarations is unspecified so this is a speculation on the outcome of
w3c/csswg-drafts#11272.

CSSFontFeatureValuesRules hoist declarations for font-display, which will
presumably be removed (w3c/csswg-drafts#2973).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-page-3 Current Work
Projects
None yet
Development

No branches or pull requests

4 participants