Background Color:
 
Background Pattern:
Reset
Search
Home Recent Changes Show All Pages

Positioning and Flow

Not Rated Yet

Getting content into a page is only half the job. Getting that content flowing correctly around the page(s) and positioning it according to the page and other content is what makes a document interesting. scryber supports block level, inline, relative and absolute positioning with ease and sophistication.

 

Article Contents

 

Background reading.

 

Before jumping into the positioning and flow of content in documents, it is important to understand about the container components Panel, Div, Para, Pre, Span and how Pages and Sections deal with flowing content. Because we will be explicitly laying out content in the is article it is recommended that you also understand Units and measurement, Understanding Styles and the Position Style Item.

 

Laying out some text in a block.

 

By default scryber will always use a flowing layout for textual content measuring each string and fitting to the available width for you. Once that line is full it will move on to the next line and fill this as required. For panels and divs we know that they are treated as block level components, and a block component is the only component on it's own line...So if we put some textual content in a div on a page we can see the layout.

<?xml version="1.0" encoding="utf-8" ?>
<pdf:Document xmlns:pdf="Scryber.Components, Scryber.Components, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
              xmlns:style="Scryber.Styles, Scryber.Styles, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
              xmlns:data="Scryber.Data, Scryber.Components, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
              id="PostioningAndFlow" compression="Compress" auto-bind="true">
  <Viewer page-display="Outlines" page-layout="SinglePage"/>
  <Styles>

  </Styles>
  <Pages>

    <pdf:Page id="titlepage" >
      <Content>
        <pdf:Div id="maincontent" style:border-color="black" >
          By default scryber flows the content of text. So long strings such as this should have soft breaks on to 
          multiple lines of text without having to measure the characters or add explicit breaks. The format within the 
          the actual text (such as tabs and breaks) is ignored within the template - as with HTML.
        </pdf:Div>
      </Content>
    </pdf:Page>

  </Pages>
</pdf:Document>

 

Here we can see the block being rendered with the text inside flowing where necessary.

 

Structure of the page layout.

 

When a document is generated the template is used to create a complete in memory representation of each page in turn. The PDFLayoutPage instance has 3 blocks in it - the header, footer and the body. We are adding our content to the body of the page. Every block has one or more regions in it (these are effectively the columns of the block). And every region has zero or more lines or further blocks.
And so the hierarchy is built of these blocks, regions and lines.

 

Padding and margins.

 

Scryber supports padding and margins on all blocks. The margins are applied to outside the block, and padding insets the contained region within that block. Each side can be set independently, or they can all be set at once. Because of the way the property works, it is possible to set the all property, and then one or more sides individually, but the value of all can no longer be relied on after that point.

NOTE: The border thickness is not (by design) taken into account. If a thick border is applied (or a corner radius) then this may interact with the actual content of the region, and padding may be needed explicitly.

 

<pdf:Document xmlns:pdf="Scryber.Components, Scryber.Components, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
              xmlns:style="Scryber.Styles, Scryber.Styles, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
              xmlns:data="Scryber.Data, Scryber.Components, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
              id="PostioningAndFlow" compression="Compress" auto-bind="true">
  <Viewer page-display="Outlines" page-layout="SinglePage"/>
  <Styles>

  </Styles>
  <Pages>

    <pdf:Page id="titlepage" style:border-color="red" 
              style:margins="20 10 20 10" style:padding="10 10 10 10" >
      <Content>
        <pdf:Div id="maincontent" style:border-color="black" 
                 style:margins="10" style:padding="10" >
          By default scryber flows the content of text. So long strings such as this should have soft breaks on to 
          multiple lines of text without having to measure the characters or add explicit breaks. The format within the 
          the actual text (such as tabs and breaks) is ignored within the template - as with HTML.
        </pdf:Div>
      </Content>
    </pdf:Page>

  </Pages>
</pdf:Document>

 

 

As we can see the inner div is inset 20 points from the red border of the page body. This is the 10pt from the padding of the body and the 10pt from the margins of the div. The available width for the textual content of the div has been reduced, so it flows within the new boundaries

When specifying the margins as a single attribute value they are parsed as Top, Left, Bottom and Right (anti-clockwise from the top).

 

Content above and below

 

If we add a block above our main div, and below, then we can see how it is positioned in the page again.

