Copyright © 2014-2018 Bert Frees
This specification presents new features to fully support the media type embossed, i.e. to print braille on paper. The specification is derived from CSS2 [CSS2] and CSS3.
This document is merely a public working draft of a potential specification. It has no official standing of any kind and does not represent the support or consensus of any standards organisation.
Braille CSS was invented by the creators of DAISY Pipeline 2 as a means of configuring the braille production scripts, and as an interface between software components.
Although the media types braille (intended for braille tactile feedback devices) and embossed (intended for paged braille printers) exist, there is no support in CSS2 [CSS2] and CSS3 for actually laying out content for braille devices or braille paper. Because of its very restricted grid layout and its bulkiness, braille has rather specific requirements, and the styling possibilities are limited. Therefore it was decided to make a custom CSS specification that would support all the features specific to braille.
Braille CSS has become a pick-and-mix of existing CSS2 and CSS3 features and new ones. While virtually all of the core concepts of CSS remain intact, a great deal of existing features were either not incorporated, or were incorporated in a slimmed-down form. One reason is that a lot of features simply don't make sense in the context of braille. Also, for the sake of simplicity, the authors didn't bother to include features that are not supported by implementations. Still it was chosen not to write the specification from scratch but to explicitely reference existing specifications whenever possible and to explain the differences.
While the main purpose of this specification is a practical one, namely to support the use and development of the DAISY Pipeline 2 braille production scripts, we hope to evolve towards full compatilbity with CSS in the long run. In order achieve this, braille CSS will have to define how implementations should cope with all possible CSS rules and properties, given the limited rendering possilities in the context of braille. But in addition, CSS would also have to be extended to support features specific to braille.
If you would like to give feedback or contribute to this specification, please file issues at this project's home on GitHub.
This section is non-normative.
Braille is a tactile writing system used by the blind and visually impaired. Each braille character is formed within a rectangular box with fixed dimensions known as a braille cell. A character is made up of up to six raised dots arranged in a 3 x 2 configuration, which yields sixty-four possible combinations. In eight-dot braille, a full braille cell consists of eight (4 x 2) dots and there are 256 combinations. Unicode has reserved the U+2800..U+28FF range for the Braille Patterns block.
The process of transforming text to braille is called braille transcription. The rules that define the braille transcription in a certain language form the braille code of that language. There are hundreds of braille codes in use all over the world. Each language can have several codes, and each code can have several variants.
Braille can be read on paper or on a refreshable braille display connected to a computer. Most braille printers (also called embossers) and braille displays have a fixed-pitch character grid or matrix layout. If m represents the maximal number of lines a page can contain and n is the maximal number of cells in a line, then a cell can only appear in one of m x n possible positions.
Because braille cells take up a lot of space compared to printed words, paper braille books are considerably bulkier than regular books. Usually braille books are divided into several volumes in order to make them more handleable and suitable for distribution.
Agents supporting braille CSS can be subdivided into two categories:
This specification follows the CSS property definition conventions from [CSS2]. In addition to the property-specific values listed in their definitions, all properties defined in this specification also accept the inherit and initial keywords as their values. For readability they have not been repeated explicitly.
Value types, properties, functions and at-rules not defined in this specification are defined in CSS Level 2 Revision 1 [CSS2] or in other CSS modules. External definitions will always be explicitely referenced from this specification. This specification will further expand, restrict or override definitions. In that case the differences will be explained in informative notes.
The examples included in this specification serve as illustrations as well as tests for two implementations of braille CSS that are being developed within the DAISY Pipeline 2 project. Test results of the Liblouis based renderer are marked with an “L”, those of the Dotify based renderer are marked with a “D”.
Examples are set off from the normative test with a yellow box, like this:
This is an example.
Notes are set off from the normative test with a green box, like this:
This is an informative note.
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in this specification are to be interpreted as described in [RFC2119].
[CSS3SYN] describes the basic structure and syntax of CSS stylesheets. The syntax also applies to braille CSS.
Implementations of braille CSS may support vendor-specific properties and values. To avoid clashes with future CSS features, the [CSS2] specification reserves a prefixed syntax for proprietary extensions. Other implementations that not recognize such vendor-prefixed properties should ignore them.
For all known implementations with proprietary extensions, include references to relevant documentation. For example, the Dotify based implementation may support -obfl- prefixed properties. See braille-css#36.
[CSS3VAL] describes the common values and units that CSS properties accept and the syntax used for describing them in CSS property definitions. Some but not all of them apply to braille CSS. The following types are redefined or newly defined:
<length> redefines <length> [CSS3VAL], <braille-character> and <braille-string> are new.
See braille-css#25.
See braille-css#26.
Some document formats, such as HTML, have a style attribute to permit the author to directly apply style information to specific elements. The style attribute's syntax and interpretation in defined in [CSSSTYLEATTR]:
inline-stylesheet
: S* declaration? [ ';' S* declaration? ]*
;
Interpreters may optionally support an extension of this syntax:
inline-stylesheet
: declaration-list [ S+ inline-ruleset ]*
;
declaration-list
: S* declaration? [ ';' S* declaration? ]*
;
inline-ruleset
: '&'? S* [ [ '>' | '+' | '~' ]? S* selector ]+ S* '{' declaration-list '}' S*
;
This syntax is inspired by Sass [SASS]. The inline rulesets apply to elements relative to the element to which the style attribute belongs. A ‘&’ (ampersand) indicates the position of the base element within the combined selector expression. Without a ‘&’, a space between the base element and the relative selector is assumed. If a ‘&’ is present and is no space of other combinator separates it from the relative selector, it means the relative selector is effectively “chained” onto the base element as if it where a single sequence of simple selectors.
Specifying media-dependent style sheets is done using media types [CSS2]. For braille CSS, only one media type is relevant: a braille renderer shall only take into account style sheet rules for media type embossed (or all).
A braille translator may also look at other media types (notably print) in order to find hints for the translation. A typical use case is text-level styling in print such as boldfacing or italicizing which is conveyed in braille using braille indicators.
Add examples of other media types. See braille-css#27.
Allow media braille in addition to embossed in order to differentiate between properties that only make sense for braille on paper, and properties that make sense on refreshable braille displays too (examples would be white-space, hyphens, hyphen-character, text-transform, etc.). See braille-css#1.
See braille-css#29.
The CSS Box model [CSS3BOX] describes how each element and each string of text is laid out by transforming the document tree into a tree of rectangular boxes, each consisting of a content area and optional surrounding padding, border and margin areas. Braille CSS has a slightly simplified model.
Each element in the document tree generates zero or more boxes. Some other boxes are not the direct result of an element, such as for instance line boxes, page boxes, and anonymous boxes. The parent box of another box is called the containing box or container. In general, generated boxes of an element act as containing boxes of descendant elements.
Elements that are broken across lines or pages result in box fragments. The generic term for containers like line and page boxes is fragmentainers. How content breaks across fragmentainers is described in the section Box Model for Breaking [CSS3BREAK].
The position and size of an element's box(es) are often calculated with respect to the edges of a certain rectangle, called the containing block. The containing block in which the root element lives is called the initial containing block which coincidences with the page area box. Note that the initial containing block depends on the context. Different pages have different initial containing blocks. For other elements, the containing block is formed by the content edge of the nearest block-level ancestor box.
These simplified definitions are equivalent to the original definitions of containing block and initial containing block [CSS3BOX] [CSS3POS], considering that braille CSS does not support continuous media or anything other than static positioning.
There are page boxes, block-level boxes, line boxes and inline-level boxes. A block-level box is like a paragraph, a line box like a line of text, and inline-level boxes like words inside a line. Page boxes are described in the section Paged Media. Boxes are laid out according to the normal flow positioning scheme, which consists of block formatting of block-level boxes and inline formatting of inline-level boxes.
As opposed to [CSS2] where boxes can be floated or positioned absolutely as well, braille CSS only supports the normal flow positioning scheme. Another difference is that normal flow in braille CSS doesn't include relative positioning.
Elements with a value of block or list-item for the display property are called block-level elements. Block-level elements generate block-level boxes, which are boxes that participate in a block formatting context. In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block. The vertical distance between two sibling boxes is determined by the margin properties. Vertical margins between adjacent block-level boxes collapse.
In general, each box's left and right outer edges touch the left and right edges of the containing block. The following constraint must hold:
margin-left + border-left-width + padding-left + width + padding-right + border-right-width + margin-right = width of containing block
In the equation above, border-left-width is equal to 1 if the value of border-left is not none, or 0 otherwise. Similarly, border-right-width is equal to 1 if the value of border-right is not none, or 0 otherwise.
However, if an element is positioned, the box's edges don't need to touch the edges of the containing block. In this case the equation becomes:
left offset + margin-left +
border-left-width + padding-left +
width + padding-right +
border-right-width + margin-right + right
offset = width of initial containing block
Here, left offset is equal to the value of left if it is not auto, or otherwise the distance from the left edge of the containing block to the left edge of the initial containing block. Likewise, right offset is equal to the value of right if it is not auto, or otherwise the distance from the right edge of the containing block to the right edge of the initial containing block.
If a box has only inline-level children, the height is the number of line boxes. An empty box has height ‘0’. If the box has block-level children, the height is the distance between the top border-edge of the topmost block-level child box that doesn't have margins collapsed through it and the bottom border-edge of the bottommost block-level child box that doesn't have margins collapsed through it. However, if the element has a nonzero top padding and/or top border, then the content starts at the top margin edge of the topmost child. Similarly, if the element has a nonzero bottom padding and/or bottom border, then the content ends at the bottom margin edge of the bottommost child.
Block formatting in braille CSS is considerably simplified with respect to [CSS2] and [CSS3BOX]. Since there is no floating, no absolute positioning and no display: inline-block, each page has only a single block formatting context. Furthermore, the text orientation is always left-to-right and top-to-bottom (it is as if the direction and writing-mode properties would have their values set to ltr and horizontal-tb). Finally, because there can be no replaced elements and there are no width, height, min-width, min-height, max-width and max-height’ properties (it is as if their values would be set to auto, auto, 0, 0, none and none), calculating widths, heights and margins becomes rather trivial.
Elements with a value of inline for the display property are called inline-level elements. Inline-level elements generate inline-level boxes, which are boxes that participate in an inline-level formatting context. In an inline-level formatting context, boxes are laid out horizontally, one after the other, beginning at the top of a containing block. The rectangular area that contains the boxes that form a line is called a line box. Line boxes are created as needed to hold inline-level content. Line boxes are never empty and do never hold collapsible white space only.
The height of a line box is determined by the line-height property, which has an initial value of 1. The width of a line box is determined by the containing block. The left edge of a line box touches the left edge of its containing block and the right edge touches the right edge of its containing block.
When the total width of the inline-level boxes on a line is less than the width of the line box containing them, their horizontal distribution within the line box is determined by the text-align property. When an inline box exceeds the width of a line box, it is split into several boxes and these boxes are distributed across several line boxes.
Inline formatting in braille CSS is simplified with respect to [CSS2] and [CSS3TEXT]. The height of a line box is always equal to 1, and there is no inline-level alignment.
Anonymous boxes are created when the box model requires a child box with a certain value for display, but the child actually has a different value.
The properties of anonymous boxes are inherited from the enclosing non-anonymous box. Non-inherited properties have their initial value.
The adjoining margins of two or more boxes (which might or might not be siblings) may combine to form a single margin. Margins that combine this way are said to “collapse”. Margins are adjoining if there are no line boxes, padding or border areas to separate them. Adjoining vertical margins collapse, horizontal margins don't. A collapsed margin is considered adjoining to another margin if any of its component margins is adjoining to that margin (collapsing is “transitive”). When two or more margins collapse, the the width of the resulting margin is the maximum of the collapsing margins' widths.
This simplified definition is equivalent to the original definition of collapsing margins [CSS2] [CSS3BOX], considering that in braille CSS each page has only a single block formatting context, that the height of block-level boxes are auto-computed, that boxes can have no negative top or bottom margins, that the margin properties do not apply on inline-level boxes and that there is no floating, no clearance, no overflow, no absolute positioning, no vertical boxes and no display: inline-block.
In the Liblouis implementation, paddings currently collapse. See pipeline-mod-braille#12. Also, the behavior of margins in liblouis at the top of pages is not according to CSS.
Name: | display |
---|---|
Value: | block | inline | list-item | none |
Initial: | inline |
Applies to: | all elements and pseudo-elements |
Inherited: | no |
Media: | embossed |
Computed value: | the specified value |
This property determines the type of box(es) that are generated for an element. The values are as follows:
An element is said to be positioned if its left or right properties have a value other than auto.
Name: | left, right |
---|---|
Value: | <length> | auto |
Initial: | auto |
Applies to: | block | list-item |
Inherited: | no |
Media: | embossed |
Computed value: |
The left and right properties... Values have the following meanings:
Name: | margin-top, margin-right, margin-bottom, margin-left |
---|---|
Value: | <length> |
Initial: | 0 |
Applies to: | block | list-item | @page |
Inherited: | no |
Media: | embossed |
Computed value: | see text |
For block and list-item elements, the margin properties set the thickness of the margin area. The value may be a negative length for margin-left and margin-right.
In a page context, margin-top and margin-bottom set the height of the top and bottom page-margin areas. The value must be a non-negative <length>.
These properties have a number differences with the original margin properties defined in [CSS3BOX]:
<body> <p> ⠤⠤⠤ </p> </body>
@page { size: 10 3; } p { display: block; margin-left: 1; }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="3" cols="10" rowgap="0" duplex="true"> <section> <page> <row>⠀⠤⠤⠤</row> </page> </section> </volume> </body> </pef>
The value of margin-left may be negative:
@page { size: 10 3; } body { display: block; margin-left: 3; } p { display: block; margin-left: -1; }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="3" cols="10" rowgap="0" duplex="true"> <section> <page> <row>⠀⠀⠤⠤⠤</row> </page> </section> </volume> </body> </pef>
Name: | margin |
---|---|
Value: | [ <length> | auto ]{1,4} |
Initial: | (see individual properties) |
Applies to: | block | list-item |
Inherited: | no |
Media: | embossed |
Computed value: | (see individual properties) |
margin is a shorthand for the other four properties. If margin has four values, they set top, right, bottom and left in that order. If left is omitted, it is the same as right. If bottom is omitted, it is the same as top. If right is omitted it is the same as top.
@page { size: 10 3; } p { display: block; margin: 1; }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="3" cols="10" rowgap="0" duplex="true"> <section> <page> <row/> <row>⠀⠤⠤⠤</row> </page> </section> </volume> </body> </pef>
Name: | padding-top, padding-right, padding-bottom, padding-left |
---|---|
Value: | <length> |
Initial: | 0 |
Applies to: | block | list-item |
Inherited: | no |
Media: | embossed |
Computed value: | the specified value |
Padding properties set the thickness of the padding area. The value may not be negative.
These properties have a number differences with the original padding properties defined in [CSS3BOX]:
Name: | padding |
---|---|
Value: | <length>{1,4} |
Initial: | (see individual properties) |
Applies to: | block | list-item |
Inherited: | no |
Media: | embossed |
Computed value: | (see individual properties) |
padding is a shorthand for the other four properties. If padding has four values, they set top, right, bottom and left in that order. If left is omitted, it is the same as right. If bottom is omitted, it is the same as top. If right is omitted it is the same as top.
Name: | border-top, border-right, border-bottom, border-left |
---|---|
Value: | <braille-character> | none |
Initial: | none |
Applies to: | block | list-item |
Inherited: | no |
Media: | embossed |
Computed value: | the specified value |
These properties set the style of the top, right, bottom, and left border of a box. Values have the following meanings:
Name: | border |
---|---|
Value: | [ <braille-character> | none ]{1,4} |
Initial: | (see individual properties) |
Applies to: | block | list-item |
Inherited: | no |
Media: | embossed |
Computed value: | (see individual properties) |
border is a shorthand for the other four. Its four values set the top, right, bottom and left border respectively. A missing left is the same as right, a missing bottom is the same as top, and a missing right is also the same as top.
<body> <h> ⠿⠿⠿ </h> </body>
@page { size: 10 3; } h { display: block; padding: 0 1; border: ⠒ ⠸ ⠒ ⠇; }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="3" cols="10" rowgap="0" duplex="true"> <section> <page> <row>⠖⠒⠒⠒⠒⠒⠒⠒⠒⠲</row> <row>⠇⠀⠿⠿⠿⠀⠀⠀⠀⠸</row> <row>⠓⠒⠒⠒⠒⠒⠒⠒⠒⠚</row> </page> </section> </volume> </body> </pef>
User agents in the ‘braille renderer’ category require that the document text (as well as text in content properties) consists of only white space characters and Unicode braille. Braille translators don't have this restriction, they can transform text to braille when necessary. The transformation from text to braille can be controlled on element level with the text-transform property.
The specification doesn't impose a specific ordering between text transformation, white space processing and line breaking, as long as in the end the white space processing, line breaking and braille translation rules are satisfied, and all text can be rendered in braille cells.
When document text does not consist solely of Unicode braille and white space, the braille translator transforms it to braille somehow. How text is supposed to be transformed depends on the braille code but also on the context. The text-transform property can be used for providing the translator with all the necessary context information to do its job correctly.
Name: | text-transform |
---|---|
Value: | auto | <custom-ident> + |
Initial: | auto |
Applies to: | all elements and pseudo-elements and margin contexts, and @counter-style rules |
Inherited: | yes |
Media: | embossed |
Computed value: | Values are inherited in a special way (see below). |
Because braille transcription is a complex process influenced by braille codes and other factors, the possible values for text-transform and their exact meanings are UA-dependent.
In order to get some indication of what kind of values could be supported and to create uniformity across braille codes, a grammar could be made with a list of possible values and approximate meanings.
Values are inherited in a cumulative way:
There is a fundamental difference between this property and the original text-transform property as defined in [CSS3TEXT]. While the original property is about describing basic character transforms (e.g. case transforms) for styling purposes, the Braille CSS property is about influencing the braille transcription. It is obvious that a transformation to another writing system is much more complex than simple case transforms, and this explains why the Braille CSS property can have arbitrary values whereas the original property has well-defined values (except for the capitalize value which depends on how word boundaries are determined).
Note that for certain text-transform values such as e.g. uppercase one could consider the transformation to braille as a two-step process consisting of a text-to-text step and a text-to-braille step. However there is no reason to make that distinction explicit as it would only be limiting.
See braille-css#30.
The source text of a document often contains formatting that is not relevant to the final rendering: for example, breaking the source into segments (lines) for ease of editing, or adding white space characters such as tabs and spaces to indent the source code. The interpretation of such formatting can be controlled with the white-space property. The property specifies whether and how white space is collapsed and whether lines may wrap at unforced soft wrap opportunities.
Name: | white-space |
---|---|
Value: | normal | pre-wrap | pre-line |
Initial: | normal |
Applies to: | all elements and pseudo-elements and margin contexts |
Inherited: | yes |
Media: | embossed |
Computed value: | the specified value |
Values have the following meanings, which must be interpreted according to the white space processing and line breaking rules:
White space processing affects only the white space characters: spaces (U+0020 space), braille spaces (U+2800 braille pattern blank), tabs (U+0009 character tabulation), and segment breaks (U+000D carriage return, U+000A line feed and U+000D U+000A).
Within an inline formatting context, white space characters are processed as follows:
Every braille space and every tab is converted to a normal space (U+0020 space).
If white-space is normal or pre-line, all spaces and tabs immediately preceding or following a segment break are removed.
Segment breaks are transformed for rendering according to the segment break transformation rules:
If white-space is pre-wrap or pre-line, segment breaks are transformed into a preserved line feed (U+000A line feed).
If white-space is normal, segment breaks are converted to a collapsible space (U+0020 space), unless the character immediately before or immediately after the segment break is the zero-width space character (U+200B zero width space (zwsp)), then the segment break is removed.
If white-space is normal or pre-line, spaces are considered collapsible. Any space immediately following another collapsible space is collapsed to have zero advance width. It is invisible, but retains its soft wrap opportunity, if any. A translator may in some cases completely remove collapsible spaces.
As an example of space that is dropped between words, in EBAE English braille, “to have” is translated to “⠖⠓”.
If white-space is pre-wrap, any sequence of spaces is treated as a sequence of non-breaking spaces (U+00A0 no-break space (nbsp)). However, a soft wrap opportunity exists at the end of the sequence.
Two characters in the same inline formatting context can follow each other regardless of whether they are within the boundaries of the same inline box.
Then, as inline boxes are laid out:
Sequences of collapsible spaces at the beginning of line boxes are removed.
Each non-collapsed space (U+0020 space) is rendered as a number of empty braille cells specified by the word-spacing property (by default 1). Non-breaking spaces (U+00A0 no-break space (nbsp)) are not considered word-separator characters and are treated as any other character. Zero-width space characters (U+200B zero width space (zwsp)) have a zero advance width.
Sequences of collapsible spaces at the end of line boxes are removed. If spaces at the end of a line are non-collapsible but have white-space set to pre-wrap the UA may visually collapse their character advance widths.
White space that was not removed or collapsed during the white space processing steps is called preserved white space.
When inline-level content is laid out into lines, it is broken across line boxes. Line breaking is based on [CSS3TEXT]:
Lines break at the start and end of blocks (forced line breaks).
Regardless of the white-space value, line-breaking behavior defined for the LF line breaking class in [UAX14] must be honored.
In other words, line breaks are forced at preserved line feed characters (U+000A line feed).
When white-space allows wrapping, line breaking behavior defined for the SP, ZW and GL (NBSP only) line breaking classes in [UAX14] must be honored.
In other words, spaces (U+0020 space) and zero width spaces (U+200B zero width space (zwsp)) form soft wrap opportunities. Non-breaking spaces (U+00A0 no-break space (nbsp)) prohibit breaks unless overruled by a space or zero-width space. Note that if collapsible space between words is completely removed during translation, the soft wrap opportunity is also gone. A translator may also drop zero width spaces, e.g. when they appear inside a contraction.
Hyphenation opportunities create soft wrap opportunities within words (see Breaking within words below).
For soft wrap opportunities before the first or after the last character of a box, the break occurs immediately before/after the box (at its margin edge) rather than breaking the box between its content edge and the content.
See braille-css#31.
Hyphenation allows the controlled splitting of words to improve the layout of paragraphs, typically splitting words at syllabic or morphemic boundaries and visually indicating the split. Especially for braille, where space is very limited, hyphenation can have a significant impact on the layout. Braille CSS does not define the rules for hyphenation, but provides ways to control whether hyphenation is allowed and how hyphenation opportunities are determined.
Name: | hyphens |
---|---|
Value: | none | manual | auto |
Initial: | manual |
Applies to: | all elements and pseudo-elements |
Inherited: | yes |
Media: | embossed |
Computed value: | the specified value |
Hyphenation is controlled with the hyphens property. Values have the following meanings:
[UAX14] describes the role of soft hyphens in Unicode line breaking.
The hyphenate-character property specifies the character that is rendered at the end of the line before a hyphenation break.
Name: | hyphenate-character |
---|---|
Value: | auto | <braille-character> |
Initial: | auto |
Applies to: | all elements and pseudo-elements |
Inherited: | yes |
Media: | embossed |
Computed value: | the specified value |
The auto value means that it is up to the user agent to find an appropriate value.
The height of a line box is determined by the line-height property of its block container. Values must be strictly positive <length>s. By default the line height is equal to the text height which is always 1. When line-height is set to a higher value, text inside the line box touches the top edge of the box, and space is added at the bottom. All line boxes in a block have the same height, including the last one. In other words, the content area of a block box changes proportionately with the value of line-height. Top and bottom padding and margins however are not affected by line-height.
Allow values between 1 and 2.
Name: | line-height |
---|---|
Value: | <length> |
Initial: | 1 |
Applies to: | block | list-item |
Inherited: | yes |
Media: | embossed |
Computed value: | the specified value |
[CSS3LINE] describes how the vertical positioning of text inside a line box is affected by the vertical-align property. There is no such property in braille CSS. Text is always aligned vertically as if vertical-align were top.
<body> <p> ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ </p> </body>
@page { size: 10 6; } body { display: block; line-height: 2; }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="6" cols="10" rowgap="0" duplex="true"> <section> <page> <row rowgap="4">⠤⠤⠤⠀⠤⠤⠤</row> <row rowgap="4">⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤</row> </page> </section> </volume> </body> </pef>
Margins are not affected by line-height:
<body> <p> ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ </p> </body>
@page { size: 10 6; } body { display: block; line-height: 2; } p { display: block; margin-top: 3; }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="6" cols="10" rowgap="0" duplex="true"> <section> <page> <row/> <row/> <row/> <row rowgap="4">⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> </page> </section> </volume> </body> </pef>
Alternating lines on facing pages can be accomplished with a combination of line-height, @page:right, @page:left and margin-top:
<body> <p> ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ </p> <p> ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ </p> <p> ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ </p> </body>
@page { size: 10 6; } @page:left { margin-top: 1; } body { display: block; line-height: 2; } p { display: block; }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="6" cols="10" rowgap="0" duplex="true"> <section> <page> <row rowgap="4">⠤⠤⠤⠀⠤⠤⠤</row> <row rowgap="4">⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤</row> </page> <page> <row/> <row rowgap="4">⠤⠤⠤⠀⠤⠤⠤</row> <row rowgap="4">⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤</row> </page> <page> <row rowgap="4">⠤⠤⠤⠀⠤⠤⠤</row> <row rowgap="4">⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤</row> </page> </section> </volume> </body> </pef>
See braille-css#32.
Name: | text-align |
---|---|
Value: | left | center | right |
Initial: | left |
Applies to: | block | list-item |
Inherited: | yes |
Media: | embossed |
Computed value: | the specified value |
Name: | text-indent |
---|---|
Value: | <length> |
Initial: | 0 |
Applies to: | block | list-item |
Inherited: | yes |
Media: | embossed |
Computed value: | the specified value |
<body> <p> ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ </p> </body>
@page { size: 10 3; } p { display: block; text-indent: 1; }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="3" cols="10" rowgap="0" duplex="true"> <section> <page> <row>⠀⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤</row> </page> </section> </volume> </body> </pef>
The value of text-indent may be negative:
@page { size: 10 3; } body { display: block; margin-left: 3; } p { display: block; text-indent: -1; }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="3" cols="10" rowgap="0" duplex="true"> <section> <page> <row>⠀⠀⠤⠤⠤⠀⠤⠤⠤</row> <row>⠀⠀⠀⠤⠤⠤⠀⠤⠤⠤</row> <row>⠀⠀⠀⠤⠤⠤</row> </page> </section> </volume> </body> </pef>
The word-spacing property specifies spacing between “words”, expressed in multiples of an empty cell. Values must be non-negative lengths. Word boundaries are determined and word spacing applied as part of the white space processing. By default word-spacing is 1. A zero value results in all inter-word spacing being eliminated.
Name: | word-spacing |
---|---|
Value: | <length> |
Initial: | 1 |
Applies to: | all elements and pseudo-elements and margin contexts |
Inherited: | yes |
Media: | embossed |
Computed value: | the specified value |
This property differs from the original word-spacing property [CSS3TEXT] in that it specifies the absolute inter-word spacing and not the (absolute or relative) additional inter-word spacing. Also, in braille CSS non-breaking spaces are not considered word-separator characters.
The letter-spacing property specifies the spacing, expressed in multiples of an empty cell, between adjacent “base units” of the language, script or text. What these base units are is determined by the braille code. The exact result of applying letter-spacing is therefore UA-dependent.
The base unit could for example be defined as the smallest unit of the script (called a grapheme) which in the case of braille is any (non-blank) braille character (Unicode character in the range U+2801..U+28FF).
Another definition of the base unit could be any group of braille characters that corresponds with a single grapheme when written in a certain other writing system (such as Latin). In the case of contracted braille, this definition could be extended to any group of braille characters that corresponds with a group of graphemes in the other writing system and can not be further divided in smaller such groups.
A last example of a definition is any group of braille characters that corresponds with a single letter in another writing system. This would mean among other things that capital and number signs are attached to the next character, and that punctuation marks are attached to the previous character.
Name: | letter-spacing |
---|---|
Value: | <length> |
Initial: | 0 |
Applies to: | all elements and pseudo-elements and margin contexts |
Inherited: | yes |
Media: | embossed |
Computed value: | the specified value |
The values of letter-spacing must be non-negative <length>s. The default is 0. Letter spacing is not applied at the beginning or at the end of a line. Letter spacing between two characters effectively “belongs” to the innermost element that contains the two characters: the total letter spacing between two adjacent characters is specified by and rendered within the innermost element that contains the boundary between the two characters. Letter spacing ignores zero-width spaces (U+200B zero width space (zwsp)). Non-breaking spaces (U+00A0 no-break space (nbsp)) are treated like any other character.
See braille-css#33.
Pseudo-elements provide a way to insert and style content that does not exist in the source document. Pseudo-elements generate boxes just like normal elements do. For pseudo-elements to be generated, they must not have their content property set to none. In the general case, pseudo-elements inherit any inheritable properties from the element in the document tree to which they are associated (their superior parent), and their boxes are positioned with respect to the superior parent's box. The syntax for selecting pseudo-elements is defined in [CSS3GENCON].
The ::before and ::after pseudo-elements are used to insert content immediately before and immediately after the content of an element (or other pseudo-element). The generated boxes are contained within the superior parent's box. The content property is used to specify the content to insert.
The ::marker pseudo-element is used to represent a list item's marker (the bullet or number identifying the item). For a ::marker pseudo-element to be generated, its superior parent must have a computed display value of list-item. The default value of the pseudo-element's content property is determined by the list-style-type property of its superior parent.
See braille-css#9.
A counter is a special concept used to automatically number list items, pages, etc. [CSS3LIST] describes how counters are created and manipulated with the counter-increment, counter-set and counter-reset properties, and used with the counter() function.
Name: | counter-reset |
---|---|
Value: | [ <custom-ident> <integer>? ]+ | none |
Initial: | none |
Applies to: | all elements and pseudo-elements |
Inherited: | no |
Media: | embossed |
Computed value: | the specified value |
The counter-reset property creates new counters on an element. Its values are defined as follows:
Name: | counter-set |
---|---|
Value: | [ <custom-ident> <integer>? ]+ | none |
Initial: | none |
Applies to: | all elements and pseudo-elements |
Inherited: | no |
Media: | embossed |
Computed value: | the specified value |
Name: | counter-increment |
---|---|
Value: | [ <custom-ident> <integer>? ]+ | none |
Initial: | none |
Applies to: | all elements and pseudo-elements |
Inherited: | no |
Media: | embossed |
Computed value: | the specified value |
The counter-set and counter-increment properties manipulate the value of existing counters. They only create new counters if there is no counter of the given name on the element yet. Their values are defined as follows:
Inheriting counters must be done before resetting counters, which must be done before setting counters, which must be done before incrementing counters, which must be done before using counters.
A counter in an element that does not generate a box cannot be set, reset, or incremented.
Every element has a collection of zero or more counters, which are inherited through the document tree in a special way. A counter and its value are inherited separately, possibly from different elements.
If an element has preceding siblings, it inherits all of the immediately preceding sibling's counters. Otherwise, if the element has a parent, it inherits all of the parent's counters.
The element then inherits counter values from the immediately preceding element in document order. This is done by examining the set of counters that the immediately preceding element has, and, for every counter that exists in both the element's set and the preceding element's set, giving the element's counter the same value.
Additional counters can be created on elements with the counter-reset property. The effect depends on what other counters of that name exist on the element:
The value of the new counter is set to the provided starting value.
A page counter is created automatically on the root element. Its purpose is for numbering braille pages. The counter is implicitely incremented on each page. Depending on the implementation, explicitely setting or incrementing this counter may or may not have an effect. No new counters can be created with the name page.
Implementations may define additional automatic counters.
Counters can be used with the counter() function. This happens automatically in the default contents of ::marker pseudo-elements, but the function can be used anywhere a string value is allowed. The function takes the name of a counter and an optional <counter-style> name (which defaults to decimal) and returns a <string> value:
counter() = counter( <custom-ident> [, [ <counter-style> | none ] ]? )
The <string> value returned by the function is obtained as follows:
<body> ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ </body>
@page { size: 10 5; margin-top: 1; @top-right { content: counter(page); } }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="5" cols="10" rowgap="0" duplex="true"> <section> <page> <row>⠀⠀⠀⠀⠀⠀⠀⠀⠼⠁</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> </page> <page> <row>⠀⠀⠀⠀⠀⠀⠀⠀⠼⠃</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿</row> </page> </section> </volume> </body> </pef>
The @counter-style rule allows the definition of custom counter styles. A @counter-style rule consists of the keyword @counter-style, a name, and a block of declaractions (called desciptors) which define how a counter value is converted into a string. A counter styles's name must be a <custom-ident> not equal to none or decimal. The various descriptors that make up a counter style are described in [CSS3COUNTERSTYLES]. In addition, a counter style in Braille CSS can also have a text-transform descriptor.
User agents must define the decimal counter style as an ultimate fallback style. Agents may include additional predefined styles in their UA stylesheet. All counter styles, predefined or not, except for decimal, can be overridden.
The decimal counter style may be defined as follows:
@counter-style decimal { system: numeric; symbols: '⠚' '⠁' '⠃' '⠉' '⠙' '⠑' '⠋' '⠛' '⠓' '⠊' }
In addition to the steps listed in [CSS3COUNTERSTYLES] for generating a counter representation, user agents in the ‘translator’ category must perform the necessary steps to ensure that the resulting representation is a braille string. The transformation to braille is influenced by the text-transform descriptor.
Name: | list-style-type |
---|---|
Value: | <braille-string> | <counter-style> | none |
Initial: | none |
Applies to: | list-item |
Inherited: | yes |
Media: | embossed |
Computed value: | specified value |
The list-style-type property is used to construct the default contents of a list item's marker; otherwise, list-style-type is ignored. The values are defined as follows:
<counter-prefix> counter( list-item, <counter-style> )
<counter-suffix>
where <counter-prefix> and <counter-suffix> are the
values of the prefix and
suffix descriptors for
the specified counter style.
See braille-css#17.
The string-set property sets the value of a named string, which functions as a variable. The value can be retrieved using the string() function. Since these variables may change on a given page, an optional second value for the string() function allows authors to choose which value on a page is used.
Name: | string-set |
---|---|
Value: | [ <custom-ident> <content-list> ] [, <custom-ident> <content-list> ]* | none |
Initial: | none |
Applies to: | all elements |
Inherited: | no |
Media: | embossed |
Computed value: | specified value |
The string-set property contains one or more pairs, each consisting of a custom identifier followed by a content-list describing how to construct the value of the named string.
<content-list> expands to one or more of the following values, in any order. The generated content is the concatenation of all values in the list.
content-list = [ <string> |
<attr(<identifier>)> | <content()> ]+
Named strings contain unformatted text. XML structure and CSS styling are not preserved. Text transformation and white space processing of strings happens after evaluation of the variable (with the string() function) and not before assignment (with the string-set property). This means that text-transform and white-space properties can have an effect at the place of insertion, but not at the original position in the DOM.
The content values of named strings are assigned at the point when the content box (or first content box fragment) of the element is created, or if the element does not generate any boxes, would have been created if it was a non-empty inline element.
The string() function is used to insert the value of a named string into the document via the content property. This function requires one argument, the name of the named string. Since the value of a named string may change several times on a page an optional second argument indicates which value of the named string should be used.
string() = string( <custom-ident> [ , [ first | start | last |
start-except-last | last-except-start | page-first | page-start | page-last |
page-start-except-last | page-last-except-start | spread-first | spread-start |
spread-last | spread-start-except-last | spread-last-except-start | ] ]? )
The second argument of the string() function is one of the following keywords:
<body> <p foo="⠁"> ⠁⠁⠁ ⠁⠁⠁ ⠁⠁⠁ ⠁⠁⠁ ⠁⠁⠁ </p> <p foo="⠿"> ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ </p> <p foo="⠤"> ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ </p> <p foo="⠸"> ⠸⠸⠸ ⠸⠸⠸ ⠸⠸⠸ ⠸⠸⠸ ⠸⠸⠸ </p> <p foo="⠛"> ⠛⠛⠛ ⠛⠛⠛ ⠛⠛⠛ ⠛⠛⠛ ⠛⠛⠛ ⠛⠛⠛ ⠛⠛⠛ </p> <p foo="⠌"> ⠌⠌⠌ ⠌⠌⠌ ⠌⠌⠌ ⠌⠌⠌ ⠌⠌⠌ </p> </body>
@page { size: 10 6; @top-left { content: string(foo, first); } @top-right { content: string(foo, start); } @bottom-left { content: string(foo, last); } @bottom-right { content: string(foo, last-except-start); } } p { display: block; string-set: foo attr(foo); }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="6" cols="10" rowgap="0" duplex="true"> <section> <page> <row>⠁⠀⠀⠀⠀⠀⠀⠀⠀⠁</row> <row>⠁⠁⠁⠀⠁⠁⠁</row> <row>⠁⠁⠁⠀⠁⠁⠁</row> <row>⠁⠁⠁</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠀⠀⠀⠀⠀⠀⠀⠀⠿</row> </page> <page> <row>⠤⠀⠀⠀⠀⠀⠀⠀⠀⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠀⠀⠀⠀⠀⠀⠀⠀⠤</row> </page> <page> <row>⠸⠀⠀⠀⠀⠀⠀⠀⠀⠤</row> <row>⠤⠤⠤</row> <row>⠸⠸⠸⠀⠸⠸⠸</row> <row>⠸⠸⠸⠀⠸⠸⠸</row> <row>⠸⠸⠸</row> <row>⠸⠀⠀⠀⠀⠀⠀⠀⠀⠸</row> </page> <page> <row>⠛⠀⠀⠀⠀⠀⠀⠀⠀⠛</row> <row>⠛⠛⠛⠀⠛⠛⠛</row> <row>⠛⠛⠛⠀⠛⠛⠛</row> <row>⠛⠛⠛⠀⠛⠛⠛</row> <row>⠛⠛⠛</row> <row>⠛⠀⠀⠀⠀⠀⠀⠀⠀⠀</row> </page> <page> <row>⠌⠀⠀⠀⠀⠀⠀⠀⠀⠌</row> <row>⠌⠌⠌⠀⠌⠌⠌</row> <row>⠌⠌⠌⠀⠌⠌⠌</row> <row>⠌⠌⠌</row> <row/> <row>⠌⠀⠀⠀⠀⠀⠀⠀⠀⠀</row> </page> </section> </volume> </body> </pef>
A leader is a repeating pattern used to visually connect content across horizontal spaces. They are most commonly used in tables of contents, between titles and page numbers. The leader() function, as a value for the content property, is used to create leaders. A <braille-string> describes the repeating pattern for the leader.
leader() = leader( <braille-string> )
See braille-css#34.
The target-counter() function retrieves the value of the named counter at the element referred to by the <url>. The second argument is the name of the counter.
target-counter() = target-counter( <url>, <custom-ident> )
This function differs from the original target-counter() function [CSS3GCPM] in that it doesn't take an optional <counter-style> argument.
The target-counter(), target-string() and target-text() functions only take a fragment URL which points to a location in the current document. The URL may also be provided indirectly using the attr() function [CSS3VAL], in which case ‘url’ will be implied as the type argument if omitted.
Add a target-content() function. See braille-css#6.
The target-string() function retrieves the value of the named string at the element referred to by the <url>. The second argument is the name of the counter.
target-string() = target-string( <url>, <custom-ident> )
The target-text() function retrieves the text value of the element referred to by the <url>.
target-text() = target-text( <url> )
This function differs from the original target-text() function [CSS3GCPM] in that it doesn't take an optional second argument.
Name: | content |
---|---|
Value: | none | <content-list> |
Initial: | none |
Applies to: | ::before, ::after, ::marker and ::alternate pseudo-elements, margin contexts and @begin and @end rules. |
Inherited: | no |
Media: | embossed |
Computed value: | the specified value |
The content property dictates what is rendered inside the pseudo-element or margin area.
<content-list> = [
<string> |
<attr()> |
<string()> |
<counter()> |
<target-text()> |
<target-string()> |
<target-counter()> |
<leader()> |
<flow()>
]+
See braille-css#28.
For producing braille on paper, the content of the document must be split into discrete pages. This process is called pagination. This specification defines properties for controlling the page dimensions, where pages may or must be broken, and for inserting content in page headers and footers.
The page model [CSS3PAGE] specifies how a document is formatted within rectangular areas with a finite width and height, called page boxes, each consisting of a page area and up to 16 page-margin boxes. Braille CSS has a slightly simplified model.
In braille CSS, page boxes consist only of content and margin areas, no borders or padding. Moreover, the top and bottom page margins can only contain up to three page-margin boxes each.
CSS distinguishes between left pages and right pages on all documents, regardless of whether or not they are printed duplex or not. Each left page is followed by a right page and vice versa. Left and right pages can be styled differently with the :left and :right pseudo-classes.
The properties of a page box, such as its dimensions, are determined by properties declared within the page context, using @page rules.
A @page rule consists of the keyword @page, an optional page type selector, an optional page pseudo-class, and a block of declarations and margin at-rules (said to be in the page context). The page type selector matches pages of the named page type generated by the page property. Valid page pseudo-classes are :left, :right, :first and :blank. The :left and :right classes only match left or right pages, respectively. :first matches the first printed page of a volume. :blank matches content-empty pages that appear as the result of forced page breaks.
Declarations in page and margin contexts cascade as explained in the section Cascading in the page context [CSS3PAGE].
Name: | size |
---|---|
Value: | <length>{2} | auto |
Initial: | auto |
Applies to: | page context |
Inherited: | N/A |
Media: | embossed |
Computed value: | the specified value |
The size property specifies the size of the page box's containing block. Values have the following meanings:
The size property is not allowed within @page rules with a :left or :right pseudo-class.
This property differs from the original size property [CSS3PAGE] in that it doesn't specify the orientation of the page box, and that no other values than auto and lengths are allowed.
Note that while in the original specification the size property is meant to match the size of the page sheet, in braille CSS it is meant to match the printable area.
Page-margin boxes are boxes within the page margin that can contain generated content. Page margins can be used to create page headers and footers, which are portions of the page set aside for supplementary information such as the page number or document title. The 16 page-margin boxes are defined and illustrated in [CSS3PAGE].
Only 6 of the 16 page-margin boxes are relevant in braille CSS, namely top-left, top-center, top-right, bottom-left, bottom-center and bottom-right.
Page-margin boxes are created by margin at-rules inside the page context. A margin at-rule consists of an ATKEYWORD that identifies the page-margin box (e.g. @top-left) and a block of declaractions (said to be in the margin context).
This rules differs from the original margin at-rule [CSS3PAGE] in that only the content and white-space properties are allowed in declarations.
A page-margin box is generated if and only if the computed value of its content property is not none and does not consist of collapsible white space only. The height of a page-margin box is determined by the number of line boxes it contains. Soft wrapping is not allowed in page-margin boxes, but forced line breaks are. This means that if white-space is normal, the height is 1, and if white-space is pre-wrap or pre-line, the height is equal to the number of segment breaks plus 1. Text that falls outside of the page-margin box edges (horizontally) is clipped.
The top-left, top-center and top-right boxes, if they are generated, touch the page box's top edge. The offset between the page box's top edge and the page area is determined by the margin-top property, which defaults to 0. Page-margin boxes with a height less than this offset have empty space between them and the page area. Page-margin boxes with a height greater than margin-top extend into the page area, with the text in the page area wrapping around the page-margin boxes.
Analogous rules govern the properties of the bottom page-margin area (with ‘top’ replaced by ‘bottom’ everywhere).
Need to define how text in the page area should wrap around page-margin boxes.
Text in top-left and bottom-left boxes is left-aligned (as if text-align was set to left), text in top-center and bottom-center boxes is centered (as if text-align was set to center) and text in top-right and bottom-right boxes is right-aligned (as if text-align was set to right). Further alignment can be achieved by padding text with preserved spaces.
Name: | page |
---|---|
Value: | auto | <custom-ident> |
Initial: | auto |
Applies to: | block | list-item |
Inherited: | no (see text) |
Media: | embossed |
Computed value: | the specified value |
The page property is used to specify a particular type of page (called a named page) on which an element must be displayed. If necessary, a forced page break is introduced and a new page generated of the specified type. The page can be styled by using the same type name in a page selector.
The page property does not inherit. However, if the page value on an element is auto, then its used value is the value specified on its nearest ancestor with a non-auto value. When specified on the root element, the used value for auto is the empty string.
<body> <div id="a"> <p> ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ </p> </div> <div id="b"> <p> ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ </p> </div> </body>
Setting the size of the page and page margins:
@page { size: 10 7; margin-top: 1; margin-bottom: 2; }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="7" cols="10" rowgap="0" duplex="true"> <section> <page> <row/> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> </page> <page> <row/> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> </page> <page> <row/> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> </page> </section> </volume> </body> </pef>
Setting different page sizes for different sections:
@page a { size: 8 4; } @page b { size: 4 8; } #a { page: a; } #b { page: b; }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="4" cols="8" rowgap="0" duplex="true"> <section> <page> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> </page> <page> <row>⠤⠤⠤⠀⠤⠤⠤</row> </page> </section> <section rows="8" cols="4"> <page> <row>⠿⠿⠿</row> <row>⠿⠿⠿</row> <row>⠿⠿⠿</row> <row>⠿⠿⠿</row> <row>⠿⠿⠿</row> <row>⠿⠿⠿</row> <row>⠿⠿⠿</row> <row>⠿⠿⠿</row> </page> <page> <row>⠿⠿⠿</row> <row>⠿⠿⠿</row> </page> </section> </volume> </body> </pef>
Generating content in the page margin:
@page { size: 10 6; margin-top: 1; @top-right { content: '⠒⠒⠒⠒'; } } @page b { margin-top: 2; } #b { page: b; }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="6" cols="10" rowgap="0" duplex="true"> <section> <page> <row>⠀⠀⠀⠀⠀⠀⠒⠒⠒⠒</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> </page> </section> <section> <page> <row>⠀⠀⠀⠀⠀⠀⠒⠒⠒⠒</row> <row/> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> </page> <page> <row>⠀⠀⠀⠀⠀⠀⠒⠒⠒⠒</row> <row/> <row>⠿⠿⠿⠀⠿⠿⠿</row> </page> </section> </volume> </body> </pef>
Multiline content in the page margin:
@page { size: 10 6; margin-top: 2; @top-right { content: '⠒⠒⠒\A⠸⠸'; white-space: pre-line; } }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="6" cols="10" rowgap="0" duplex="true"> <section> <page> <row>⠀⠀⠀⠀⠀⠀⠀⠒⠒⠒</row> <row>⠀⠀⠀⠀⠀⠀⠀⠀⠸⠸</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> </page> <page> <row>⠀⠀⠀⠀⠀⠀⠀⠒⠒⠒</row> <row>⠀⠀⠀⠀⠀⠀⠀⠀⠸⠸</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> </page> <page> <row>⠀⠀⠀⠀⠀⠀⠀⠒⠒⠒</row> <row>⠀⠀⠀⠀⠀⠀⠀⠀⠸⠸</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> </page> </section> </volume> </body> </pef>
Making text in the page area wrap around page margin boxes:
@page { size: 10 6; @top-right { content: '⠒⠒⠒⠒'; } }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="6" cols="10" rowgap="0" duplex="true"> <section> <page> <row>⠤⠤⠤⠀⠀⠀⠒⠒⠒⠒</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠿⠿⠿</row> </page> <page> <row>⠿⠿⠿⠀⠀⠀⠒⠒⠒⠒</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> </page> </section> </volume> </body> </pef>
Setting a different page layout for left- and right-hand pages:
@page { size: 10 6; } @page:left { @bottom-center { content: '⠂⠂⠂⠂⠂⠂' } }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="6" cols="10" rowgap="0" duplex="true"> <section> <page> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> </page> <page> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row/> <row>⠀⠀⠂⠂⠂⠂⠂⠂⠀⠀</row> </page> </section> </volume> </body> </pef>
In order to avoid awkward breaks, the layout engine must be able to shift around content that would otherwise fall across the page break. The generic term for breaking content across containers such as page boxes is fragmentation, and the containers are called fragmentainers. [CSS3BREAK] defines how and where a sequence of boxes can be fragmented, including across page breaks. It defines properties for indicating where pages may or must be broken, and on what page (left or right) the subsequent content resumes.
A page break opportunity between two boxes is under the influence of the containing block's page-break-inside property, the page-break-after property of the preceding element, and the page-break-before property of the following element. A page break opportunity between line boxes is under the influence of the containing block's widows and orphans properties. A break can be allowed, forced, or discouraged depending on the values of these properties. See the section Rules for Page Breaking below for the exact rules on how these properties affect page breaking.
Name: | page-break-before |
---|---|
Value: | auto | always | avoid | left | right |
Initial: | auto |
Applies to: | block | list-item |
Inherited: | no |
Media: | embossed |
Computed value: | specified value |
avoid | left is currently not supported in the Liblouis based implementation.
Name: | page-break-after |
---|---|
Value: | auto | always | avoid | left | right |
Initial: | auto |
Applies to: | block | list-item |
Inherited: | no |
Media: | embossed |
Computed value: | specified value |
left | right is currently not supported in the Liblouis based implementation.
Name: | page-break-inside |
---|---|
Value: | auto | avoid |
Initial: | auto |
Applies to: | block | list-item |
Inherited: | no |
Media: | embossed |
Computed value: | specified value |
These properties control page break behaviour before, after and within the element's principle box. Values have the following meanings:
Since breaks are allowed between siblings, but not between a box and its container (see Rules for Page Breaking), a page-break-before value on a first-child box is propagated to its container. Likewise a page-break-after value on a last-child box is propagated to its container.
Name: | orphans |
---|---|
Value: | <integer> |
Initial: | 0 |
Applies to: | block | list-item |
Inherited: | no |
Media: | embossed |
Computed value: | specified value |
Name: | widows |
---|---|
Value: | <integer> |
Initial: | 0 |
Applies to: | block | list-item |
Inherited: | no |
Media: | embossed |
Computed value: | specified value |
The orphans property specifies the minimum number of line boxes in a block container that must be left in a fragment before a page break. The widows property specifies the minimum number of line boxes of a block container that must be left in a fragment after a page break. Only positive integers are allowed. If a block contains fewer lines than the value of widows or orphans, the rule simply becomes that all lines in the block must be kept together.
widows is currently not supported in the Liblouis based implementation. See pipeline-mod-braille#13.
<body> <p id="1"> ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ ⠤⠤⠤ </p> <p id="2"> ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ </p> <p id="3"> ⠛⠛⠛ </p> <p id="4"> ⠸⠸⠸ ⠸⠸⠸ ⠸⠸⠸ ⠸⠸⠸ ⠸⠸⠸ </p> </body>
Forcing page breaks:
@page { size: 10 5; } p { display: block; } p#1 { page-break-before: always; } p#2 { page-break-after: always; } p#3 { page-break-after: right; }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="5" cols="10" rowgap="0" duplex="true"> <section> <page> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> </page> <page> <row>⠿⠿⠿</row> </page> <page> <row>⠛⠛⠛</row> </page> </section> <section> <page> <row>⠸⠸⠸⠀⠸⠸⠸</row> <row>⠸⠸⠸⠀⠸⠸⠸</row> <row>⠸⠸⠸</row> </page> </section> </volume> </body> </pef>
Forbidding page breaks:
@page { size: 10 5; } p { display: block; } p#2 { page-break-inside: avoid;} p#3 { margin-top: 1; } p#4 { page-break-before: avoid; }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="5" cols="10" rowgap="0" duplex="true"> <section> <page> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤</row> </page> <page> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿</row> </page> <page> <row/> <row>⠛⠛⠛</row> <row>⠸⠸⠸⠀⠸⠸⠸</row> <row>⠸⠸⠸⠀⠸⠸⠸</row> <row>⠸⠸⠸</row> </page> </section> </volume> </body> </pef>
@page { size: 10 5; } p { display: block; } p#2 { widows: 2; } p#3 { margin-top: 1; } p#4 { orphans: 2; }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="5" cols="10" rowgap="0" duplex="true"> <section> <page> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤⠀⠤⠤⠤</row> <row>⠤⠤⠤</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> </page> <page> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿</row> <row/> <row>⠛⠛⠛</row> </page> <page> <row>⠸⠸⠸⠀⠸⠸⠸</row> <row>⠸⠸⠸⠀⠸⠸⠸</row> <row>⠸⠸⠸</row> </page> </section> </volume> </body> </pef>
A flow may be broken across pages at a number of possible break points. In the case of forced breaks, the UA is required to break the flow at that point. In the case of unforced breaks the UA has to choose among the possible breaks that are allowed. Page breaks can occur between sibling block-level boxes (class A break point), or between line boxes inside a block container box (class B break point).
A forced page break occurs at a class A break point if, among the page-break-after and page-break-before properties of all the elements generating boxes that meet at this margin, there is at least one with a forced break value (always, left, or right).
A forced break takes precedence over any break restrictions acting at that point. When multiple forced break values apply to a single break point, they combine such that all types of break are honored. When left, and right are combined, the value specified on the latest element in the flow wins.
A forced page break (type right) also occurs at a class A break point if the last line box above this margin and the first one below it do not have the same value for page.
Unforced page breaks are inserted automatically in order to prevent content from overflowing the page. The following rules control whether unforced breaking at a break point opportunity is allowed:
If the above doesn't provide enough break points to keep content from overflowing the page, then rules 1, 2 and 4 are dropped in order to find additional break points. If that still does not lead to sufficient break points, rule 3 is dropped as well.
Note that these rules only define where breaking is allowed, and while this specification requires that content does not overflow the page, it does not impose any particular algorithm for determining the exact break points.
Exactly how content breaks across pages is described in the section Box Model for Breaking [CSS3BREAK]. In short:
When producing braille on paper, a document may need to be split into several so called volumes due to size limits on paper books. Volumes are the physical units (books) that make up the complete work. This specification defines properties for controlling the size of volumes, where volumes may or must be broken, and for inserting content at the beginning or end of specific volumes.
The properties of a volume, such as its dimensions, are determined by CSS properties declared within the volume context, using @volume rules.
A @volume rule consists of the keyword @volume, an optional volume selector, and a block of declarations and at-rules (said to be in the volume context). A volume selector is made of either a volume type selector, a volume pseudo-class, or a type selector followed by a pseudo-class. A volume selector matches a given volume if and only if all of its components match the volume. A volume type selector is a CSS identifier and matches volumes of the named volume type generated by the volume property. The volume pseudo-classes :first, :last and :nth(<n>) match the first, last and nth volume. If the pseudo-class follows a volume type selector, it matches the first, last or nth volume in a sequence of volumes of the specified type.
Name: | min-length |
---|---|
Value: | <integer> | auto |
Initial: | auto |
Applies to: | volume context |
Inherited: | N/A |
Media: | embossed |
Computed value: | the specified value |
Name: | max-length |
---|---|
Value: | <integer> | auto |
Initial: | auto |
Applies to: | volume context |
Inherited: | N/A |
Media: | embossed |
Computed value: | the specified value |
The min-length and max-length properties specify the minimum and maximum allowed lengths of a volume in terms of pages. Negative lengths are illegal. The value auto means that no lower/upper constraint is set on the volume size. When max-length is auto and there are no forced volume breaks, the document must consist of a single volume.
Volume areas are boxes at the beginning and end of volumes that can contain generated content. They are created by @begin and @end rules inside the volume context.
A @begin rule consists of the keyword @begin followed by a block of declarations. An @end rule consists of the keyword @end and a block of declarations.
A volume area box is generated if and only if the computed value of its content property is not none.
Name: | volume |
---|---|
Value: | auto | <custom-ident> |
Initial: | auto |
Applies to: | block | list-item |
Inherited: | no (see text) |
Media: | embossed |
Computed value: | the specified value |
The volume property is used to specify a particular type of volume (called a named volume) on which an element must be displayed. If necessary, a forced volume break is introduced.
The volume property does not inherit. However, if the volume value on an element is auto, then its used value is the value specified on its nearest ancestor with a non-auto value. When specified on the root element, the used value for auto is the empty string.
See braille-css#3.
In order to avoid awkward volume breaks (for instance, in the middle of a sentence, or after the first paragraph of a chapter), volumes sometimes need to be broken before the upper page bound has been reached. This specification defines properties for indicating where volumes may or must be broken. Breaks at certain places may be forced, encouraged or discouraged.
A volume break opportunity between two boxes is under the influence of the containing block's volume-break-inside property, the volume-break-after property of the preceding element, and the volume-break-before property of the following element. See the section Rules for Volume Breaking below for the exact rules on how these properties affect volume breaking.
Name: | volume-break-before |
---|---|
Value: | auto | always | avoid | prefer |
Initial: | auto |
Applies to: | block | list-item |
Inherited: | no |
Media: | embossed |
Computed value: | specified value |
Name: | volume-break-after |
---|---|
Value: | auto | always | avoid | prefer |
Initial: | auto |
Applies to: | block | list-item |
Inherited: | no |
Media: | embossed |
Computed value: | specified value |
Name: | volume-break-inside |
---|---|
Value: | auto | avoid |
Initial: | auto |
Applies to: | block | list-item |
Inherited: | no |
Media: | embossed |
Computed value: | specified value |
These properties control volume break behaviour before, after and within the element's principle box. Values have the following meanings:
Since breaks are allowed between siblings, but not between a box and its container (see Rules for Volume Breaking), a volume-break-before value on a first-child box is propagated to its container. Likewise a volume-break-after value on a last-child box is propagated to its container.
A flow may be broken across volumes at a number of possible break points. In the case of forced breaks, the UA is required to break the flow at that point. In the case of unforced breaks the UA has to choose among the possible breaks that are allowed. Volume breaks can occur between sibling block-level boxes (class A break point), or between line boxes inside a block container box (class B break point).
A forced volume break occurs at a class A break point if, among the volume-break-after and volume-break-before properties of all the elements generating boxes that meet at this margin, there is at least one with a forced break value (always). A forced break takes precedence over any break restrictions acting at that point.
A forced volume break also occurs at a class A break point if the last line box above this margin and the first one below it do not have the same value for volume.
Unforced volume breaks are inserted automatically in order to meet the max-length constraints. The following rules control whether unforced breaking at a break point opportunity is allowed:
If the above doesn't provide enough break points, the UA may break anywhere in order to avoid violating the max-length constraints.
In the end, all min-length constraints must be met as well, unless a volume being to short is the result of forced volume breaks.
Note that these rules only define where breaking is allowed. The specification does not impose any particular algorithm for determining the exact break points.
It is sometimes useful to take elements out of their normal flow and move or copy them into other containers. Examples include footnotes, volume endnotes, and repeated content at the beginning of volumes. This section describes a generic mechanism for moving content, called “named flows”. CSS is not a transformation language; the motivation for supporting named flows is presentational rather than structural.
The approach taken in braille CSS is inspired by a number of CSS concepts and features described elsewhere:
A named flow is the ordered sequence of content associated with a flow with a given identifier. Content is placed into a named flow with the flow property, and taken out using the flow() value of the content property. The same element can participate in more than one flow (including the normal flow), and a named flow can have multiple sources and multiple destinations. This makes it possible to not only move but also copy and repeat content.
Name: | flow |
---|---|
Value: | normal | <custom-ident> |
Initial: | normal |
Applies to: | all elements and ::alternate and ::duplicate pseudo-elements |
Inherited: | no |
Media: | embossed |
Computed value: | the specified value |
The flow property causes an element to participate in the specified flow. The value must be one of the following:
The flow property does not affect the DOM position of an element or its contents, and it does not affect the CSS cascade and inheritance.
The visual formatting model however uses the relationships between content in the named flow as input, rather than the contents' original position in the DOM. Elements channelled into a named flow become siblings. A box establishes a containing block for the content it consumes using the flow() function. Elements in a named flow are ordered according to their document order.
Content can be generated or duplicated using the ::alternate and ::duplicate pseudo-elements. The content of an ::alternate pseudo-element is determined by its content property. The content of a ::duplicate pseudo-element is copied from the element in the document tree
to which it is associated. The ::alternate(<n>)
and
::duplicate(<n>)
notations can be used to create several ::alternate or ::duplicate pseudo-elements for
one given element.
The flow property dictates in which flow a pseudo-element participates. A value normal causes the pseudo-element to be included where the element in the document tree to which it is associated would be positioned. It is not allowed that several pseudo-elements associated to the same element participate in the same flow (normal or named flow), nor that they participate in the same flow as the element they are associated to.
Unlike other pseudo-elements, these pseudo-elements inherit from the parent of the element to which it they are associated, not from that element itself.
The flow() function is used to consume named flows, via the content property. The function requires one argument, the name of the flow. Elements in the named flow are rendered as children of the block container on which the content property is specified. In the default case, all elements in a named flow are consumed as many times as there are flow() calls. This behaviour can be overridden with an optional second argument that specifies which elements should be included. Elements in a flow are duplicated as many times as needed in order to meet the demand.
flow() = flow( <custom-ident> [, [ document | volume ] ]?
)
The second argument dictates the search direction and range and is one of the following keywords:
Books typically have sections that can be referred to as generated lists. They are generated from the main content, and have the nature of lists. Examples include a table of contents, an index, a glossary, a list of figures, a list of tables and an endnote section.
See braille-css#10.
See braille-css#3.
See braille-css#5.
See braille-css#4.
See braille-css#14.
<body> <span class="pagenum">⠼⠁</span> <p> ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ </p> <span class="pagenum">⠼⠃</span> <p> ⠭⠭⠭ ⠭⠭⠭ ⠭⠭⠭ ⠭⠭⠭ ⠭⠭⠭ <span class="pagenum">⠼⠉</span> ⠭⠭⠭ ⠭⠭⠭ ⠭⠭⠭ ⠭⠭⠭ ⠭⠭⠭ </p> <p> ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ ⠿⠿⠿ </p> </body>
Using the string-set property and the string() function, print page numbers can be rendered in the page footer:
@page { size: 12 6; margin-bottom: 1; @bottom-right { content: string(print-page); } } p { display: block; text-indent: 2; } .pagenum { display: none; string-set: print-page content(); }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="6" cols="12" rowgap="0" duplex="true"> <section> <page> <row>⠀⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠀⠀⠭⠭⠭⠀⠭⠭⠭</row> <row>⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠼⠁</row> </page> <page> <row>⠭⠭⠭⠀⠭⠭⠭⠀⠭⠭⠭</row> <row>⠭⠭⠭⠀⠭⠭⠭⠀⠭⠭⠭</row> <row>⠭⠭⠭⠀⠭⠭⠭</row> <row>⠀⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠼⠉</row> </page> <page> <row>⠿⠿⠿⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row/> <row/> <row/> <row>⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠼⠉</row> </page> </section> </volume> </body> </pef>
The range of print pages covered on a braille page can be rendered in the page footer:
@page { size: 12 6; margin-bottom: 1; @bottom-right { content: string(print-page, start) string(dash-print-page, last-except-start); } } p { display: block; text-indent: 2; } .pagenum { display: none; string-set: print-page content(), dash-print-page '⠒' content(); }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="6" cols="12" rowgap="0" duplex="true"> <section> <page> <row>⠀⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠀⠀⠭⠭⠭⠀⠭⠭⠭</row> <row>⠀⠀⠀⠀⠀⠀⠀⠼⠁⠒⠼⠃</row> </page> <page> <row>⠭⠭⠭⠀⠭⠭⠭⠀⠭⠭⠭</row> <row>⠭⠭⠭⠀⠭⠭⠭⠀⠭⠭⠭</row> <row>⠭⠭⠭⠀⠭⠭⠭</row> <row>⠀⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠀⠀⠀⠀⠀⠀⠀⠼⠃⠒⠼⠉</row> </page> <page> <row>⠿⠿⠿⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row/> <row/> <row/> <row>⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠼⠉</row> </page> </section> </volume> </body> </pef>
The range of print pages covered on the current page spread can be rendered in the footer of the right-hand page:
@page { size: 12 6; margin-bottom: 1; } @page:right { @bottom-right { content: string(print-page, spread-start) string(dash-print-page, spread-last-except-start); } } p { display: block; text-indent: 2; } .pagenum { display: none; string-set: print-page content(), dash-print-page '⠒' content(); }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="6" cols="12" rowgap="0" duplex="true"> <section> <page> <row>⠀⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠀⠀⠭⠭⠭⠀⠭⠭⠭</row> <row>⠀⠀⠀⠀⠀⠀⠀⠼⠁⠒⠼⠃</row> </page> <page> <row>⠭⠭⠭⠀⠭⠭⠭⠀⠭⠭⠭</row> <row>⠭⠭⠭⠀⠭⠭⠭⠀⠭⠭⠭</row> <row>⠭⠭⠭⠀⠭⠭⠭</row> <row>⠀⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿⠀⠿⠿⠿</row> <row/> </page> <page> <row>⠿⠿⠿⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row/> <row/> <row/> <row>⠀⠀⠀⠀⠀⠀⠀⠼⠃⠒⠼⠉</row> </page> </section> </volume> </body> </pef>
Print page breaks can be indicated with full lines across the width of the page, followed by the page number of the next print page:
@page { size: 12 6; } p { display: block; text-indent: 2; } .pagenum { display: block; text-indent: 0; } .pagenum::before { content: leader('⠒') '⠀'; }
<pef xmlns="http://www.daisy.org/ns/2008/pef" version="2008-1"> <head xmlns:dc="http://purl.org/dc/elements/1.1/"> <meta> <dc:format>application/x-pef+xml</dc:format> </meta> </head> <body> <volume rows="6" cols="12" rowgap="0" duplex="true"> <section> <page> <row>⠒⠒⠒⠒⠒⠒⠒⠒⠒⠀⠼⠁</row> <row>⠀⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> <row>⠒⠒⠒⠒⠒⠒⠒⠒⠒⠀⠼⠃</row> </page> <page> <row>⠀⠀⠭⠭⠭⠀⠭⠭⠭</row> <row>⠭⠭⠭⠀⠭⠭⠭⠀⠭⠭⠭</row> <row>⠒⠒⠒⠒⠒⠒⠒⠒⠒⠀⠼⠉</row> <row>⠭⠭⠭⠀⠭⠭⠭⠀⠭⠭⠭</row> <row>⠭⠭⠭⠀⠭⠭⠭</row> <row>⠀⠀⠿⠿⠿⠀⠿⠿⠿</row> </page> <page> <row>⠿⠿⠿⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿⠀⠿⠿⠿</row> <row>⠿⠿⠿⠀⠿⠿⠿</row> </page> </section> </volume> </body> </pef>