Skip to content

Commit

Permalink
CSSPageDescriptors and related fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
hamishwillee committed Jul 22, 2024
1 parent 8cc0728 commit 2f2ece2
Show file tree
Hide file tree
Showing 4 changed files with 293 additions and 17 deletions.
153 changes: 153 additions & 0 deletions files/en-us/web/api/csspagedescriptors/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
---
title: CSSPageDescriptors
slug: Web/API/CSSPageDescriptors
page-type: web-api-interface
browser-compat: api.CSSPageDescriptors
---

{{APIRef("CSSOM")}}

The **`CSSPageDescriptors`** interface represents a CSS declaration block for an {{cssxref("@page")}} rule.

The interface exposes style information and various style-related methods and properties for the page.
Each multi-word property has versions in camel- and snake-case, following both CSS and Web API naming conventions.

A `CSSPageDescriptors` object is accessed through the {{DOMxRef("CSSPageRule.style", "style")}} property of the `CSSPageRule` interface, which can in turn be found using the {{DOMxRef("CSSStyleSheet")}} API.

{{InheritanceDiagram}}

## Attributes

_This interface also inherits properties of its parent, {{domxref("CSSStyleDeclaration")}}._

- `margin`
- : A string representing the `margin` property of the corresponding `@page` rule.
- `marginTop`
- : A string representing the `margin-top` property of the corresponding `@page` rule.
- `marginRight`
- : A string representing the `margin-right` property of the corresponding `@page` rule.
- `marginBottom`
- : A string representing the `margin-bottom` property of the corresponding `@page` rule.
- `marginLeft`
- : A string representing the `margin-left` property of the corresponding `@page` rule.
- `margin-top`
- : A string representing the `margin-top` property of the corresponding `@page` rule.
- `margin-right`
- : A string representing the `margin-right` property of the corresponding `@page` rule.
- `margin-bottom`
- : A string representing the `margin-bottom` property of the corresponding `@page` rule.
- `margin-left`
- : A string representing the `margin-left` property of the corresponding `@page` rule.
- `pageOrientation`
- : A string representing the `page-orientation` property of the corresponding `@page` rule.
- `page-orientation`
- : A string representing the `page-orientation` property of the corresponding `@page` rule.
- `size`
- : A string representing the `size` property of the corresponding `@page` rule.

## Instance methods

_This interface inherits the methods of its parent, {{domxref("CSSStyleDeclaration")}}._

## Examples

### Inspecting a page rule

This example gets the `CSSPageDescriptors` for a {{cssxref("@page")}} rule, if the object is supported on the browser, and then logs its properties.

```html hidden
<pre id="log"></pre>
```

```js hidden
const logElement = document.querySelector("#log");
function log(text) {
logElement.innerText = `${logElement.innerText}${text}\n`;
logElement.scrollTop = logElement.scrollHeight;
}
```

```css hidden
#log {
height: 280px;
overflow: scroll;
padding: 0.5rem;
border: 1px solid black;
}
```

#### CSS

Below we define styles for the page using a {{cssxref("@page")}} rule.
We assign different values for each margin property using the `margin` shorthand, and also specify the `size`.
We don't set the `page-orientation`.
This allows us to see how the properties map in the Web API object.

```css
@page {
margin: 1cm 2px 3px 4px;
/* page-orientation: upright; */
size: A4;
}
```

#### JavaScript

First we check if `CSSPageDescriptors` is defined on the global window object, and if not we log that the interface is not supported.

If `CSSPageDescriptors` is supported, we get the document stylesheet at index `1`, and then gets the `cssRules` defined in that stylesheet.
We need to get this stylesheet because the example is embedded in a separate frame with its own sheet.

We then iterate through the rules defined for the live example and match any that are of type `CSSPageRule`, as these correspond to `@page` rules.
For the matching objects we then log the `style` and all its values.

```js
if (typeof window.CSSPageDescriptors === "undefined") {
log("CSSPageDescriptors is not supported on this browser.");
} else {
// Get stylesheets for example and then get its cssRules
const myRules = document.styleSheets[1].cssRules;
for (let i = 0; i < myRules.length; i++) {
if (myRules[i] instanceof CSSPageRule) {
log(`${myRules[i].style}`);
log(`margin: ${myRules[i].style.margin}`);

// Access properties using CamelCase properties
log(`marginTop: ${myRules[i].style.marginTop}`);
log(`marginRight: ${myRules[i].style.marginRight}`);
log(`marginBottom: ${myRules[i].style.marginBottom}`);
log(`marginLeft: ${myRules[i].style.marginLeft}`);
log(`pageOrientation: ${myRules[i].style.pageOrientation}`);

// Access properties using snake-case properties
log(`margin-top: ${myRules[i].style["margin-top"]}`);
log(`margin-right: ${myRules[i].style["margin-right"]}`);
log(`margin-left: ${myRules[i].style["margin-left"]}`);
log(`margin-bottom: ${myRules[i].style["margin-bottom"]}`);
log(`page-orientation: ${myRules[i].style["page-orientation"]}`);

log(`size: ${myRules[i].style.size}`);

// Log the original CSS text using inherited property: cssText
log(`cssText: ${myRules[i].style.cssText}`);
log("\n");
}
}
}
```

#### Results

The results are shown below.
Note that the `style` object displayed at the top of the log should be a `CSSPageDescriptors` to match the current specification, but may be a `CSSStyleDeclaration` in some browsers.
Note also that the corresponding values for properties in camel- and snake-case match each other and the `@page` declaration, and that `page-orientation` is the empty string `""` because it is not defined in `@page`.

{{EmbedLiveSample("Inspecting a page rule", "100%", "350px")}}

## Specifications

{{Specifications}}

## Browser compatibility