<pdf:Document xmlns:pdf="Scryber.Components, Scryber.Components, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
              xmlns:style="Scryber.Styles, Scryber.Styles, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
              xmlns:data="Scryber.Data, Scryber.Components, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
              id="PostioningAndFlow" compression="Compress" auto-bind="true">
  <Viewer page-display="Outlines" page-layout="SinglePage"/>
  <Styles>

  </Styles>
  <Pages>

    <pdf:Page id="titlepage" style:border-color="red" 
              style:margins="20 10 20 10" style:padding="10 10 10 10" >
      <Content>
        <pdf:Div style:border-color="green" style:padding="10" >This is some content above</pdf:Div>
        <pdf:Div id="maincontent" style:border-color="black" 
                 style:margins="10" style:padding="10" >
          By default scryber flows the content of text. So long strings such as this should have soft breaks on to 
          multiple lines of text without having to measure the characters or add explicit breaks. The format within the 
          the actual text (such as tabs and breaks) is ignored within the template - as with HTML.
        </pdf:Div>
        <pdf:Div style:border-color="green" style:padding="10" >And this is some content below</pdf:Div>
      </Content>
    </pdf:Page>

  </Pages>
</pdf:Document>

 

Now the top and bottom divs obey the padding of the page block, but have only padding applied to them which is applied within the border rectangle. Our main content div is pushed down, and the div below is after our content div.

Width and Height of blocks

 

Block components support the width and height style properties (either inline, out of line or as an applied style - Understanding Styles)

This means we can apply the sizing explicitly and the content will reflow automatically. (also adding a background fill colour to highlight the output rectangle)

	<pdf:Page id="titlepage" style:border-color="red" 
              style:margins="20 10 20 10" style:padding="10 10 10 10" >
      <Content>
        <pdf:Div style:border-color="green" style:padding="10" >This is some content above</pdf:Div>
        <pdf:Div id="maincontent" style:border-color="black" style:bg-color="#AAAAAA" style:bg-opacity="0.5"
                 style:margins="10" style:padding="10" style:width="140mm" style:height="200mm" >
          By default scryber flows the content of text. So long strings such as this should have soft breaks on to 
          multiple lines of text without having to measure the characters or add explicit breaks. The format within the 
          the actual text (such as tabs and breaks) is ignored within the template - as with HTML.
        </pdf:Div>
        <pdf:Div style:border-color="green" style:padding="10" >And this is some content below</pdf:Div>
      </Content>
    </pdf:Page>

 

 

The dimensions are applied to the border rectangle rather than the total bounds, so with the 10pt margins applied to our content div the actual space taken up will be 140mm + 20pt by 200mm + 20pt. And the content space will be 140mm - 20pt by 200mm - 20pt based on the margins.

Units can be mixed and matched throughout any document. Ultimately they will all be converted to the point unit - that is native to PDF.

 

Relative Positioning

 

Along with the width and height of a block, we also have the x and y style properties. These will not only change the position of the component, but will also automatically change the position-mode from block to relative. A relatively positioned block will not be taken into account in the flow of other components within it's parent, so the bottom content moves up into the position of the main content

The main content block keeps its' width and height (but if not set would still automatically fill the required space for the textual content.)

 

    <pdf:Page id="titlepage" style:border-color="red" 
	          style:margins="20 10 20 10" style:padding="10 10 10 10" >
      <Content>
        <pdf:Div style:border-color="green" style:padding="10" style:bg-color="green" 
                 style:bg-opacity="0.5"  >This is some content above</pdf:Div>

        <pdf:Div id="maincontent" style:border-color="black" style:bg-color="#AAAAAA" style:bg-opacity="0.5" 
                 style:margins="10" style:padding="10" style:width="140mm" style:height="140mm"
                 style:x="10" style:y="10" >
          By default scryber flows the content of text. So long strings such as this should have soft breaks on to 
          multiple lines of text without having to measure the characters or add explicit breaks. The format within the 
          the actual text (such as tabs and breaks) is ignored within the template - as with HTML.
        </pdf:Div>
        <pdf:Div style:border-color="green"  style:padding="10" style:bg-color="green" 
                 style:bg-opacity="0.5" >And this is some content below</pdf:Div>
      </Content>
    </pdf:Page>

 

 

Because the content is positioned relative to it's parent's top left origin - this is the page, then is is positioned relative to the available content rect within the page (taking into account the margins and padding of the page block), and also takes into account the margins of the main content block as well.

