Odoo Development

How to Add Colors to List View Rows and Cells in Odoo

Use decoration-* attributes to colour-code rows and individual cells in Odoo list views based on field values — with expression syntax, all decoration types, and a migration note for the tree → list rename. Verified for Odoo 18 & 19.

iWesabe Editorial TeamSeptember 9, 20217 min read

Odoo list views support row-level and cell-level visual styling via `decoration-*` attributes. These attributes accept the same Python expression syntax used by `invisible` and `readonly` — they evaluate against the current row's field values and apply a Bootstrap text class when the expression is truthy. This makes it straightforward to highlight overdue records in red, confirmed orders in green, or draft entries in italic without writing any custom JavaScript.

How List View Row Colouring Works

Decoration attributes are placed on the `` element (formerly ``) to colour entire rows, or on individual `` elements inside the list to colour only that cell. Each attribute takes a Python expression string. When the expression evaluates to `True` for a given record, Odoo adds the corresponding Bootstrap CSS class to the row or cell element.

Decoration Attributes Reference

All decoration-* attributes — Odoo 16–19
AttributeCSS class appliedVisual effectCommon use case
decoration-successtext-successGreen textConfirmed, done, paid records
decoration-warningtext-warningOrange / amber textPending, in-progress, needs attention
decoration-dangertext-dangerRed textOverdue, cancelled, blocked, errors
decoration-infotext-infoBlue / cyan textInformational, draft, new records
decoration-mutedtext-mutedGrey / dimmed textArchived, inactive, cancelled records
decoration-primarytext-primaryPrimary brand colourHighlighted or selected records
decoration-bffw-bold (font-weight bold)Bold textImportant rows, totals, high-priority
decoration-itfst-italic (font-style italic)Italic textDraft, estimated, or provisional records

Row-Level Decoration (Entire Row)

xml
<!-- Row-level decoration on the <list> element -->
<!-- Each decoration-* attribute colours ALL cells of a matching row -->
<list decoration-success="state == 'sale'"
      decoration-warning="state == 'draft'"
      decoration-danger="date_deadline and date_deadline &lt; current_date"
      decoration-muted="state == 'cancel'"
      decoration-bf="priority == '2'"
      decoration-it="state == 'draft'">

    <field name="name"/>
    <field name="partner_id"/>
    <field name="date_deadline"/>
    <field name="amount_total"/>
    <field name="state"/>
    <field name="priority" column_invisible="True"/>
    <!-- ↑ Include fields used in expressions even if not shown as columns -->
</list>

Cell-Level Decoration (Individual Field)

You can also apply `decoration-*` to an individual `` element inside the list. The decoration then applies only to that column's cell, leaving the rest of the row unstyled. This is useful when you want to highlight a specific value — such as making overdue dates red while keeping the row itself neutral.

xml
<!-- Cell-level decoration — only that field's cell is styled -->
<list>
    <field name="name"/>
    <field name="partner_id"/>

    <!-- Colour the deadline cell based on urgency -->
    <field name="date_deadline"
           decoration-danger="date_deadline and date_deadline &lt; current_date"
           decoration-warning="date_deadline and date_deadline == current_date"/>

    <!-- Highlight the amount when it exceeds a threshold -->
    <field name="amount_total"
           decoration-success="amount_total &gt;= 10000"
           decoration-warning="amount_total &gt; 0 and amount_total &lt; 10000"
           decoration-muted="amount_total == 0"/>

    <field name="state"
           decoration-success="state == 'sale'"
           decoration-danger="state == 'cancel'"
           decoration-it="state == 'draft'"/>
</list>

The tree → list Rename (Odoo 16)

tree vs. list element across Odoo versions
Odoo version<tree> element<list> elementdecoration-* supportRecommendation
Odoo 15✓ Canonical name✗ Not recognised✓ Supported on <tree>Use <tree>
Odoo 16✓ Alias (works)✓ New canonical name✓ Supported on bothUse <list>, migrate <tree>
Odoo 17✓ Alias retained✓ Canonical✓ Supported on bothUse <list>
Odoo 18 & 19✓ Alias retained✓ Canonical✓ Supported on bothUse <list>

Combining Multiple Decorations

You can combine colour decorations with font decorations on the same element. When multiple decoration expressions are true simultaneously, all matching CSS classes are applied. A common pattern is bold + colour for priority records.

xml
<!-- Bold + red for high-priority overdue records -->
<list decoration-danger="priority == '2' and date_deadline and date_deadline &lt; current_date"
      decoration-bf="priority == '2'"
      decoration-warning="state == 'draft'"
      decoration-it="state == 'draft'"
      decoration-muted="state == 'cancel'">

    <field name="name"/>
    <field name="date_deadline"/>
    <field name="state"/>
    <field name="priority" column_invisible="True"/>
</list>

Using current_date in Decoration Expressions

`current_date` is a special variable available in list view decoration expressions (and in domain strings). It holds today's date as a `datetime.date` object, allowing date comparisons without hardcoding values. It is also available as a string in ISO format (`'YYYY-MM-DD'`) when used in domain strings.

xml
<!-- Highlight overdue records (deadline passed) in red -->
<!-- Highlight due-today records in orange -->
<!-- Highlight upcoming (within 7 days) in info blue -->
<list
  decoration-danger="date_deadline and date_deadline &lt; current_date"
  decoration-warning="date_deadline and date_deadline == current_date"
  decoration-info="date_deadline and date_deadline &gt; current_date">
    <field name="name"/>
    <field name="date_deadline"/>
</list>

Troubleshooting

Common decoration issues and fixes
SymptomLikely causeFix
Decoration never applies — rows remain unstyledField used in expression is not loaded (not included as a <field> element in the list)Add the field with column_invisible="True" so Odoo loads the value for expression evaluation.
XML parse error when using < or > in expression< and > are reserved XML characters and must be escaped inside attribute valuesReplace < with &lt; and > with &gt; inside the decoration attribute string.
Decoration applies to wrong rows (always true or always false)Expression references a field whose value is always the same (e.g. a relational ID instead of the selection value)Check the field type: selection fields use string values like 'done', not integers. Many2one fields compare IDs (integers), not display names.
Two colour decorations both active — unexpected colour shownTwo decoration expressions are simultaneously true; CSS specificity determines which winsMake the expressions mutually exclusive using 'and not' or 'and state != ...' to ensure only one is true at a time.
decoration-bf or decoration-it not visibleA custom theme CSS overrides Bootstrap's fw-bold or fst-italic classesInspect the row element in browser dev tools to confirm the class is added. If overridden, add a custom CSS rule in your module's SCSS with !important or higher specificity.

Version Notes

List view decoration across Odoo versions
Odoo versionKey changes affecting list view decoration
Odoo 15decoration-* attributes supported on <tree>. attrs used for row visibility (deprecated in Odoo 16). current_date available.
Odoo 16<tree> renamed to <list> (alias retained). attrs deprecated — use invisible on <field>. column_invisible introduced for hiding columns.
Odoo 17attrs removed. <list> canonical; <tree> retained as alias. decoration-* API unchanged. Bootstrap 5 classes (fw-bold, fst-italic) replace older Bootstrap 4 names for decoration-bf/decoration-it.
Odoo 18 & 19No breaking changes to decoration-* attributes. <list> remains canonical, <tree> alias still works.

Need Custom List View Styling or a Full Odoo Module Upgrade?

Our Odoo-certified developers handle view customisation, module upgrades from Odoo 15 to 18/19, and full compliance verification for Saudi businesses — ZATCA, GOSI, and PDPL.

WhatsApp

Frequently Asked Questions

Can I use decoration-* on buttons or other elements inside a list view?
`decoration-*` is supported on the `` element itself (row-level) and on `` elements inside the list (cell-level). It is not supported on `` elements inside a list — use the `invisible` attribute on buttons to show or hide them based on record state instead.
Why does decoration-danger on date_deadline not work when the field is empty?
An empty date field evaluates to `False`. An expression like `date_deadline < current_date` raises an error when `date_deadline` is `False` because you cannot compare `False` with a date. Always guard date comparisons with a truthy check: `date_deadline and date_deadline < current_date`. The `and` short-circuits — if `date_deadline` is `False`, the expression immediately evaluates to `False` without attempting the comparison.
Can I apply a background colour instead of just text colour?
The built-in `decoration-*` attributes only apply Bootstrap text colour classes (`text-success`, `text-danger`, etc.) — not background colours. For background colours, you need a custom CSS class. Add a class to the row via a custom `decoration-*` style (this is not natively supported) or add a custom SCSS file in your module that targets the row's Bootstrap class. A common workaround is to accept text-colour-only styling, which is consistent with Odoo's standard UI.
Is decoration-* available in Kanban or form views?
No. `decoration-*` attributes are specific to list (tree) views. Kanban views have their own colour mechanism via the `color` field on the Kanban card and a `` attribute. Form views do not have row-level decoration — use `invisible` and `readonly` for conditional field styling, or apply a custom CSS class via a widget.
Can I combine decoration-bf (bold) with a colour like decoration-danger?
Yes. Colour decorations (`decoration-success`, `decoration-danger`, etc.) and font decorations (`decoration-bf`, `decoration-it`) are independent — they apply different CSS properties and do not conflict. A row can be both bold and red simultaneously. You can even use different expressions: bold for high-priority records, red for overdue ones, so a high-priority overdue record gets both.
My list view has many decoration conditions and is getting hard to read. Is there a cleaner approach?
Move the decoration logic into a stored computed field on the model — for example, a `Char` field named `row_color` that returns `'danger'`, `'warning'`, `'success'`, or `''` based on the record's state and dates. Then use a single `decoration-danger="row_color == 'danger'"` etc. on the `` element. This keeps view XML clean and puts the logic where it belongs — in the Python model — where it is easier to test and reuse.
iWesabe Editorial Team

iWesabe Editorial Team

Practitioner insights on Odoo ERP, ZATCA compliance, and Saudi enterprise digital operations — written by iWesabe's consulting, finance, and engineering teams.

About iWesabe

Related Articles