To enable CSS support, edit the field options and press the … button next to the HTML option:

This opens a dialog with a set of options, one of which is CSS and provides the ability to edit the stylesheet. A stylsheet contains a list of properties that map to InDesigns Scripting DOM properties.
Working with Text
The InsertionPoint DOM object is used for text based tags to process the CSS. Any writable property can be set. Collections are supported as shown in the following example:
1 2 3 | <p style = "characters[all].fillcolor:red;">This is the first paragraph</p> <p style = "characters[all].fillcolor:green;">This is the second paragraph</p> <p style = "characters[all].fillcolor:blue;">This is the third paragraph</p> |
If the HTML contained no formatting:
1 2 3 | <p>This is the first paragraph. It introduces the topic.</p> <p>This is the second paragraph. It provides more details and examples.</p> <p>This is the third paragraph. It concludes the discussion and wraps up the ideas.</p> |
Use a stylesheet to apply properties via a basic CSS parser. For example. nth-of-type is used here to pick out each of the first 3 paragraphs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | p:nth-of-type(1) { characters[all].fillcolor:red; } p:nth-of-type(2) { characters[all].fillcolor:green; spacebefore: 4pt; } p:nth-of-type(3) { characters[all].fillcolor:blue; texts[0].appliedParagraphStyle:example; } |
Some properties, such as appliedFont can apply properties delimited by a tab. A meta character sequence should he used for the tab:
1 | <lu style = "appliedfont:Baskerville^tItalic;">Baskerville Italic</p></ul> |
Working with Images
The Rectangle DOM object is used for <img> tags:
1 2 3 4 5 6 7 8 9 10 11 12 13 | img { fillcolor : orange; strokecolor : yellow; strokeweight: 5pt; topleftcornerradius : 20pt; toprightcornerradius : 20pt; toprightcorneroption : rounded_corner; topleftcorneroption : rounded_corner; transparencysettings.dropshadowsettings.mode : drop; filltint : 90; width : 1cm; height: 1cm; }; |
In addition to the DOM properties, EasyCatalog also adds width, height and fit as a writable properties. fit accepts contentproportionally and frametocontent.
It’s also possible to manipulate the text inside an image tag, such as forcing the image into a new page or column.
1 2 3 | img { parent.insertionPoints[0].contents : column_break; } |
However because this manipulation is inside the link, the field content is changed so flagged as an error as it modifies content. Modifying link content is generally not recommended for this reason. The following example turns the Rectangle object into a TextFrame and inserts text into it. Meta character sequences are used to insert a paragraph break:
1 2 3 4 5 6 7 8 | img { contenttype : text_type; texts[0].contents : Hello^pWorld; texts[0].justification : center_align; textframePreferences.verticalJustification : center_align; fillcolor : orange; filltint : 50; } |
Working with Tables
When working with tables, the <table> tag uses a Table object. The <tr> tag uses a Row object and the <td><th> tag uses a Cell object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | <body> <table> <thead> <tr> <th>ID</th> <th>Name</th> <th>Age</th> <th>City</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>Alice</td> <td>25</td> <td>New York</td> </tr> <tr> <td>2</td> <td>Bob</td> <td>30</td> <td>London</td> </tr> <tr> <td>3</td> <td>Charlie</td> <td>28</td> <td>Paris</td> </tr> <tr> <td>4</td> <td>Diana</td> <td>32</td> <td>Berlin</td> </tr> <tr> <td>5</td> <td>Edward</td> <td>27</td> <td>Tokyo</td> </tr> </tbody> </table> </body> </html> |
Row Properties
To color the header and an alternating rows, the following stylesheets can be defined. The properties here belong to a Row DOM object. Any property that takes a color can also take a css style color name in addition to a named swatch. These are automatically created by EasyCatalog:
1 2 3 4 5 6 7 8 9 10 11 12 | table tr:nth-child(even) { fillcolor: #f2f2f2; /* light gray */ } table tr:nth-child(odd) { fillcolor: #ff0000; /* red */ } th { fillcolor: #000000; /* black */ cells[all].texts[0].fillColor : white; } |
Cell Properties
For <td> and <th> tags, a Cell object is used, so properties for the Cell DOM object can be assigned. if the HTML contained a class attribute, eg:
1 | <td class = "age">30</td> |
Then a stylesheet can pick this out:
1 2 3 | td.age { fillcolor: green; } |
Setting a cell width:
1 2 3 | td { width: 2cm; } |
Table Properties
The following HTML contains 2 tables with id attributes to identify them:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | <body> <table id="people"> <thead> <tr> <th>ID</th> <th>Name</th> <th>Age</th> <th>City</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>Alice</td> <td>25</td> <td>New York</td> </tr> <tr> <td>2</td> <td>Bob</td> <td>30</td> <td>London</td> </tr> <tr> <td>3</td> <td>Charlie</td> <td>28</td> <td>Paris</td> </tr> <tr> <td>4</td> <td>Diana</td> <td>32</td> <td>Berlin</td> </tr> <tr> <td>5</td> <td>Edward</td> <td>27</td> <td>Tokyo</td> </tr> </tbody> </table> <table id="prices"> <thead> <tr> <th>Order ID</th> <th>Product</th> <th>Quantity</th> <th>Price ($)</th> <th>Status</th> </tr> </thead> <tbody> <tr> <td>1001</td> <td>Laptop</td> <td>2</td> <td>1200</td> <td>Shipped</td> </tr> <tr> <td>1002</td> <td>Smartphone</td> <td>5</td> <td>800</td> <td>Processing</td> </tr> <tr> <td>1003</td> <td>Headphones</td> <td>10</td> <td>150</td> <td>Delivered</td> </tr> <tr> <td>1004</td> <td>Monitor</td> <td>3</td> <td>300</td> <td>Pending</td> </tr> <tr> <td>1005</td> <td>Keyboard</td> <td>7</td> <td>75</td> <td>Shipped</td> </tr> </tbody> </table> </body> </html> |
The following stylesheets targets specific tables using their ID:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #people { width: 8cm; } #people td { cells[all].fillcolor: blue; cells[all].filltint: 10; } #people th { cells[all].fillcolor: blue; cells[all].filltint: 40; } #prices { width: 10cm; } #prices td { cells[all].fillcolor: red; cells[all].filltint: 10; } #prices th { cells[all].fillcolor: red; cells[all].filltint: 40; } |
This produces the following output:

Some HTML properties conflict with regular HTML properties, such as:
1 | <table border="1" cellpadding="1" cellspacing="1" style="width:500px;”> |
To stop the properties defined by the style node getting applied you can target the node and use the following:
1 2 3 | table { all : unset; /* this stops any class or styles getting applied */ } |
Lua Based Property Content
When a property includes [[ and ]], the text enclosed is treated as Lua code, and the result of the code is substituted into the property. A field function can be used within this Lua code to access the contents of any field associated with the current table, cell, row, text range. If the field does not exist, the field function will return nil.
For example, the following code checks the content of the availability field and applies colors to body cells based on its value:
1 2 3 4 5 6 | body cell { fillcolor: [[ if field('availability') == "Now" then return "Red" end return "Green" ]]; } |
Lua Based DOM manipulation
A special lua property exists that enables execution of lua based manipulation of the DOM. The self object is the DOM object that matches the CSS target, so Cell, Table, Row, Column or Text.
For example, here we want a table to be 120 mm wide, with the last column always 35 mm. All other column widths are distributed evenly in the remaining space.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | table { lua: -- Define the target table width local targetTableWidthInPoints = topoints("120mm") -- Last column should be a fixed width local widthOfLastColumnInPoints = topoints("35mm") -- Distribute the remaining space equally -- by setting each column width local totalWidthOfOtherColumns = targetTableWidthInPoints - widthOfLastColumnInPoints local colCount = self:columns():count() local otherColumnWidth = totalWidthOfOtherColumns / (colCount-1) for col = 1, colCount-1 do self:columns():item(col-1):width(otherColumnWidth .. "pt") end self:columns():item(colCount-1):width(widthOfLastColumnInPoints .. 'pt') -- semi colon needed to end the property content ; } |
The following applies color to a text field using the field function, but also uses the lua property to apply an underline using self. All enhanced HTML formatted fields get a surrounding <body> tag by default.
1 2 3 4 5 6 7 8 9 | body { fillcolor: [[ if field('availability') == "Now" then return "Red" end return "Green" ]]; lua: [[ self:underline(field('Availability') == 'Now') ]]; } |
Sharing CSS between fields
If the CSS just contains the name of a file in the data sources scripts folder, this is loaded and used.
Supported Selectors
The CSS parser is basic and evaluates whether a single HTML-like node matches a given CSS selector. The following selector types are supported:
1. Tag Selector
- Matches elements by their tag name.
- Examples:
div— matches all<div>elements*— wildcard, matches any element
2. ID Selector
- Matches elements by their
idattribute. - Syntax:
#idName - Example:
#main— matches element withid="main"
3. Class Selector
- Matches elements by their
classattribute. - Syntax:
.className - Multiple classes can be chained:
.foo.bar - Matches elements containing all specified classes.
4. Attribute Selectors
- Match elements based on attribute values.
- Supported operators:
[attr=value]— exact match[attr~=value]— whitespace-separated list containsvalue[attr|=value]— equalsvalueor starts withvalue-[attr^=value]— starts withvalue[attr$=value]— ends withvalue[attr*=value]— containsvalue
5. Structural Pseudo-Classes
Target elements based on their position or type among siblings:
| Pseudo-Class | Description |
|---|---|
:first-child | Matches the first child of its parent |
:last-child | Matches the last child of its parent |
:nth-child(n) | Matches the nth child (1-based) of its parent |
:nth-last-child(n) | Matches the nth child from the end |
:first-of-type | Matches the first element of its type among siblings |
:last-of-type | Matches the last element of its type among siblings |
:nth-of-type(n) | Matches the nth element of its type among siblings |
:nth-last-of-type(n) | Matches the nth element of its type from the end |
:only-child | Matches the only child of its parent |
:only-of-type | Matches the only element of its type among siblings |
:empty | Matches elements with no children (no elements, text, or comments) |
Note: nth-child and similar formulas support CSS-style numeric formulas (e.g., 2, 3n+1, odd, even)