{{Compat}}
60 changes: 57 additions & 3 deletions files/en-us/web/api/csspagerule/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,73 @@ _Inherits methods from its ancestors {{domxref("CSSGroupingRule")}} and {{domxre

## Examples

The stylesheet includes a single {{cssxref("@page")}} rule, therefore the first (and only) rule returned will be a `CSSPageRule`.
### Filtering for page rules

This example shows how you can find `CSSPageRule` objects for {{cssxref("@page")}} rules loaded by the document.

```html hidden
<pre id="log"></pre>
```

```js hidden
const logElement = document.querySelector("#log");
function log(text) {
logElement.innerText = `${logElement.innerText}${text}\n`;
logElement.scrollTop = logElement.scrollHeight;
}
```

```css hidden
#log {
height: 220px;
overflow: scroll;
padding: 0.5rem;
border: 1px solid black;
}
```

#### CSS

Below we define styles for the page using a {{cssxref("@page")}} rule.

```css
@page {
margin: 1cm;
}
```

#### JavaScript

The code iterates through all the sheets in the document, and through all the `cssRules` in each sheet, logging the sheet number, the number of rules, and the type of each rule object.
We then detect `CSSPageRule` objects using their type (doing nothing with the information).

```js
let myRules = document.styleSheets[0].cssRules;
console.log(myRules[0]); // a CSSPageRule
for (
let sheetCount = 0;
sheetCount < document.styleSheets.length;
sheetCount++
) {
const sheet = document.styleSheets[sheetCount].cssRules;
log(`styleSheet: ${sheetCount}`);

const myRules = document.styleSheets[sheetCount].cssRules;
log(`rules: ${myRules.length}`);
for (let i = 0; i < myRules.length; i++) {
log(`rule: ${myRules[i]}`);
if (myRules[i] instanceof CSSPageRule) {
//... Do something with CSSPageRule
}
}
}
```

#### Results

The results are shown below.
As you can see there are a two sheets, corresponding to this main document and the example code frame, and each have a number of rules, only one of which is our `CSSPageRule`.

{{EmbedLiveSample("Filtering for page rules", "100%", "300px")}}

## Specifications

{{Specifications}}
Expand Down
96 changes: 82 additions & 14 deletions files/en-us/web/api/csspagerule/style/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,104 @@ browser-compat: api.CSSPageRule.style

{{APIRef("CSSOM")}}

The **`style`** read-only property of the {{domxref("CSSPageRule")}} interface returns a {{domxref("CSSStyleDeclaration")}} object. This represents an object that is a [CSS declaration block](/en-US/docs/Web/API/CSS_Object_Model/CSS_Declaration_Block), and exposes style information and various style-related methods and properties.
The **`style`** read-only property of the {{domxref("CSSPageRule")}} interface returns a {{domxref("CSSPageDescriptors")}} object.
This represents a [CSS declaration block](/en-US/docs/Web/API/CSS_Object_Model/CSS_Declaration_Block) for a CSS {{cssxref("@page")}} rule, and exposes style information and various style-related methods and properties for the page.

## Value

A {{domxref("CSSStyleDeclaration")}} object, which represents a [CSS declaration block](/en-US/docs/Web/API/CSS_Object_Model/CSS_Declaration_Block) with the following properties:
A {{domxref("CSSPageDescriptors")}} object with properties that match the associated {{cssxref("@page")}} rule.

- computed flag
- : Unset.
- declarations
- : The declared declarations in the rule, in the order they were specified, shorthand properties expanded to longhands.
- parent CSS rule
- : The context object, which is an alias for [this](https://heycam.github.io/webidl/#this).
- owner node
- : Null.
> **Note:** Earlier versions of the specification defined this property as a {{domxref("CSSStyleDeclaration")}}.
> Check the compatibility data below for your browser.
## Examples

The stylesheet includes a {{cssxref("@page")}} rule. Getting a list of rules, then returning the value of the style property will return a {{domxref("CSSStyleDeclaration")}} object.
### Inspecting a page rule

This example uses the Web API to inspect the content of a {{cssxref("@page")}} rule.

```html hidden
<pre id="log"></pre>
```

```js hidden
const logElement = document.querySelector("#log");
function log(text) {
logElement.innerText = `${logElement.innerText}${text}\n`;
logElement.scrollTop = logElement.scrollHeight;
}
```

```css hidden
#log {
height: 230px;
overflow: scroll;
padding: 0.5rem;
border: 1px solid black;
}
```

#### CSS

Below we define styles for the page using a {{cssxref("@page")}} rule.
We assign different values for each margin property using the `margin` shorthand, and also specify the `size`.
We don't set the `page-orientation`.
This allows us to see how the properties map in the Web API object.

```css
@page {
margin: 1cm;
margin: 1cm 2px 3px 4px;
/* page-orientation: upright; */
size: A4;
}
```

#### JavaScript

The code first gets the document stylesheet at index `1`, and then gets the `cssRules` defined in that stylesheet.
We need to get this stylesheet because the example is embedded in a separate frame with its own sheet (index `0` is the CSS for this page).

```js
const myRules = document.styleSheets[1].cssRules;
```

We then iterate through the rules defined for the live example and match any that are of type `CSSPageRule`, as these correspond to `@page` rules.
For the matching objects we then log the `style` and all its values.

```js
let myRules = document.styleSheets[0].cssRules;
console.log(myRules[0].style); // returns a CSSStyleDeclaration object
for (let i = 0; i < myRules.length; i++) {
if (myRules[i] instanceof CSSPageRule) {
log(`${myRules[i].style}`);
log(`margin: ${myRules[i].style.margin}`);

// Access properties using CamelCase properties
log(`marginTop: ${myRules[i].style.marginTop}`);
log(`marginRight: ${myRules[i].style.marginRight}`);
log(`marginBottom: ${myRules[i].style.marginBottom}`);
log(`marginLeft: ${myRules[i].style.marginLeft}`);
log(`pageOrientation: ${myRules[i].style.pageOrientation}`);

// Access properties using snake-case properties
log(`margin-top: ${myRules[i].style["margin-top"]}`);
log(`margin-right: ${myRules[i].style["margin-right"]}`);
log(`margin-left: ${myRules[i].style["margin-left"]}`);
log(`margin-bottom: ${myRules[i].style["margin-bottom"]}`);
log(`page-orientation: ${myRules[i].style["page-orientation"]}`);

log(`size: ${myRules[i].style.size}`);
log("\n");
}
}
```

#### Results

The results are shown below.
Note that the object should be a `CSSPageDescriptors` to match the current specification, but may be a `CSSStyleDeclaration` in some browsers.
Note also that the corresponding values for properties in camel- and snake-case match each other and the `@page` declaration, and that `page-orientation` is the empty string `""` because it is not defined in `@page`.

{{EmbedLiveSample("Inspecting a page rule", "100%", "300px")}}

## Specifications

{{Specifications}}
Expand Down
1 change: 1 addition & 0 deletions files/jsondata/GroupData.json
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@
"CSSMediaRule",
"CSSNamespaceRule",
"CSSPageRule",
"CSSPageDescriptors",
"CSSFontFeatureValuesRule",
"CSSFontPaletteValuesRule",
"CSSPropertyRule",
Expand Down

0 comments on commit 2f2ece2

Please sign in to comment.