Cover (Title) Page
Customizing the cover page is one of the most requested customization requests.
Cover Page - XML Fragment
The merged
map file contains the <oxy:front-page>
element, as a child of
the root element. This contains the metadata and an
<oxy:front-page-title>
element with the title structure.
<bookmap xmlns:ditaarch="http://dita.oasis-open.org/architecture/2005/" ...>
<oxy:front-page xmlns:oxy="http://www.oxygenxml.com/extensions/author">
<bookmeta xmlns:dita-ot="http://dita-ot.sourceforge.net/ns/201007/dita-ot"
...
</bookmeta>
<oxy:front-page-title>
<booktitle xmlns:dita-ot="http://dita-ot.sourceforge.net/ns/201007/dita-ot"
class="- topic/title bookmap/booktitle ">
<booklibrary class="- topic/ph bookmap/booklibrary ">Retro Tools</booklibrary>
<mainbooktitle class="- topic/ph bookmap/mainbooktitle ">Tasks</mainbooktitle>
<booktitlealt class="- topic/ph bookmap/booktitlealt ">Product tasks</booktitlealt>
</booktitle>
</oxy:front-page-title>
</oxy:front-page>
For the DITA Map PDF - based on HTML5 & CSS
transformation type, the merged map is further processed resulting in a collection
of HTML5 <div>
elements. These elements preserve the
original DITA @class
attribute values and add a new value derived
from the DITA element name.
<div class="- map/map bookmap/bookmap bookmap" ... >
<div class=" front-page/front-page front-page">
<div class="- map/topicmeta bookmap/bookmeta boometa">
...
</div>
<div class=" front-page/front-page-title front-page-title">
<div class="- topic/title bookmap/booktitle booktitle">
<div class="- topic/ph bookmap/booklibrary booklibrary">Retro Tools</div>
<div class="- topic/ph bookmap/mainbooktitle mainbooktitle">Tasks</div>
<div class="- topic/ph bookmap/booktitlealt booktitlealt">Product tasks</div>
</div>
...
Cover Page - Built-in CSS rules
The element with the class frontpage/frontpage
is associated with a page
named front-page with no headers or footers. The front page title is styled with a
bigger font. The built-in CSS rules are in
[PLUGIN_DIR]/css/print/p-front-page.css.
@media print {
*[class~="front-page/front-page"] {
page: front-page;
}
/* Prevents the front-page title margin collapsing */
*[class~="front-page/front-page"]::before(1000) {
display:block;
content:"\A";
font-size:0;
}
*[class~="front-page/front-page-title"] {
display:block;
text-align:center;
margin-top:3in;
font-size:2em;
font-family:arial, helvetica, sans-serif;
font-weight:bold;
}
@page front-page {
@top-left-corner { content:none }
@top-left { content:none }
@top-center { content:none }
@top-right { content:none }
@top-right-corner { content:none }
@bottom-left-corner { content:none }
@bottom-left { content:none }
@bottom-center { content:none }
@bottom-right { content:none }
@bottom-right-corner{ content:none }
}
}
How to Add a Background Image for the Cover
The simplest way is to create an SVG image as large as the entire physical page and set it as
the background for the front-page. This makes it easy to accomplish a good positioning
of the graphical elements or artwork. In the foreground, you can place text fragments using a
series of :after
pseudo-elements bound to the front page title.
To set the size to an SVG image, you should specify the @width
and
@height
attributes on the <svg>
root element using
specified unit values (in, cm, etc.) This should be enough only if all the coordinates from
your drawing have unit identifiers.
<polygon points="17.78 826.21 577.51 ....
Next,
make sure you also specify the @viewBox
attribute on the
<svg>
root element that defines the abstract rectangle that contains
the drawing:<svg xmlns="http://www.w3.org/2000/svg" width="8.5in" height="11in" viewBox="0 0 600 850">
The following SVG document has the @width
, @height
, and
@viewBox
attributes. The width and height have physical units (in inches),
while the view box and rectangle coordinates are unit-less.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" width="8.5in" height="11in" viewBox="0 0 110 110">
<desc>A gradient as big as a page.</desc>
<defs>
<linearGradient id="lc"
x1="0%" y1="0%"
x2="0%" y2="100%"
spreadMethod="pad">
<stop offset="0%" stop-color="#00DD00" stop-opacity="1"/>
<stop offset="100%" stop-color="#00AA00" stop-opacity="1"/>
</linearGradient>
</defs>
<rect x="5" y="5" width="100" height="100" rx="10" ry="10"
style="fill:url(#lc);
stroke: #005000;
stroke-width: 3;"/>
<text x="33%" y="50%" color="#FFFFAA"> Sample </text>
</svg>
This example shows a gradient. It is the size of a US-LETTER page and can be used in a publication using this page size.
In your customization CSS, add the following:
@page front-page {
background-image: url("us-letter.svg");
background-position: center;
background-repeat: no-repeat;
background-size: 100% 100%;
}
For smaller artworks, you can use background-position
with percentage values
to position and center the artwork (for example, a company logo):
@page front-page {
background-image:url("company-logo.svg");
background-position:50% 5%; /* The first is the alignement on the X axis, the second on the Y axis.*/
background-repeat:no-repeat;
}
How to Display the Background Cover Image Before the Title
@page front-page {
@top-left { content: none; }
@top-right { content: none; }
@bottom-center { content: none; }
background-image: url("us-letter.svg");
background-position: center;
background-repeat: no-repeat;
background-size: 100% 100%;
}
@page main-title-page {
@top-left { content: none; }
@top-right { content: none; }
@bottom-center { content: none; }
}
*[class ~= "front-page/front-page-title"]:before {
display: block;
content: "\2002";
margin-bottom: 3in;
}
*[class ~= "front-page/front-page-title"] {
page: main-title-page;
}
How to Use Different Background Cover Images Based on Bookmap or Map Information
It is common to use the same CSS file for customizing multiple publications, and you may need to set a different cover for each of them. The solution is to use an XPath expression to extract some information from the document, and based on that, select the SVG images.
@page front-page {
background-image: url(oxy_xpath("\
if(//*[contains(@class, ' topic/prodname ')][1] = 'gardening') then 'bg-gardening.svg' else\
if(//*[contains(@class, ' topic/prodname ')][1] = 'soil') then 'bg-soil.svg'\
else 'bg-default.svg'\
"));
background-position:center;
}
The backslash (\) is used to continue the expression string on the subsequent lines (there should be no spaces after it). For more use cases solved using XPath, see: Metadata.
How to Change Styling of the Cover Page Title
*[class ~= "front-page/front-page-title" {
margin-top: 1in;
font-size: 3em;
}
How to Add Text to the Cover Page
If you need to add arbitrary text to the cover page, you can use the front page title element as an anchor and add as many blocks of text as you need after it, and style them differently.
In your customization CSS, add the following:
*[class ~= "front-page/front-page-title"]:after(1) {
display:block;
content: "DRAFT VERSION";
font-size: large;
color: red;
text-align:center;
}
*[class ~= "front-page/front-page-title"]:after(2) {
display:block;
content: "DO NOT DISTRIBUTE WITHOUT PERMISSION";
font-size: large;
color: red;
text-align:center;
font-style: italic;
}
The result is:
To use content from the document, you can use the oxy_xpath
function in
the content
property. For a more complex example, including the generation of
a new page for the synthetic :after
elements, see: How to Show Metadata in the Cover Page.
How to Place Cover on the Right or Left Side
In your customization CSS, add the following CSS rules:
*[class ~= "front-page/front-page"]{
page-break-before:left;
}
For more information, see: Oxygen PDF Chemistry: Controlling Page Breaks.
How to Add a Second Cover Page and Back Cover Page
@page second-cover {
@top-left {content: none;}
@top-right {content: none;}
@bottom-center {content: none;}
background-image: url("second-cover.svg");
background-position: center;
background-repeat: no-repeat;
background-size: 100% 100%;
}
*[class ~= 'front-page/front-page']:after{
page: second-cover;
page-break-after: always;
display: block;
content: "\2002";
}
:after
pseudo element on the map
itself:*[class ~= "map/map"]:after
@page
declaration:@page back-cover {
@top-left {content: none;}
@top-right {content: none;}
@bottom-center {content: none;}
background-image: url("back-cover.svg");
background-position: center;
background-repeat: no-repeat;
background-size: 100% 100%;
}
*[class ~= "map/map"]:after {
page: back-cover;
content: "\2002";
}
background-image
, it is recommended to use
SVG instead of PNG (or JPG) because it scales it to the page size.:after(1)
, :after(2)
. Remember that the
larger the value, the more distant the pseudo element is to the target element.How to Dynamically Add a Second Cover Page
It is possible to dynamically set the path to the SVG image that will be displayed on the secondary cover page.
First, you need to declare a <data>
element in the
bookmap's metadata that contains the URL to your cover image:
<bookmap>
<booktitle>
...
</booktitle>
<bookmeta>
<metadata>
<data name="second-cover-url" value="covers/second-cover.svg"/>
</metadata>
</bookmeta>
...
</bookmap>
<topicmeta>
after the map's <title>
.Next, you need to modify the page declaration inside your CSS stylesheet and replace the
background-image
property value with the result of the
oxy_xpath()
function:
@page second-cover {
...
background-image: url(oxy_xpath("//*[contains(@class, 'bookmap/bookmeta')]//*[contains(@class, 'topic/data')][@name='second-cover-url']/@value"));
...
}
How to Add a Specific Number of Empty Pages After the Cover Page
In your customization CSS, add the following CSS rules:
@page my-blank-page {
/* Hide the page numbers */
@top-left {content: none;}
@top-right {content: none;}
}
*[class ~= 'front-page/front-page']:after(1){
page:my-blank-page;
display:block;
content: '\2002';
color:transparent;
page-break-after:always;
}
*[class ~= 'front-page/front-page']:after(2){
page:my-blank-page;
display:block;
content: '\2002';
page-break-after:always;
}
*[class ~= 'front-page/front-page']:after(3){
page:my-blank-page;
display:block;
content: '\2002';
page-break-after:always;
}
\2002
character is a space that is not shown on the pages,
but gives a value for the content property.How to Add a Copyright Page after the Map Cover (Not for Bookmaps)
Regular DITA maps do not have the concept of a copyright notice. This is available only in the DITA bookmap structure.
If you are constrained to using a regular map and you need to add a copyright page between the front cover and the TOC, use the following technique:
In your customization CSS, declare a new page layout:
@page copyright-notice-page {
@top-left {
content:none; /* Clear the headers for the copyright page */
}
@top-right {
content:none;
}
}
The element with the class front-page/front-page
element contains the title
of the publication and generates the cover page. A synthetic :after
element
is created that follows this element and it is placed on a different page.
*[class~="front-page/front-page"]:after{
display:block;
page: copyright-notice-page; /* Moves the synthetic element on a new page. */
margin-top:90%; /* use margins to position the text in the page */
margin-left: 5em;
margin-right: 5em;
content: "Copyright 2018-2019 MyCorp Inc. \A All rights reserved";
text-align:center; /* More styling */
color:blue;
}
If you need to add more content as blocks, use the :after(2)
,
:after(3)
pseudo-elements:
*[class~="front-page/front-page"]:after(2){
display:block;
page: copyright-notice-page; /* Continue on the same page as the first ':after'. */
content: "Some more styled text";
color:red;
}
If you want to extract information from the document, use the oxy_xpath()
function. For example, if the copyright info is stored in the map like this:
<map ...>
<topicmeta>
<copyright>
<copyryear year="2018"/>
<copyrholder>MyCorp Inc.</copyrholder>
</copyright>
</topicmeta>
...
then use this:
*[class ~= "front-page/front-page"]:after(3) {
display: block;
page: copyright-notice-page;
content:
"Year: "
oxy_xpath('//*[contains(@class, " front-page/front-page ")]/*[contains(@class, " map/topicmeta ")]/*[contains(@class, " topic/copyright ")]/*[contains(@class, " topic/copyryear ")]/@year')
"\A Holder: "
oxy_xpath('//*[contains(@class, " front-page/front-page ")]/*[contains(@class, " map/topicmeta ")]/*[contains(@class, " topic/copyright ")]/*[contains(@class, " topic/copyrholder ")]/text()');
color: green;
}
How to Remove the Cover Page and TOC
If you need to hide or remove the cover page, the table of contents or
other structures, match the elements with a "front-page/front-page
" and
"toc/toc
" classes in your customization CSS:
*[class ~= 'map/map'] > *[class ~= 'toc/toc'] {
display:none !important;
}
*[class ~= 'map/map'] > *[class ~= 'front-page/front-page']{
display:none !important;
}
*[class~='topic/topic'][is-chapter] {
-oxy-page-group : auto;
}
How to Add a Cover in Single-Topic Publishing
It is possible to add a cover page before the topic when publishing a single-topic PDF (without a DITA map) using the DITA PDF - based on HTML5 & CSS transformation scenario.
@page
rule and add it in a block before the actual content of the
document:@page topic-cover {
@top-left {content: none;}
@top-right {content: none;}
background-image: url("img/cover.svg");
background-position: center;
background-repeat: no-repeat;
background-size: 100% 100%;
}
:root::before {
page: topic-cover;
display: block;
content: "\2002";
page-break-after: always;
}
How to Use SVG Templates for Creating Dynamic Cover Pages
It is possible to use XPath expressions inside SVG templates to insert dynamic text when creating PDF output using the DITA Map PDF - based on HTML5 & CSS scenario.
Using SVG Template as a Cover Page
- In the source
<bookmap>
, the various metadata elements are inserted inside the<bookmeta>
element:<bookmap id="taskbook"> <booktitle> <booklibrary>Retro Tools</booklibrary> <mainbooktitle>Product tasks</mainbooktitle> <booktitlealt>Tasks and what they can do</booktitlealt> </booktitle> <bookmeta> <author>Howe Tuduit</author> <critdates> <created date="2015-01-01"/> <revised modified="2016-04-03"/> <revised modified="2016-03-05"/> </critdates> ... <bookrights> <copyrfirst> <year>2004</year> </copyrfirst> <copyrlast> <year>2007</year> </copyrlast> <bookowner> <organization>Retro Tools, Inc.</organization> </bookowner> </bookrights> </bookmeta> ...
- The corresponding
merged.html
file will have the following content:... <div class="- front-page/front-page front-page"> <div class="- map/topicmeta bookmap/bookmeta topicmeta bookmeta"> <div class="- topic/author author">Howe Tuduit</div> <div class="- topic/critdates critdates"> <div date="2015-01-01" class="- topic/created created"></div> <div modified="2016-04-03" class="- topic/revised revised"></div> <div modified="2016-03-05" class="- topic/revised revised"></div> </div> ... <div class="- topic/data bookmap/bookrights data bookrights"> <div class="- topic/data bookmap/copyrfirst data copyrfirst"> <div class="- topic/ph bookmap/year ph year">2004</div> </div> <div class="- topic/data bookmap/copyrlast data copyrlast"> <div class="- topic/ph bookmap/year ph year">2007</div> </div> <div class="- topic/data bookmap/bookowner data bookowner"> <div class="- topic/data bookmap/organization data organization">Retro Tools, Inc.</div> </div> </div> </div> <div class="- front-page/front-page-title front-page-title"> <div class="- topic/title bookmap/booktitle title booktitle"> <span class="- topic/ph bookmap/booklibrary ph booklibrary">Retro Tools</span> <span class="- topic/ph bookmap/mainbooktitle ph mainbooktitle">Product tasks</span> <span class="- topic/ph bookmap/booktitlealt ph booktitlealt">Tasks and what they can do</span> </div> </div> </div> ...
- The cover image (for example, named cover.template.svg) should
display
<bookmeta>
node information (author, creation date, and copyright information) and the<mainbooktitle>
will be displayed rotated.<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 610 790" style="enable-background:new 0 0 610 790;" xml:space="preserve"> <style type="text/css"> .st0{fill:url(#SVGID_1_);} .st1{opacity:0.31;fill:#FFFFFF;enable-background:new ;} .st2{fill:#FFFFFF;} .st3{fill:#F04C3E;} .st4{fill:none;stroke:#FFFFFF;stroke-width:0.3685;stroke-miterlimit:2.6131;} .st5{font-family:'Arial';} .st6{font-size:24.3422px;} .st7{font-size:10px;} .st8{font-size:63.3422px;font-weight:bold;} .st9{fill:#F04C3E;stroke:#000000;stroke-miterlimit:10;} </style> <linearGradient id="SVGID_1_" x1="305.6" y1="799.9393" x2="305.6" y2="8.9393" gradientUnits="userSpaceOnUse"> <stop offset="1.848748e-02" style="stop-color:#2F639F"/> <stop offset="1" style="stop-color:#1C3E72"/> </linearGradient> <rect x="0.1" y="0.1" class="st0" width="611" height="791"/> <path class="st1" d="M143.4,700.5l381.3-381.3c35.2-35.2,35.2-92.3, 0-127.5L332.1-0.9H0.1v685.6l15.8,15.8C51.1,735.7,108.2,735.7,143.4,700.5z"/> <path class="st2" d="M1.5,617.6c29.2,22.6,71.4,20.5,98.2-6.3l315.2-315.2c29.1-29.1, 29.1-76.3,0-105.4L224.8,0.5H1.5V617.6z"/> <text transform="matrix(1 0 0 1 419.998 615.9277)" class="st2 st5 st6"> ${//*[contains(@class, 'bookmap/bookmeta')]/*[contains(@class, 'topic/author')]} </text> <text transform="matrix(1 0 0 1 419.998 660.9277)" class="st2 st5 st6"> ${//*[contains(@class, 'bookmap/bookmeta')]//*[contains(@class, 'topic/created')]/@date} </text> <text transform="matrix(1 0 0 1 471.998 749.9277)" class="st2 st5 st7">© ${ concat(//*[contains(@class, 'bookmap/bookmeta')]/*[contains(@class, 'bookmap/bookrights')] //*[contains(@class, 'bookmap/organization')], ' ', //*[contains(@class, 'bookmap/bookmeta')]/*[contains(@class, 'bookmap/bookrights')] /*[contains(@class, 'bookmap/copyrlast')]/*[contains(@class, 'bookmap/year')]) } </text> <text transform="matrix(0.7071 -0.7071 0.7071 0.7071 88.1369 568.6693)" class="st9 st5 st8"> ${ //*[contains(@class, 'front-page/front-page-title')] //*[contains(@class, 'bookmap/mainbooktitle')] } </text> </svg>
Notes:- XPath expressions are not expanded if the SVG template is open in Author mode.
- XPath expressions can be tested (without
${}
) using the XPath/XQuery Builder view. - XPath Conditional Expressions, For Expressions, and Let Expressions are supported.
Important:- If you received the SVG image from someone else (e.g. a graphics designer), make
sure that the text from the image was not converted to glyph shapes and that it is
rendered using the
<text>
element. - The SVG
<text>
element does not wrap the text if it overflows the image. If you have longer text that needs to be rendered, you might consider using multiple<text>
elements and more evolved XPath expressions (for example, using thesubstring()
function) to place the text on multiple lines.
Tip: You can ask a designer to fill the image with some placeholders that you can later find and replace with your XPath expressions. In the above SVG, the designer could place the textHere comes the author
, that you replace with${//*[contains(@class, 'bookmap/bookmeta')]/*[contains(@class, 'topic/author')]}
:<text transform="matrix(1 0 0 1 419.998 615.9277)" class="st2 st5 st6"> Here comes the author </text>
- The CSS stylesheet should declare the template file as a background-image for the cover.
Also the following example hides the
<mainbooktitle>
and its bookmark (it is displayed in the template):@page front-page { background-image: url("cover.template.svg"); background-repeat: no-repeat; background-size: 100% 100%; } *[class ~= "bookmap/booktitle"] { display: none; } *[class ~= "front-page/front-page-title"] > *[class ~= "bookmap/booktitle"] > *[class ~= "bookmap/mainbooktitle"] { bookmark-level: 0; }
- After the transformation, the final document cover will look like this: