Positioning your content

Scryber has an intelligent layout engine. By default eveything will be laid out as per the flowing layout of the document Pages and columns. Each component, be it block level or inline will have a position next to its siblings and move and following content along in the document. If the content comes to the end of the page and cannot be fitted, then if allowed, it will be moved to the next page.

Inline Positioning

Inline components such as text and spans will continue on the current line, and if they do not fit all the contnet, then they will flow onto the next line (or column or page). If the content moves, so the inline content will move with the container.

Carriager returns within the content of the xml file are ignored by default, as per html (see Scryber.Components.PDFPreformatted if you don’t want them to be.).

Examples of inline components are spans, labels, text literals, page numbers,

<?xml version="1.0" encoding="utf-8" ?>
<pdf:Document xmlns:pdf="http://www.scryber.co.uk/schemas/core/release/v1/Scryber.Components.xsd"
                xmlns:styles="http://www.scryber.co.uk/schemas/core/release/v1/Scryber.Styles.xsd" >

<Pages>

    <pdf:Page styles:margins="20pt" styles:font-size="20pt">
        <Content>
            This is the content of the page,
            <pdf:Span styles:fill-color="maroon" >and this will continue on the current line until it reaches the end
            and then flow onto the next line.</pdf:Span>
            This with then flow after the line.<pdf:Br/>
            A line break forces a new line in the content but flow in the page (#<pdf:PageNumber />) will continue.
            <pdf:Span styles:fill-color="maroon" styles:font-size="30pt" >It also supports the use of multiple font sizes</pdf:Span> in multiple lines,
            adjusting the line height as needed.
        </Content>
    </pdf:Page>
</Pages>

</pdf:Document>

Generating this document will create the following output (see MVC Controller - Getting Started or Console or GUI - Getting Started to understand how to do this).

_images/documentpositioninginline.png

For more information on laying out textual content see documenttextlayout

Block Positioning

A block starts on a new line in the content of the page. Children will be laid out within the block (unless absolutely positioned), and content after the block will also begin a new line.

Examples of blocks are Div’s, Paragraphs, Tables, BlockQuotes, Headings, Images, and Shapes.

<?xml version="1.0" encoding="utf-8" ?>
<pdf:Document xmlns:pdf="http://www.scryber.co.uk/schemas/core/release/v1/Scryber.Components.xsd"
                xmlns:styles="http://www.scryber.co.uk/schemas/core/release/v1/Scryber.Styles.xsd" >

    <Pages>

        <pdf:Page styles:margins="20pt" styles:font-size="20pt">
            <Content>
                This is the content of the page,

                <pdf:Div styles:fill-color="maroon" >This will always be on a new on the line, and it's content will then continue inline until it reaches the end
                and then flow onto the next line.</pdf:Div>

                After a block, this with then continue with the previous flow on the next line.<pdf:Br/>
                A line break forces a new line in the content but flow in the page (#<pdf:PageNumber />) will continue.

                <pdf:Div styles:fill-color="#666600" >
                Blocks also supports the use of inline and block content within them
                <pdf:Span styles:fill-color="#006666"  styles:font-size="30pt">in multiple lines, adjusting the line height as needed.</pdf:Span>
                <pdf:Div >As a separate block within the container</pdf:Div>
                </pdf:Div>

            </Content>
        </pdf:Page>
    </Pages>

</pdf:Document>
_images/documentpositioningblocks.png

Blocks also support the use of backgrounds, borders, margins and padding. They also support Flowing pages and columns

<?xml version="1.0" encoding="utf-8" ?>
<pdf:Document xmlns:pdf="http://www.scryber.co.uk/schemas/core/release/v1/Scryber.Components.xsd"
              xmlns:styles="http://www.scryber.co.uk/schemas/core/release/v1/Scryber.Styles.xsd" >

<Pages>

    <pdf:Page styles:margins="20pt" styles:font-size="20pt">
    <Content>
        This is the content of the page,

        <pdf:Div styles:fill-color="maroon" styles:margins="20pt 10pt 10pt 10pt" >This will always
            be on a new on the line, and it's content will then continue inline
            until it reaches the end and then flow onto the next line.
        </pdf:Div>

        After a block, this with then continue with the previous flow on the next line.<pdf:Br/>
        A line break forces a new line in the content but flow in the page (#<pdf:PageNumber />) will continue.

        <pdf:Div styles:fill-color="#666600" styles:bg-color="#BBBB00" styles:padding="10pt"
                 styles:margins="10pt" styles:column-count="2">
            Blocks also supports the use of inline and block content within them

            <pdf:Span styles:fill-color="#006666"  styles:font-size="30pt">in multiple lines,
                adjusting the line height as needed.</pdf:Span>

            <!-- breaking onto a new column-->
            <pdf:ColumnBreak />

            <pdf:Div styles:fill-color="black" styles:bg-color="white" >As a separate block within the container</pdf:Div>
            And coming after the child block.
        </pdf:Div>

    </Content>
    </pdf:Page>
</Pages>

</pdf:Document>
_images/documentpositioningblocks2.png

Changing the position-mode

It is posible to change the default position mode for many components on the page. A span can be a block and a div can be a span. Images and shapes (see document_images and Drawing paths and shapes - td) also support the use of the the position mode.

<?xml version="1.0" encoding="utf-8" ?>
<pdf:Document xmlns:pdf="http://www.scryber.co.uk/schemas/core/release/v1/Scryber.Components.xsd"
              xmlns:styles="http://www.scryber.co.uk/schemas/core/release/v1/Scryber.Styles.xsd" >

<Pages>

    <pdf:Page styles:margins="20pt" styles:font-size="20pt">
        <Content>
            <pdf:Div styles:border-color="black" styles:border-width="1pt" >
                The content of this div is all as a block (by default)

                <pdf:Div styles:fill-color="maroon" >This div is positioned as a block.</pdf:Div>

                <!-- Images are by detault displayed as blocks -->
                <pdf:Image styles:width="60pt" src="../../Content/Images/group.png" />

                After the content.
            </pdf:Div>

            <pdf:Div styles:border-color="black" styles:border-width="1pt" >
                The content of this div is set explicity to inline.

                <pdf:Div styles:position-mode="Inline" styles:fill-color="maroon">This div is positioned as a block.</pdf:Div>

                <!-- Image is also set to inline and will increase the line height automatically -->
                <pdf:Image styles:position-mode="Inline" styles:width="60pt"  src="../../Content/Images/group.png" />

                After the content.
            </pdf:Div>


        </Content>
    </pdf:Page>
</Pages>

</pdf:Document>
_images/documentpositioningblocks3.png

The full-width attribute

The attribute full-width makes any block component automatically fill the available width of the region. Even if the inner content does not need it. It’s effectivly set as 100% width.

If it’s set to false, the block will be as wide as needed (without going beyond the boundaries of it’s own containing region). This applies to the page, or a column containing the block.

By default Div’s and Paragraphs are set to full width. BlockQuotes, Tables and Lists are not.

<?xml version="1.0" encoding="utf-8" ?>
<pdf:Document xmlns:pdf="http://www.scryber.co.uk/schemas/core/release/v1/Scryber.Components.xsd"
                xmlns:styles="http://www.scryber.co.uk/schemas/core/release/v1/Scryber.Styles.xsd" >

<Styles>
    <!-- Using a style to repeat the border is easier -->
    <styles:Style applied-class="bordered" >
        <styles:Border color="black" style="Solid" width="1pt"/>
        <styles:Padding all="5pt"/>
    </styles:Style>
</Styles>
<Pages>

    <pdf:Page styles:margins="20pt" styles:font-size="20pt">
    <Content>
        <pdf:Div styles:class="bordered" >
            This div is full width<pdf:Br/>
            And will extend beyond the content.<pdf:Br/>
            To the width of its container.
        </pdf:Div>
        <pdf:Br/>
        <pdf:Div styles:class="bordered" styles:full-width="false" >
            This div is NOT full width<pdf:Br/>
            And will only size to the content.<pdf:Br/>
        </pdf:Div>
        <pdf:Br/>
        <pdf:Div styles:class="bordered" styles:full-width="false" >
            This div is NOT full width,
            but will  size to the content available in the container,
            and then flow to the next line.
        </pdf:Div>
        <pdf:Br/>
        <!-- Tables are not by default full width-->
        <pdf:Table>
            <pdf:Row>
                <pdf:Cell styles:class="bordered">First</pdf:Cell>
                <pdf:Cell styles:class="bordered">Second</pdf:Cell>
                <pdf:Cell styles:class="bordered">Third</pdf:Cell>
            </pdf:Row>
            <pdf:Row>
                <pdf:Cell styles:class="bordered">Fourth</pdf:Cell>
                <pdf:Cell styles:class="bordered">Fifth</pdf:Cell>
                <pdf:Cell styles:class="bordered">Sixth</pdf:Cell>
            </pdf:Row>
        </pdf:Table>
        <pdf:Br/>
        <!-- But can be set to full width explicitly or in styles -->
        <pdf:Table styles:full-width="true">
            <pdf:Row>
                <pdf:Cell styles:class="bordered">First</pdf:Cell>
                <pdf:Cell styles:class="bordered">Second</pdf:Cell>
                <pdf:Cell styles:class="bordered">Third</pdf:Cell>
            </pdf:Row>
            <pdf:Row>
                <pdf:Cell styles:class="bordered">Fourth</pdf:Cell>
                <pdf:Cell styles:class="bordered">Fifth</pdf:Cell>
                <pdf:Cell styles:class="bordered">Sixth</pdf:Cell>
            </pdf:Row>
        </pdf:Table>
    </Content>
    </pdf:Page>
</Pages>

</pdf:Document>
_images/documentpositioningfullwidth.png

For more on styles see Styles in your template

Flowing around components

At the moment scryber does not support flowing content around other components. It is something we are looking at supporting. If you want to help, please get in touch.

Relative Positioning

When you set the position-mode to Relative, it declares the position of that component relative to the block parent. The component will no longer be in the flow of any inline content, nor alter the layout of the following components.

<?xml version="1.0" encoding="utf-8" ?>
<pdf:Document xmlns:pdf="http://www.scryber.co.uk/schemas/core/release/v1/Scryber.Components.xsd"
                xmlns:styles="http://www.scryber.co.uk/schemas/core/release/v1/Scryber.Styles.xsd" >
<Styles>
    <styles:Style applied-class="bordered">
    <styles:Border color="black" style="Solid" width="1pt"/>
    <styles:Padding all="5pt"/>
    <styles:Background color="#AAAAAA" />
    <styles:Margins top="5pt"/>
    </styles:Style>
</Styles>
<Pages>

    <pdf:Page styles:margins="20pt" styles:font-size="20pt">
    <Content>
        This is the content of the page,

        <pdf:Div styles:class="bordered" >This is the content above the block.</pdf:Div>

        <pdf:Div styles:class="bordered" >This is the flowing content within the block that will span over multiple lines
            <pdf:Span styles:position-mode="Relative" styles:bg-color="aqua" >This is relative</pdf:Span>
            with the content within it.
        </pdf:Div>

        <pdf:Div styles:class="bordered">
        After a block, this will then continue with the previous flow of content.
        </pdf:Div>

    </Content>
    </pdf:Page>
</Pages>

</pdf:Document>
_images/documentpositioningrelative.png

By default the position will be 0,0 (top, left), but using the x and y attributes it can be altered. The parent block will grow to accomodate the content including any of it’s relatively positioned content. And push any content after the block down.

<?xml version="1.0" encoding="utf-8" ?>
<pdf:Document xmlns:pdf="http://www.scryber.co.uk/schemas/core/release/v1/Scryber.Components.xsd"
                xmlns:styles="http://www.scryber.co.uk/schemas/core/release/v1/Scryber.Styles.xsd" >
<Styles>
    <styles:Style applied-class="bordered">
    <styles:Border color="black" style="Solid" width="1pt"/>
    <styles:Padding all="5pt"/>
    <styles:Background color="#AAAAAA"/>
    <styles:Margins top="5pt"/>
    </styles:Style>
</Styles>
<Pages>

    <pdf:Page styles:margins="20pt" styles:font-size="20pt">
    <Content>
        This is the content of the page,

        <pdf:Div styles:class="bordered" >This is the content above the block.</pdf:Div>

        <pdf:Div styles:class="bordered" >This is the flowing content within the block that will span over multiple lines
            <pdf:Span styles:position-mode="Relative" styles:bg-color="aqua" styles:x="300pt" styles:y="60pt" >This is relative</pdf:Span>
            with the content within it.
        </pdf:Div>

        <pdf:Div styles:class="bordered">
        After a block, this will then continue with the previous flow of content.
        </pdf:Div>

    </Content>
    </pdf:Page>
</Pages>

</pdf:Document>
_images/documentpositioningrelative2.png

Absolute Positioning

Changing the positioning mode to Absolute makes the positioning relative to the current page being rendered. The component will no longer be in the flow of any content, nor alter the layout of following components.

The parent block will NOT grow to accomodate the content. The content within the absolutely positioned component will be flowed within the available width and height of the page, but if a size is specified, then this will be honoured over and above the page size.

<?xml version="1.0" encoding="utf-8" ?>
<pdf:Document xmlns:pdf="http://www.scryber.co.uk/schemas/core/release/v1/Scryber.Components.xsd"
                xmlns:styles="http://www.scryber.co.uk/schemas/core/release/v1/Scryber.Styles.xsd" >
<Styles>
    <styles:Style applied-class="bordered">
    <styles:Border color="black" style="Solid" width="1pt"/>
    <styles:Padding all="5pt"/>
    <styles:Background color="#AAAAAA" />
    <styles:Margins top="5pt"/>
    </styles:Style>
</Styles>
<Pages>

    <pdf:Page styles:margins="20pt" styles:font-size="20pt">
    <Content>
        This is the content of the page

        <pdf:Div styles:class="bordered" >This is the content above the block.</pdf:Div>

        <pdf:Div styles:class="bordered" >This is the flowing content within the block that will span over multiple lines
            <!-- Absolutely positioned content -->
            <pdf:Span styles:position-mode="Absolute" styles:bg-color="aqua" styles:x="300pt" styles:y="60pt" >This is absolute</pdf:Span>
            with the content within it.
        </pdf:Div>

        <pdf:Div styles:class="bordered">
            After a block, this will then continue with the previous flow of content.
        </pdf:Div>

        <!-- Absolute postitioning can be applied to any component, and size can be specified. -->
        <pdf:Image styles:position-mode="Absolute" src="../../Content/Images/group.png" styles:fill-opacity="0.7"
                styles:x="500pt" styles:y="150pt" styles:width="150pt" styles:height="150pt" />
    </Content>
    </pdf:Page>
</Pages>

</pdf:Document>
_images/documentpositioningabsolute.png

Numeric Positioning

All content positioning is from the top left corner of the page or parent. This is a natural positioning mechanism for most cultures and developers. (unlike PDF, which is bottom left to top right).

Units of position can either be specified in

  • points (1/72 of an inch) e.g 36pt,
  • inches e.g. 0.5in or
  • millimeters e.g. 12.7mm

If no units are specified then the default is points. See Document drawing units and measures - td for more information.

Rendering Order

All relative or absolutely positioned content will be rendered to the output in the order it appears in the document. If a block is relatively positioned, it will overlay any content that preceded it, but anything coming after will be over the top.

<?xml version="1.0" encoding="utf-8" ?>
<pdf:Document xmlns:pdf="http://www.scryber.co.uk/schemas/core/release/v1/Scryber.Components.xsd"
                xmlns:styles="http://www.scryber.co.uk/schemas/core/release/v1/Scryber.Styles.xsd" >
<Styles>
    <styles:Style applied-class="bordered">
    <styles:Border color="black" style="Solid" width="1pt"/>
    <styles:Padding all="5pt"/>
    <styles:Background color="#AAAAAA" opacity="0.2"/>
    <styles:Margins top="5pt"/>
    </styles:Style>
</Styles>
<Pages>

    <pdf:Page styles:margins="20pt" styles:font-size="20pt">
    <Content>
        This is the content of the page,

        <pdf:Div styles:class="bordered" >This is the flowing content within the block that
            will span over multiple lines
            <pdf:Span styles:position-mode="Relative" styles:bg-color="aqua" styles:x="25pt"
                        styles:y="20pt" styles:padding="4pt" >This is relative positioned</pdf:Span>
            with this content over the top.
        </pdf:Div>

        <pdf:Div styles:class="bordered" styles:padding="10 60 10 10">
            <pdf:Image src="../../Content/Images/group.png" styles:position-mode="Relative"
                        styles:x="-40pt" styles:y="-10pt" styles:width="100pt" styles:fill-opacity="0.5" />
            This is the content that will flow over the top with the 60 point left padding and the
            image set at -40, -10 relative to the container with a width of 100pt
            and a 50% opacity.
        </pdf:Div>

    </Content>
    </pdf:Page>
</Pages>

</pdf:Document>

By using this rule interesting effects can be designed.

_images/documentpositioningover.png

Position z-index

It’s not currently supported, within scryber to specify a z-index on components. It may be supported in future.

Positioned components

There are 2 components that take advantage of the positioning within Scryber.

  1. Scryber.Components.PDFCanvas positions all direct child components in the canvas as relative, whether they have been decared as such or not.
  2. Scryber.Components.PDFLayerGroup has a collection of child Layers. These will be relatively positioned to the group.