Skip to content

CSS and HTML

HTML markup and CSS styling are first-class citizens in XTS. You can use CSS to style XTS layout elements (like <Paragraph>) and HTML content within <HTML> blocks. If you know web CSS, you already know most of what you need.

CSS stylesheets

Inline stylesheets

Define CSS rules directly in your layout file:

<StyleSheet>
    p {
        font-family: serif;
        font-size: 12pt;
        line-height: 1.4;
    }
    .highlight {
        color: firebrick;
    }
</StyleSheet>

External stylesheets

For larger projects, keep CSS in separate files:

<StyleSheet href="styles/main.css"/>
<StyleSheet href="styles/typography.css"/>

You can include as many as you need. They’re processed in order, so later rules override earlier ones (normal CSS cascade).

CSS classes

Apply classes with the class attribute – works on both XTS elements and HTML elements:

<StyleSheet>
    .product-title {
        font-size: 18pt;
        font-weight: bold;
        color: darkblue;
    }
    .price {
        font-family: monospace;
        color: green;
    }
</StyleSheet>

<PlaceObject>
    <TextBlock>
        <Paragraph class="product-title">
            <Value select="@name"/>
        </Paragraph>
        <Paragraph class="price">
            <Value select="concat(@price, ' EUR')"/>
        </Paragraph>
    </TextBlock>
</PlaceObject>

Multiple classes are space-separated: class="centered bold large".

Inline styles

For one-off styling:

<Paragraph style="color: red; font-weight: bold;">
    <Value>Warning!</Value>
</Paragraph>

Supported CSS properties

The CSS Properties Reference lists every property, value and selector that XTS understands, and the at-rules for fonts, colors and page margin boxes.

HTML content

The <HTML> element lets you include HTML markup:

<PlaceObject>
    <TextBlock>
        <HTML>
            <p>A wonderful <b>serenity</b> has taken possession
               <i>of my <b>entire soul,</b></i> like these sweet mornings.</p>
        </HTML>
    </TextBlock>
</PlaceObject>

Supported HTML elements

Element Description
<p> Paragraph
<b>, <strong> Bold
<i>, <em> Italic
<u>, <ins> Underline
<s>, <del> Strike-through
<span> Inline container
<br> Line break
<a> Link
<ul>, <ol>, <li> Lists
<table>, <tr>, <td>, <th> Tables
<h1> – <h6> Headings
<div> Block container
<pre>, <code> Preformatted / code
<img> Image

Floats

float: left and float: right set an image or a block beside the text, and the lines flow around it. This works in <HTML> inside a <TextBlock> as well as in a <Flow>:

<StyleSheet>
    img.left { float: left; width: 20mm; }
    .facts   { float: right; background-color: #eef3f7; padding: 2mm 3mm; }
</StyleSheet>

<HTML>
    <p><img class="left" src="lens.svg"/>The heart of the tower is not
       the lamp but the lens around it. ...</p>
    <div class="facts"><b>Skerry Point</b><br/>Tower: 32 m<br/>Range: 22 nautical miles</div>
    <p>The rings are ground so precisely that ...</p>
</HTML>

text flowing around a floated image and a box

An SVG image at the start of a paragraph floats at its first line. The box of facts has no width and shrinks to its longest line.

An image floats when it stands at the very start of a paragraph or as a block of its own; PNG, JPEG, PDF and SVG files behave alike. A float without a width is as wide as its longest line. The space between float and text is the float’s margin on that side, or -bag-float-gutter (9pt by default) where it has none, and clear: both starts a block below the floats before it. The how-to Wrap text around an image on boxesandglue.dev goes through the details and the limits; they hold for XTS as well.

Dynamic content with expand-text

By default, {...} expressions are not evaluated inside HTML. Enable them with expand-text="yes":

<SetVariable variable="product" select="'Premium Widget'"/>

<PlaceObject>
    <TextBlock>
        <HTML expand-text="yes">
            <p><b>{$product}</b></p>
            <p>Page: {sd:current-page()}</p>
        </HTML>
    </TextBlock>
</PlaceObject>

For literal curly braces, double them: {{ and }}.

Loading HTML from data

Pull HTML from your data file using select:

<!-- Reference HTML nodes directly -->
<HTML select="/data/htmlcontent"/>

<!-- Or decode raw HTML strings -->
<HTML select="sd:decode-html(description)"/>

Combining XTS elements and HTML

Mix freely within a <TextBlock>:

<TextBlock>
    <Paragraph>
        <Value>Introduction: </Value>
        <HTML><b>Important</b> information follows.</HTML>
    </Paragraph>
    <HTML>
        <ul>
            <li>First item</li>
            <li>Second item</li>
        </ul>
    </HTML>
</TextBlock>

Practical example

A complete product catalog card:

<StyleSheet>
    body { font-family: serif; font-size: 11pt; }
    h1 { font-size: 18pt; color: darkblue; margin-bottom: 12pt; }
    .product { border: 1pt solid #ccc; padding: 10pt; margin-bottom: 10pt; }
    .product-name { font-weight: bold; font-size: 14pt; }
    .price { color: green; font-feature-settings: "tnum"; }
    .description { font-style: italic; color: #666; }
</StyleSheet>

<Record match="products">
    <PlaceObject>
        <TextBlock>
            <HTML><h1>Product Catalog</h1></HTML>
            <ForAll select="product">
                <HTML expand-text="yes">
                    <div class="product">
                        <p class="product-name">{@name}</p>
                        <p class="price">{@price} EUR</p>
                        <p class="description">{description}</p>
                    </div>
                </HTML>
            </ForAll>
        </TextBlock>
    </PlaceObject>
</Record>