Computing Page-margin Box Dimension
Reference specifications: https://www.w3.org/TR/css3-page/#margin-dimension
This issue describe some page-margin box calculations, i.e. the width and height of each page-margin box.
Page-margin boxes are boxes within the page margin, there default value are created when margins are declared in the @page rules, they are positioned with respect to the page area.
At-rules for page-margin boxes Page-margin boxes are created by margin at-rules inside the page context.
We define for this issues five types of margin box :
- Top margins: @top-left, @top-center and @top-right
- Bottom margins: @bottom-left, @bottom-center and @bottom-right
- Left margins: @left-top, @left-middle and @left-bottom
- Right margins: @right-top, @right-middle and @right-bottom
- Corner margins: @top-left-corner, @top-right-corner, @bottom-left-corner @bottom-right-corner
For each types of margins boxes, the margin boxes that compose them are considered together for calculation.
Model for calculations
For top margins and bottom margins, the model as follow is defined:
If this model represent the top margins:
- A = @top-left
- B = @top-center
- C = @top-right
For left margins and right margins, it's the same model but width
is replaced by height
.
Top margins (we consider width for calculation, the height never change)
- A = @top-left /
.pagedjs_page .pagedjs_margin-top-left { }
- B = @top-center /
.pagedjs_page .pagedjs_margin-top-center { }
- C = @top-right /
.pagedjs_page .pagedjs_margin-top-right { }
Bottom margins (we consider width for calculation, the height never change)
- A = @bottom-left /
.pagedjs_page .pagedjs_margin-bottom-left { }
- B = @bottom-center /
.pagedjs_page .pagedjs_margin-bottom-center { }
- C = @bottom-right /
.pagedjs_page .pagedjs_margin-bottom-right { }
Left margins (we consider height for calculation, the width never change)
- A = @left-top /
.pagedjs_page .pagedjs_margin-left-top { }
- B = @left-middle /
.pagedjs_page .pagedjs_margin-left-middle { }
- C = @left-bottom /
.pagedjs_page .pagedjs_margin-left-bottom { }
Right margins (we consider height for calculation, the width never change)
- A = @right-top /
.pagedjs_page .pagedjs_margin-right-top
{ } - B = @right-middle /
.pagedjs_page .pagedjs_margin-right-middle
{ } - C = @right-bottom /
.pagedjs_page .pagedjs_margin-right-bottom
{ }
Generated margin boxes
A margin box is considered generated when a content property (content: none | <content>;
) and/or a size property (width
, max-width
, min-width
, height
, max-height
, min-height
) is declared in is margin rules.
In the following example, @top-left
, @top-center
and @bottom-left
are generated but not @bottom-center
and the other margin boxes of the page.
@page {
@top-left { content: "counter(page)" }
@top-center{ width: 50px; }
@bottom-left { content: none }
@bottom-center { }
}
Note: I add the rules for the size property, the W3C specifications are only about the content:
As with the ‘:before’ and ‘:after’ pseudo-elements, a specified ‘content: normal’ on a page-margin box computes to ‘none’. A page-margin box is generated if and only if the computed value of its ‘content’ property is not ‘none’. Otherwise, no box is generated, as for elements with ‘display: none’.
https://www.w3.org/TR/css3-page/#populating-margin-boxes
Page-Margin Box Variable Dimension Computation Rules
The high-level goals are (in order of priority) to center the middle box (B) if it is generated, to minimize overflow and overlap, and to distribute space proportionally to the amount of content.
https://www.w3.org/TR/css3-page/#variable-auto-sizing
This specification can be followed with the following patterns.
For top and bottom margins, "size" correspond to width.
max-width
, min-width
are transformed into width
.
For left and right margins, "size" correspond to height.
max-height
, min-height
are transformed into height
.
Only one box is generated
The extent of the margin box is allowed to cross the other margin boxes.
A generated (auto size) && B, C not generated
<=>
B, C { size: 0; flex-grow: 0; }
A generated (sizeA) && B, C not generated
<=>
A { size: <sizeA>; flex-grow: 0; }
B generated (auto size) && A, C not generated
<=>
A, C { size: 0; flex-grow: 0; }
B generated (sizeB) && A, C not generated
<=>
B { size: <sizeB>; flex-grow: 0; }
C generated (auto size) && A, B not generated
<=>
A, B { size: 0; flex-grow: 0; }
C generated (sizeC) && A, B not generated
<=>
C { size: <sizeC>; flex-grow: 0; }
2 box are generated
auto size for all
<=>
nothing
A (auto size), B (sizeB) generated / auto && C not generated
<=>
B { size: <sizeB>; flex-grow: 0; }
A (sizeA), B (auto size) generated / auto && C not generated
<=>
A, C { size: <sizeA>; flex-grow: 0; }
A (sizeA), B (sizeB) generated / auto && C not generated
<=>
A { size: <sizeA>; flex-grow: 0; }
B { size: <sizeB>; flex-grow: 0; }
A (auto size), C (sizeC) generated / auto && B not generated
<=>
B { size: 0; flex-grow: 0; }
C { size: <sizeC>; flex-grow: 0; }
A (sizeA), C (auto) generated / auto && B not generated
<=>
A { size: <sizeA>; flex-grow: 0; }
B { size: 0; flex-grow: 0; }
A (sizeA), C (sizeC) generated / auto && B not generated
<=>
A { size: <sizeA>; flex-grow: 0; }
C { size: <sizeC>; flex-grow: 0; }
B (auto size), C (sizeC) generated / auto && A not generated
<=>
A, C { size: <sizeC>; flex-grow: 0; }
B (sizeB), C (sizeC) generated / auto && A not generated
<=>
B { size: <sizeB>; flex-grow: 0; }
C { size: <sizeC>; flex-grow: 0; }
3 box are generated
auto size for all
<=>
nothing
A (sizeA), B (auto size), C (auto size)
<=>
A, C { size: <sizeA>; flex-grow: 0; }
A (auto size), B (sizeB), C (auto size)
<=>
B { size: <sizeB>; flex-grow: 0; }
A (auto size), B (auto size), C (sizeC)
<=>
A, C { size: <sizeC>; flex-grow: 0; }
A (sizeA), B (sizeB), C (auto size)
<=>
A { size: <sizeA>; flex-grow: 0; }
B { size: <sizeB>; flex-grow: 0; }
A (sizeA), B (auto size), C (sizeC)
<=>
A { size: <sizeA>; flex-grow: 0; }
C { size: <sizeC>; flex-grow: 0; }
A (auto size), B (auto size), C (sizeC)
<=>
A, C { size: <sizeC>; flex-grow: 0; }
A (sizeA), B (sizeB), C (sizeC)
<=>
A { size: <sizeA>; flex-grow: 0; }
B { size: <sizeB>; margin: 0 auto; flex-grow: 0; }
C { size: <sizeC>; flex-grow: 0; }