Whilst the relative positioning mode is inferred with this example, it is valid to just set the style:position-mode attribute to Relative. If the X or Y values are not set, then they will be inferred as 0 (Zero)

Relative positions also effect the calculated size of the parent container, so if we wrap all our current content in an outer div it's size will be the union of all the bounds. Any following content will be below this.

	<pdf:Page id="titlepage" style:border-color="red"
	              style:margins="20 10 20 10" style:padding="10 10 10 10" >
      <Content>

        <pdf:Div id="outerdiv" style:bg-color="lime" style:bg-opacity="0.5" >

          <pdf:Div style:border-color="green" style:padding="10" style:bg-color="green"
                   style:bg-opacity="0.5"  >This is some content above</pdf:Div>

          <pdf:Div id="maincontent" style:border-color="black" style:bg-color="#AAAAAA" style:bg-opacity="0.5"
                   style:margins="10" style:padding="10" style:width="140mm" style:height="140mm"
                   style:x="10" style:y="10" >
            By default scryber flows the content of text. So long strings such as this should have soft breaks on to
            multiple lines of text without having to measure the characters or add explicit breaks. The format within the
            the actual text (such as tabs and breaks) is ignored within the template - as with HTML.
          </pdf:Div>
          <pdf:Div style:border-color="green"  style:padding="10" style:bg-color="green"
                   style:bg-opacity="0.5" >And this is some content below</pdf:Div>

        </pdf:Div>
                  This is some content after the outer container.
      </Content>
    </pdf:Page>

 

 

Absolute positioning

 

With absolute positioning, the location of the component is relative to the current page irrespective of it's parent components and their position. To position a component absolutely, it's the applied position-mode attribute must be explicitly set to Absolute.

When components are positioned in this way, they no longer have any impact on the size and space required for their parent components.

    <pdf:Page id="titlepage" style:border-color="red"
	              style:margins="20 10 20 10" style:padding="10 10 10 10" >
      <Content>

        <pdf:Div id="outerdiv" style:bg-color="lime" style:bg-opacity="0.5" >

          <pdf:Div style:border-color="green" style:padding="10" style:bg-color="green"
                   style:bg-opacity="0.5"  >This is some content above</pdf:Div>

          <pdf:Div id="maincontent" style:border-color="black" style:bg-color="#AAAAAA" style:bg-opacity="0.5"
                   style:margins="10" style:padding="10" style:width="140mm" style:height="140mm"
                   style:x="10" style:y="10" style:position-mode="Absolute" >
            By default scryber flows the content of text. So long strings such as this should have soft breaks on to
            multiple lines of text without having to measure the characters or add explicit breaks. The format within the
            the actual text (such as tabs and breaks) is ignored within the template - as with HTML.
          </pdf:Div>
          <pdf:Div style:border-color="green"  style:padding="10" style:bg-color="green"
                   style:bg-opacity="0.5" >And this is some content below</pdf:Div>

        </pdf:Div>
        This is some content after the outer container.
      </Content>
    </pdf:Page>

 

 

In the above example the main-content div's border top left is at x=20 and y=20, because the position is 10,10 and the margins are 10,10. We can also see that the content after the outer container has moved up.

 

Top to Bottom Ordering

 

As can be seen in the example the order of the components as added to the template is preserved in the drawing output. It is not the offset from the top left that determines rendering order, but the order in the collection of components. It does not matter is the component is relatively positioned or absolutely positioned, the drawing instructions are kept in the order the components are collected.

At the moment there is no z-order attribute or other way to alter the 'depth' or components as drawn on the page - except change the order in the collection

 

Using style for position

 

As with other style attributes, the position values can all be driven from applied styles either within the document, or in a referenced style-sheet (.psfx)

