Styles, Templates & Markup
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
Baseline date: 2026-10-09. A JasperReports design says where things go (see JRXML Report Design) and a style says how they look: font, colours, borders, alignment, number pattern, line spacing. Repeating those attributes on every element is how reports become impossible to restyle, so JasperReports lets an element point to a named style, lets a style inherit from another, switch properties on and off with a condition, and live in a separate style template file shared by many reports. Text can also carry formatting inside its own content through styled text, HTML or RTF markup. This page covers all of that for JasperReports 7.0.8, using a stock report of the Bookshelf Billing service: a list of books with the low-stock rows in red, alternate row colours and the category highlighted by a computed style.
The example below was compiled, filled and exported to PDF with Java 21 and JasperReports 7.0.8, and the PDF was rendered to an image and read back to check the colours, the fonts and the text. Behaviour observed in that run, and that the official samples do not describe, is marked "observed". The expressions used in the conditions are explained in Expressions, Parameters, Fields & Variables, the font side (font extensions, embedding, missing fonts) in Fonts & Internationalization, and the Maven setup in Getting Started with Spring Boot.
What a style is, and what changed since the old books
A style is a <style> element with a unique name and any of the formatting attributes. Elements refer to it with their
style attribute and inherit every attribute that applies to their kind (a text field uses the font and the alignment, a
rectangle only the colours and the pen). Attributes written on the element override the style. A style can name a parent
with its own style attribute, and one style of the report can be marked default="true": it applies to every element
that has no style of its own, and it is the root of the inheritance chain of the other styles (the property
net.sf.jasperreports.styles.inherit.from.default is true in the default configuration of 7.0.8).
The attributes that a 7.0.8 <style> accepts are listed below. The list is what the Jackson loader reports for the style
class, so it is the authority for 7.0 files, whatever the older documentation says.
| Group | Attributes and children |
|---|---|
Identity and inheritance |
|
Colours and fill |
|
Text |
|
Images |
|
PDF font hints |
|
Children |
|
The books of the corpus describe styling with the mechanisms of their day, and several of them do not load any more
(finding O18). B2 (JasperReports 1.x/2.x) and B3 (the Ultimate Guide) use a report-wide reportFont element, boolean
attributes with the is prefix, the pdfFontName, pdfEncoding and isPdfEmbedded triple as the way to reach a PDF font,
the Acrobat Asian font packs, and border and leftBorder attributes on elements. Nothing from those books is reproduced
here, and these are the results for 7.0.8, each checked by compiling a one-line report:
-
<reportFont>is rejected:Unrecognized field "reportFont"(aJacksonRuntimeException). Fonts are set with styles. -
isBoldon a style is rejected in the same way; the attribute isbold(anditalic,underline,strikeThrough). -
borderandleftBorderon an element are rejected; borders are a<box>with<pen>children, shown below. -
isStyledTextis rejected; the replacement ismarkup="styled". -
pdfFontName,pdfEncodingandpdfEmbeddedstill load. The supported way to embed fonts is the font extension mechanism (jasperreports-fontsandjasperreports_extension.properties), not these attributes. -
An unknown style name in
stylefails withCould not resolve style(s): nope.
A v6 JRXML (and a v6 .jrtx, see below) is not a 7.0 file, so the whole file needs converting with Jaspersoft Studio 7, as
explained on the JRXML design page.
A complete example
The example is one report with a style template. The template holds the house look, and the report adds the pieces that depend on its own data. All three files are the ones that were run.
The style template, src/main/resources/reports/styles.jrtx, defines a default style, a table heading, a table cell whose
text turns red and bold when the row is low on stock, and a money cell:
<jasperTemplate>
<style name="Base" default="true" fontName="DejaVu Sans" fontSize="9.0" forecolor="#222222" vTextAlign="Middle"/>
<style name="Heading" style="Base" mode="Opaque" backcolor="#1F5FA6" forecolor="#FFFFFF" bold="true">
<box padding="3"/>
</style>
<style name="Cell" style="Base">
<box padding="3">
<bottomPen lineWidth="0.5" lineColor="#CCCCCC"/>
</box>
<conditionalStyle forecolor="#B00020" bold="true">
<conditionExpression><![CDATA[$F{lowStock}]]></conditionExpression>
</conditionalStyle>
</style>
<style name="Money" style="Cell" hTextAlign="Right" pattern="#,##0.00"/>
</jasperTemplate>
The report, src/main/resources/reports/styles-demo.jrxml, loads the template, adds the zebra stripes as a conditional
style (they use a report variable, which a template cannot), picks the category style with an expression, and shows
HTML, styled text and a paragraph definition in the title:
<jasperReport name="styles-demo" language="java"
pageWidth="595" pageHeight="842" columnWidth="515"
leftMargin="40" rightMargin="40" topMargin="40" bottomMargin="40">
<template><![CDATA["reports/styles.jrtx"]]></template>
<style name="Zebra" style="Cell">
<conditionalStyle mode="Opaque" backcolor="#F2F6FC">
<conditionExpression><![CDATA[$V{REPORT_COUNT} % 2 == 0]]></conditionExpression>
</conditionalStyle>
</style>
<style name="CategoryPlain" fontName="DejaVu Sans" fontSize="9.0" vTextAlign="Middle">
<box padding="3">
<bottomPen lineWidth="0.5" lineColor="#CCCCCC"/>
</box>
</style>
<style name="CategoryHighlight" style="CategoryPlain" mode="Opaque" backcolor="#FFF3C4"/>
<style name="ZebraMoney" style="Zebra" hTextAlign="Right" pattern="#,##0.00"/>
<field name="title" class="java.lang.String"/>
<field name="category" class="java.lang.String"/>
<field name="stock" class="java.lang.Integer"/>
<field name="price" class="java.math.BigDecimal"/>
<field name="lowStock" class="java.lang.Boolean"/>
<title height="130">
<element kind="staticText" x="0" y="0" width="515" height="24" fontSize="16.0" bold="true">
<text><![CDATA[Bookshelf stock report]]></text>
</element>
<element kind="staticText" x="0" y="28" width="515" height="40" markup="html">
<text><![CDATA[Titles in <font color="#B00020"><b>red</b></font> are <i>low on stock</i>; H<sub>2</sub>O and x<sup>2</sup> need no escapes.]]></text>
</element>
<element kind="staticText" x="0" y="72" width="515" height="50" markup="styled" style="Base">
<paragraph firstLineIndent="20" leftIndent="10" spacingAfter="4" lineSpacing="Fixed" lineSpacingSize="14.0">
<tabStop position="200" alignment="Right"/>
</paragraph>
<text><![CDATA[Styled: <style isBold="true" forecolor="#1F5FA6">Bookshelf</style> <style backcolor="yellow">marker</style> tabbed]]></text>
</element>
</title>
<columnHeader height="20">
<element kind="staticText" x="0" y="0" width="280" height="20" style="Heading"><text><![CDATA[Title]]></text></element>
<element kind="staticText" x="280" y="0" width="100" height="20" style="Heading"><text><![CDATA[Category]]></text></element>
<element kind="staticText" x="380" y="0" width="50" height="20" style="Heading" hTextAlign="Right"><text><![CDATA[Stock]]></text></element>
<element kind="staticText" x="430" y="0" width="85" height="20" style="Heading" hTextAlign="Right"><text><![CDATA[Price]]></text></element>
</columnHeader>
<detail>
<band height="20">
<element kind="textField" x="0" y="0" width="280" height="20" style="Zebra"><expression><![CDATA[$F{title}]]></expression></element>
<element kind="textField" x="280" y="0" width="100" height="20" style="CategoryPlain">
<styleExpression><![CDATA["Science".equals($F{category}) ? "CategoryHighlight" : "CategoryPlain"]]></styleExpression>
<expression><![CDATA[$F{category}]]></expression>
</element>
<element kind="textField" x="380" y="0" width="50" height="20" style="Zebra" hTextAlign="Right"><expression><![CDATA[$F{stock}]]></expression></element>
<element kind="textField" x="430" y="0" width="85" height="20" style="ZebraMoney"><expression><![CDATA[$F{price}]]></expression></element>
</band>
</detail>
</jasperReport>
The row class is a plain JavaBean (a Java record is not accepted by the bean data source, see the JRXML page):
package bookshelf;
import java.math.BigDecimal;
public class Book {
private final String title;
private final String category;
private final int stock;
private final BigDecimal price;
public Book(String title, String category, int stock, BigDecimal price) {
this.title = title;
this.category = category;
this.stock = stock;
this.price = price;
}
public String getTitle() { return title; }
public String getCategory() { return category; }
public int getStock() { return stock; }
public BigDecimal getPrice() { return price; }
public boolean isLowStock() { return stock < 5; }
}
And the driver compiles the report, fills it with a fixed locale so that the number pattern prints the same everywhere, and writes the PDF:
package bookshelf;
import java.io.InputStream;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
public class StylesDemo {
public static void main(String[] args) throws Exception {
List<Book> books = List.of(
new Book("Dune", "Fiction", 12, new BigDecimal("9.90")),
new Book("Cosmos", "Science", 3, new BigDecimal("14.50")),
new Book("Emma", "Fiction", 8, new BigDecimal("7.25")),
new Book("The Selfish Gene", "Science", 20, new BigDecimal("11.00")),
new Book("Ulysses", "Fiction", 1, new BigDecimal("13.75")));
try (InputStream jrxml = StylesDemo.class.getResourceAsStream("/reports/styles-demo.jrxml")) {
JasperReport report = JasperCompileManager.compileReport(jrxml);
Map<String, Object> params = new HashMap<>();
params.put(JRParameter.REPORT_LOCALE, Locale.ENGLISH);
JasperPrint print = JasperFillManager.fillReport(report, params, new JRBeanCollectionDataSource(books));
Path out = Path.of(args.length > 0 ? args[0] : "styles-demo.pdf");
Files.write(out, JasperExportManager.exportReportToPdf(print));
System.out.println(out + ": " + print.getPages().size() + " page(s)");
}
}
}
The dependencies are the four JasperReports artifacts of this section at 7.0.8
(net.sf.jasperreports:jasperreports, jasperreports-pdf, jasperreports-fonts and jasperreports-jdt, all with the same
version), declared as in the JRXML design page.
Running it prints styles-demo.pdf: 1 page(s). Reading the PDF back gave the title line, the two lines of markup text, the
heading row and the five books with their prices as 9.90, 14.50, 7.25, 11.00 and 13.75; rendered to an image, the
heading is white on blue, Cosmos and Ulysses are bold red, the even rows (Cosmos, The Selfish Gene) have the pale blue
background and the two Science cells are highlighted in pale yellow. The sections that follow take the file apart. The example
derives from the
JasperReports templates sample and the
markup sample.
Parent styles and the default style
In the template, Heading, Cell and Money declare style="Base" or style="Cell" and only add what differs, so the font
is written once, in Base. Base is also default="true", which is why the title, written without any style, comes out in
DejaVu Sans 9 pt dark grey, and why fontSize="16.0" and bold="true" on the title text are the only things it needs to say.
A change of corporate colour or typeface is then one edit in styles.jrtx.
Three precedence rules explain the output. An attribute on the element beats the style: the Stock cells use Zebra and
override hTextAlign to Right. A style beats its parent: Money sets an alignment that Cell does not have. And a
conditional style beats the style it belongs to while its condition is true, which is the next section. The API of the
resolved result is JRStyle; the loader
class of a design style is
JRDesignStyle.
Conditional styles and alternate row colours
A <conditionalStyle> inside a style holds a <conditionExpression> and the attributes that apply while it evaluates to
true. In 7.0 the attributes are written on the <conditionalStyle> element itself, as the example shows
(<conditionalStyle forecolor="#B00020" bold="true">), and the same child elements as a style (<box>, <pen>,
<paragraph>) are allowed.
Alternate row colours need a conditional style and a counter that says which row this is. The built-in variables for that are
$V{REPORT_COUNT} when the alternation runs through the whole report, $V{PAGE_COUNT} when every page should start with
the same colour, $V{COLUMN_COUNT} for multi-column pages, and a group’s own counter such as $V{CategoryGroup_COUNT}
when each group should start the same way. The Zebra style of the example is exactly the pattern of the official sample:
<style name="Zebra" style="Cell">
<conditionalStyle mode="Opaque" backcolor="#F2F6FC">
<conditionExpression><![CDATA[$V{REPORT_COUNT} % 2 == 0]]></conditionExpression>
</conditionalStyle>
</style>
Derived from the alternate row colours section of the scriptlet sample.
The style that stripes a cell has to be applied to every cell of the row (the example uses Zebra or ZebraMoney on all
four), otherwise the stripe has holes.
Conditions in a style template
The condition of a conditional style that lives in a .jrtx file is restricted. The templates sample states that it must be
a simple reference to a Boolean parameter, field or variable, and 7.0.8 enforces it: the Cell style of the example uses
$F{lowStock} (a Boolean field filled from the isLowStock() getter), and it works. Observed: a template whose condition
was $F{stock} < 5 compiled, but the fill failed with "Interpreted expression … is not a simple
parameter/field/variable/resource message reference". The reason is that a template is shared and its expressions can only be
evaluated against the report that uses it. So the rule of thumb is: put the comparison in the data (a computed boolean field
or a variable) and reference it from the template, or keep that conditional style in the report itself, as Zebra does with
$V{REPORT_COUNT}. The conditional style stays inherited by the report’s own styles, which is why the Zebra rows also turn
red when $F{lowStock} is true.
Style expressions
Since JasperReports 6.20.6 (the release notes of that version describe it as an optional style expression added to report
elements in addition to the static style reference) an element can compute its style name at fill time, with a
<styleExpression> child. The result is the name of a style of the report. The example uses it for the category cell:
<element kind="textField" x="280" y="0" width="100" height="20" style="CategoryPlain">
<styleExpression><![CDATA["Science".equals($F{category}) ? "CategoryHighlight" : "CategoryPlain"]]></styleExpression>
<expression><![CDATA[$F{category}]]></expression>
</element>
It is the right tool when the choice is among several whole styles (a different style per status, per customer tier or per parameter), where a conditional style only switches properties of one style on and off. Three results from 7.0.8 are worth knowing, all observed:
-
The name must be the name of a style declared in the report. A style that exists only in a
.jrtxtemplate failed at fill time with "Style not found". Copy the styles that a style expression can choose into the report. -
The parents of the chosen style must be report styles too. When the style chosen by the expression had a parent that is defined in the template (
style="Cell"), the cell was rendered without the parent’s font and padding, as if the parent did not exist; with a parent defined in the report the chain was resolved. That is whyCategoryPlainrepeats the font and padding instead of inheritingCell. -
When the expression returns
null, the element did not go back to its static style: it kept the style chosen for the previous record (the Fiction rows after a Science row came out highlighted). Always return a name, nevernull, as the example does with"CategoryPlain".
For delayed evaluation of styles the configuration reference has the property net.sf.jasperreports.style.evaluation.time.enabled,
which is false by default in 7.0.8; it was not tested for this page.
Style templates (.jrtx)
When several reports must look alike, the styles live in one external file, by convention with the .jrtx extension. In 7.0
it is an XML file whose root is <jasperTemplate>, without a namespace or a DOCTYPE, as for JRXML. It contains
<style> elements with the same attributes as in a report, and optionally <template> elements that include other
template files, so a library of styles can be layered. The file of the example is the whole format; a layered one looks like:
<jasperTemplate>
<template>base.jrtx</template>
<style name="Strong" style="Base" bold="true"/>
</jasperTemplate>
The nested form was checked: a style in the second file inherited the colour of its parent from the first. Derived from the templates sample.
A report loads a template with a <template> element, whose content is an expression evaluated at fill time:
<template><![CDATA["reports/styles.jrtx"]]></template>
<template><![CDATA[$P{BaseTemplateLocation} + "styles.jrtx"]]></template>
<template class="java.net.URL"><![CDATA[$P{StyleTemplateURL}]]></template>
Only literals and parameters can appear in that expression (fields and variables do not exist yet when templates are loaded),
and a null result makes the engine skip the template. The location is resolved like the location of an image or a
subreport: a URL, a file or a classpath resource, and the class attribute can be java.lang.String, java.io.File,
java.net.URL, java.io.InputStream or net.sf.jasperreports.engine.JRTemplate. The example loads it from the classpath.
A location that cannot be found fails the fill with "Byte data not found at: nope.jrtx" (observed).
Three practical points. The styles of a template are available to the report by name, as parents and as style values, but
see the previous section for style expressions. Keep style names unique across the template library and the report. And a v6 .jrtx is, like a v6 JRXML, not a v7 file:
the v7 Jackson-based format applies to both, and no template conversion was run for this page, so open and save
the old ones in Jaspersoft Studio 7 and diff the result. The loader class is
JRXmlTemplateLoader.
Styled text, HTML and RTF markup
Everything above formats a whole element. To format part of a text (one bold word, a red warning, a superscript) the element
declares a markup language, on the element or on a style: none (the default, plain text), styled, html or rtf. It
works on static texts and, more usefully, on text fields, whose expression result is then parsed as markup.
Styled text is the JasperReports own XML dialect: the content is a fragment in which <style> tags change the font,
colours and decorations of a portion, with the simple tags <b>, <i>, <u>, <font>, <sup>, <sub>, <li>
and <br> and the hyperlink <a>. The tags inside the text still use the old is attribute names, for example
<style isBold="true" forecolor="#1F5FA6"> (this is the one place where isBold is correct in 7.0; the example shows it).
Nested <style> tags inherit from the enclosing one. HTML markup accepts the usual inline tags and is interpreted by the
Swing HTML editor kit. RTF is read with the Swing RTF editor kit. Both are
converted to styled text internally: a short RTF string with a bold and an italic run came out as
styled text with isBold="true" and isItalic="true" runs (checked). The element of the example for HTML is:
<element kind="staticText" x="0" y="28" width="515" height="40" markup="html">
<text><![CDATA[Titles in <font color="#B00020"><b>red</b></font> are <i>low on stock</i>; H<sub>2</sub>O and x<sup>2</sup> need no escapes.]]></text>
</element>
For a text field the same attribute is set and the expression returns the markup string, as in the markup sample
(<element kind="textField" markup="html"> with $P{HtmlText}). Derived from the
markup and
styled text samples.
Two cautions, both observed in 7.0.8. First, the data that reaches a markup field is parsed, so a title or a comment typed by
a user must be escaped before it is used there: with markup="styled" the text a < b & c made the parser log a SEVERE
"Error parsing styled text" and the engine fell back to showing the raw text, and with markup="html" the same text lost the
< and printed a b & c; with markup="none" the text is printed exactly as written, so leave the markup off for anything
that is not meant to carry it. Second, an unknown value such as markup="bogus" fails the fill with "No markup processor
factory specified". The older boolean isStyledText no longer loads.
Paragraphs
The <paragraph> element, available on text elements and styles, controls how a block of text flows. Its attributes are the
line spacing (lineSpacing: Single, 1_1_2, Double, AtLeast, Fixed or Proportional, with lineSpacingSize for the
last three), the indents (firstLineIndent, leftIndent, rightIndent), the vertical space (spacingBefore,
spacingAfter) and the tabs (tabStopWidth for the regular tab width, or <tabStop position="..." alignment="..."> children
with Left, Center or Right alignment). Horizontal and vertical alignment are not part of the paragraph: they are the
hTextAlign and vTextAlign attributes of the element or the style (the Justified value is accepted by hTextAlign). The
styled-text element of the example uses most of them:
<paragraph firstLineIndent="20" leftIndent="10" spacingAfter="4" lineSpacing="Fixed" lineSpacingSize="14.0">
<tabStop position="200" alignment="Right"/>
</paragraph>
In the rendering, the first line is indented and the text after the tab character ends at the right tab stop. The tab in the
example is a literal tab inside the CDATA. Defaults for all reports of a context are set with properties such as
net.sf.jasperreports.default.first.line.indent and net.sf.jasperreports.default.tab.stop.width (default 40), listed in the
paragraph sample; those properties are covered with the other configuration on
Scriptlets, Properties & Extensions. Derived from the
paragraphs sample. One discrepancy: the
templates sample still lists lineSpacing among the attributes of a style, but the 7.0.8 loader has it only on the
paragraph, so write it there.
Borders: box and pen
The old border attributes became children. A <box> holds the padding (or topPadding, leftPadding, bottomPadding,
rightPadding) and the borders; each side has its own pen (<topPen>, <leftPen>, <bottomPen>, <rightPen>) and
a bare <pen> inside the box sets all four. A pen has lineWidth, lineStyle and lineColor. Graphic elements (lines,
rectangles, ellipses) use a direct <pen> child. The Cell style of the example draws a hairline under every row with
a bottom pen, and Heading has padding only:
<box padding="3">
<bottomPen lineWidth="0.5" lineColor="#CCCCCC"/>
</box>
A frame with a full border was shown in the JRXML design page. Because they are children of a style, boxes and pens are
inherited like other attributes, and a <conditionalStyle> can switch them (for instance a red border for a failed check).
Where to go next
-
Fonts & Internationalization for
fontNamevalues that exist in the PDF, embedding and Unicode. -
Groups, Sorting & Filtering for group counters in alternate row colours.
-
Subreports, Datasets, Tables & Lists for styling table components with the same styles.
-
JRXML Report Design for bands and elements.