<pdf:Document xmlns:pdf="Scryber.Components, Scryber.Components, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
              xmlns:style="Scryber.Styles, Scryber.Styles, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
              xmlns:data="Scryber.Data, Scryber.Components, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"
              id="PostioningAndFlow" compression="Compress" auto-bind="true">
  <Viewer page-display="Outlines" page-layout="SinglePage"/>
  <Styles>
    <style:Style applied-type="pdf:Div" >
        <style:Background opacity="0.5"/>
      </style:Style>

    <style:Style applied-class="topandbottom" >
      <style:Border color="green"/>
      <style:Padding all="10"/>
      <style:Background color="green"/>
    </style:Style>

    <style:Style applied-id="maincontent" >
      <style:Border color="black" />
      <style:Background color="#AAAAAA" />
      <style:Padding all="10"/>
      <style:Margins all="10"/>
      <style:Position mode="Absolute" x="10" y="10" width="140mm" height="140mm"/>
      <style:Fill opacity="0.5"/>
    </style:Style>

    <style:Style applied-id="outerdiv">
      <style:Background color="lime"/>
    </style:Style>
  </Styles>
  <Pages>

    <pdf:Page id="titlepage" style:border-color="red"
              style:margins="20 10 20 10" style:padding="10 10 10 10" >
      <Content>

        <pdf:Div id="outerdiv" >

          <pdf:Div style:class="topandbottom"  >This is some content above</pdf:Div>

          <pdf:Div id="maincontent" >
            By default scryber flows the content of text. So long strings such as this should have soft breaks on to
            multiple lines of text without having to measure the characters or add explicit breaks. The format within the
            the actual text (such as tabs and breaks) is ignored within the template - as with HTML.
          </pdf:Div>
          <pdf:Div style:class="topandbottom" >And this is some content below</pdf:Div>

        </pdf:Div>
        This is some content after the outer container.
      </Content>
    </pdf:Page>

  </Pages>
</pdf:Document>

This simplifies our content significantly, and separates the content from the presentation

 

Inline positioning

 

As mentioned the Div is by default a block level component appearing on it's own line within the page content and filling the width. However this behaviour is driven from the base style, rather than there being any special significance to the Div component itself - it is simply a panel.

    [PDFParsableComponent("Div")]
    public class PDFDiv : PDFPanel
    {

        [PDFElement()]
        [PDFArray(typeof(PDFVisualComponent))]
        public override PDFVisualComponentList Contents
        {
            get
            {
                return base.Contents;
            }
        }

        public PDFDiv()
            : this(PDFObjectTypes.Div)
        {
        }

        protected PDFDiv(PDFObjectType type)
            : base(type)
        {
        }

        protected override PDFStyle GetBaseStyle()
        {
            PDFStyle style = base.GetBaseStyle();
            style.Position.FullWidth = true;
            style.Position.PositionMode = Drawing.PositionMode.Block;
            return style;
        }
    }

We can completely alter the behaviour of the Div, and make it act just like a span by setting the postion-mode of the Div to inline, and remove any X,Y,Width and Height values (as these have a higher precedence).

NOTE: Inline components do not support backgrounds, padding, margins or borders - as they do not have blocks to apply these styles to.
    <pdf:Page id="titlepage" style:class="grid" style:border-color="red"
	              style:margins="20 10 20 10" style:padding="10 10 10 10" >
      <Content>

        <pdf:Div id="outerdiv" style:bg-color="lime" style:bg-opacity="0.5" >

          <pdf:Div style:class="topandbottom" style:position-mode="Inline"  >This is some content above</pdf:Div>

          <pdf:Div style:position-mode="Inline" >
            By default scryber flows the content of text. So long strings such as this should have soft breaks on to
            multiple lines of text without having to measure the characters or add explicit breaks. The format within the
            the actual text (such as tabs and breaks) is ignored within the template - as with HTML.
          </pdf:Div>
          <pdf:Div style:class="topandbottom" style:position-mode="Inline" >And this is some content below</pdf:Div>

        </pdf:Div>
        This is some content after the outer container.
      </Content>
    </pdf:Page>

 

 

As can be seen, the outer div still acts as a block with a background color, but the top bottom and main content flow seamlessly from one to the next.

 

Checking your positioning.

 

During the building of complex layouts, it can be required to validate where content is positioned, and where it moves other content to. The scryber styles include an Overlay-Grid Style Item that will render a grid on top of any content at the required spacing interval so it can be checked. This style can also render a colour behind the content for each of the columns. The overlay can be added to the page or any component on the page, and multiple grids can be rendered.

  .
  .
  .
   <style:Style applied-class="grid" >
     <style:Overlay-Grid color="aqua" opacity="1" spacing="10mm" show="true"/>
   </style:Style>

  </Styles>

  <Pages>

    <pdf:Page id="titlepage" style:class="grid" style:border-color="red"
              style:margins="20 10 20 10" style:padding="10 10 10 10" >
      <Content>
      .
      .
      .

 

 

See Also



  Rating
Rate This Page: Poor Great   |  Rate Content |
Average rating:  No Ratings Yet   
Number of Ratings : 0
  Comments
Add Comment
No Comments Yet