# CSS

## Rationale

Form Runner has a built-in theme for forms. This page documents how you can make changes to that default style.

CSS stands for [Cascading Style Sheets](https://developer.mozilla.org/en-US/docs/Web/CSS), and is the standard technology to add style to web pages and web applications. Orbeon Forms supports custom CSS files which allows you to change your forms' appearance. This assumes that you have some CSS knowledge.

## Adding your own CSS files

1. Place your CSS file(s) under one of the following recommended locations:
   * `WEB-INF/resources/forms/assets`: CSS for all forms
   * `WEB-INF/resources/forms/APP/assets`: CSS for app name APP
   * `WEB-INF/resources/forms/APP/FORM/assets`: CSS for app name APP and form name FORM
2. Define the `oxf.fr.css.custom.uri` property to point to the file(s) you added. The path points to location under the `WEB-INF/resources` directory.

```xml
<property as="xs:string" name="oxf.fr.css.custom.uri.*.*">
    /forms/acme/assets/acme.css
</property>
```

You can add more than one file, and just separate the paths by whitespace in the property.

Note that the locations suggested are just about how to organize the files for clarity. In addition, if some CSS files apply to specific app or form names, you must specify the app and form name in the property or properties. For example:

```xml
<property as="xs:string" name="oxf.fr.css.custom.uri.APP.*">
    /forms/APP/assets/my-app.css
</property>

<property as="xs:string" name="oxf.fr.css.custom.uri.APP.FORM">
    /forms/APP/assets/my-app.css
    /forms/APP/FORM/assets/my-app-and-form.css
</property>
```

The names `APP`, `FORM`, `my-app.css` and `my-app-and-form.css` are just placeholders for your own app name, form name, and CSS files names.

If a specific property is defined for an app/form, such as `oxf.fr.css.custom.uri.APP.FORM`, only that property is considered and other properties defined only for a given app but without a specific form, such as `oxf.fr.css.custom.uri.APP.*`, will be ignored. This means that you must repeat references to CSS resources in the more specific property if desired. For example above `/forms/APP/assets/my-app.css` is repeated.

\[SINCE Orbeon Forms 2017.1]

In addition to [`oxf.fr.css.custom.uri`](https://doc.orbeon.com/configuration/properties/form-runner#adding-your-own-css), you can also use the following properties, which apply only to the Summary and Detail pages respectively:

* [`oxf.fr.summary.css.custom.uri`](https://github.com/orbeon/orbeon-forms-doc/blob/master/form-runner/styling/form-runner-summary-page.md#adding-your-own-css-files)
* [`oxf.fr.detail.css.custom.uri`](https://github.com/orbeon/orbeon-forms-doc/blob/master/form-runner/styling/form-runner-detail-page.md#adding-your-own-css-files)

### Overriding CSS variables

[\[SINCE Orbeon Forms 2025.1\]](https://github.com/orbeon/orbeon-forms-doc/blob/master/release-notes/orbeon-forms-2025.1.md)

Orbeon Forms provides CSS variables that allow you to customize various styling aspects such as font sizes, font families, font weights, colors, background colors, and border colors. You can override these variables in a custom CSS file referenced using the `oxf.fr.css.custom.uri.*.*` property.

*NOTE: This is a work in progress. More variables will be introduced in future releases. Variable names are subject to change.*

You can view the available CSS variables in the [`form-runner-css-variables.less` LESS file on GitHub](https://github.com/orbeon/orbeon-forms/blob/master/form-runner/jvm/src/main/assets/apps/fr/style/form-runner-css-variables.less).

Example of overriding variables in Form Runner only (not in Form Builder):

```css
.orbeon:not(:has(.fb-main)) {
    --orbeon-base-font-size: 14px;
}
```

To override variables in generated PDF files, use the `@media print` rule:

```css
@media print {
    .orbeon {
        --orbeon-base-font-size: 14px;
    }
}
```

## Authoring CSS

**Disable the minimal and combined resources**. When working on your CSS, you might want to temporarily set the following properties in your `properties-local.xml`, which will disable the combined and minimized resources, so the files and line numbers you see in your browser correspond to what you have on disk.

````
```xml
<property
    as="xs:boolean"
    name="oxf.xforms.minimal-resources"
    value="false"/>

<property
    as="xs:boolean"
    name="oxf.xforms.combine-resources"
    value="false"/>
```

Note that with the [Form Runner Liferay Proxy Portlet](/form-runner/link-embed/liferay-proxy-portlet.md), you cannot disable combined resources as URL rewriting does not work in that case. 
````

**Know which class names to use in your CSS selectors**. We strongly recommend you use the [Chrome Dev Tools](https://developer.chrome.com/devtools) to check which classes are generated by Orbeon Forms. Once you have your CSS working with Chrome and/or Firefox, it is likely that the CSS will work with other modern browsers.

## Orbeon Forms CSS classes

### Prefixes

Orbeon Forms standardizes on the following prefixes for CSS classes:

* `xforms-`: for built-in standard XForms controls
* `xxforms-`: for built-in extension XForms controls
* `fr-`: for Form Runner constructs
* `xbl-`: for XBL components

### Form structure

| Class Name         | Element      | Comment                                    |
| ------------------ | ------------ | ------------------------------------------ |
| `orbeon`           | `<body>`     | body or enclosing embedding element        |
| `xforms-form`      | `<form>`     | enclosing `<form>` handled by Orbeon Forms |
| `fr-view`          |              | enclosing element for the Form Runner view |
| `fr-mode-MODE`     | `.fr-view`   | `MODE`: `new`, `edit`, `view`              |
| `fr-body`          |              | main form body                             |
| `xbl-fr-section`   |              | section                                    |
| `fr-section-title` | `<h2>`, etc. | section title                              |
| `xbl-fr-grid`      |              | grid                                       |

### Grids

| Class Name             | Element    | Comment                                    |
| ---------------------- | ---------- | ------------------------------------------ |
| `fr-grid`              |            | enclosing grid element                     |
| `fr-repeat`            | `.fr-grid` | indicate a repeated grid                   |
| `fr-repeat-single-row` | `.fr-grid` | indicate a repeated grid over a single row |
| `fr-grid-head`         |            | grid head (repeated grids only)            |
| `fr-grid-master-row`   |            | grid header row (repeated grids only)      |
| `fr-grid-body`         |            | grid body (multiple for repeated grids)    |
| `fr-grid-tr`           |            | grid row                                   |
| `fr-grid-th`           |            | grid header cell (repeated grids only)     |
| `fr-grid-td`           |            | grid cell                                  |

### Wizard

| Class Name       | Comment                  |
| ---------------- | ------------------------ |
| `xbl-fr-wizard`  | enclosing wizard element |
| `fr-wizard-toc`  | wizard table of contents |
| `fr-wizard-body` | wizard body              |

### Built-in controls and components

Form controls can either be *built-in* or *components*.

| Class Name        | Element           | Comment                                    |
| ----------------- | ----------------- | ------------------------------------------ |
| `xforms-control`  |                   | built-in control                           |
| `xforms-NAME`     | `.xforms-control` | `NAME`: `input`, `textarea`, etc.          |
| `xbl-component`   |                   | component                                  |
| `xbl-PREFIX-NAME` | `.xbl-component`  | `PREFIX`: `fr`, etc.; `NAME`: `date`, etc. |

### Aspects of a control or component

Built-in controls and components can have extra CSS classes.

| Class Name                             | Comment                                                                                |
| -------------------------------------- | -------------------------------------------------------------------------------------- |
| `xforms-disabled`                      | the control is not visible (non-relevant)                                              |
| `xforms-readonly`                      | the control is readonly                                                                |
| `xforms-type-TYPE`                     | `TYPE`: `date`, `boolean`, `integer`, etc.                                             |
| `xforms-visited`                       | the control has been visited by the user, i.e. tabbed out once                         |
| `xforms-invalid`                       | the control has an error level                                                         |
| `xforms-warning`                       | the control has a warning level                                                        |
| `xforms-info`                          | the control has an info level                                                          |
| `xforms-required`                      | the control is required                                                                |
| `xforms-empty`                         | the control is required and empty                                                      |
| `xforms-filled`                        | the control is required and filled                                                     |
| `xforms-incremental`                   | the control is in incremental mode                                                     |
| `xforms-select1-appearance-APPEARANCE` | `APPEARANCE`: `full`, etc.                                                             |
| `xforms-mediatype-TYPE`                | `TYPE`: `image`, `text` etc.                                                           |
| `xforms-mediatype-TYPE-SUBTYPE`        | `SUBTYPE`: `html`, etc.                                                                |
| `xforms-static`                        | the control is in static-readonly mode                                                 |
| `xforms-field`                         | in static-readonly mode only, outputs which look like fields \[SINCE Orbeon Forms 4.5] |

*NOTE: A data type is not present if the control is `xforms-disabled`.*

`xforms-field` applies to `xf:input`, `xf:secret`, `xf:select`/`xf:select1`. It is used to highlight (by default display a field box around) readonly fields in review and PDF modes.

### Classes on other elements

| Class Name          | Element         | Comment                                           |
| ------------------- | --------------- | ------------------------------------------------- |
| `xforms-label`      |                 | a label                                           |
| `xforms-help`       |                 | a help                                            |
| `xforms-hint`       |                 | a hint                                            |
| `xforms-alert`      |                 | an alert                                          |
| `xforms-active`     | `.xforms-alert` | an active alert                                   |
| `xforms-items`      |                 | radio/checkbox items                              |
| `xforms-selected`   |                 | wrapper around a selected checkbox/radio button   |
| `xforms-deselected` |                 | wrapper around a deselected checkbox/radio button |

## Other considerations

### Separate vs. inline CSS

You can either:

1. Store your CSS is a separate CSS file, which you either provide in addition or that overrides the default CSS provided by Orbeon Forms. For more on this, see the [`oxf.fr.css.custom.uri`](https://doc.orbeon.com/configuration/properties/form-runner#adding-your-own-css) configuration property. This is the recommended technique if your CSS is intended to be shared by several forms.
2. Put your CSS inline, in the form. Uf your CSS is quite short, and specific to a given form (not to be shared amongst forms), this is a possibility. For this, put the rules within your own `<style>` section of the form:

   ```xml
   <xh:title>My Form Title</xh:title>
   <xh:style type="text/css">
       #fr-view .fr-grid .fr-grid-content .my-class input.xforms-input-input {
           width: 8em
       }
   </xh:style>
   ```

*NOTE: Since 2018.1, it is no longer recommended to place any inline CSS, as some servers use the* [*`Content-Security-Policy` header*](https://en.wikipedia.org/wiki/Content_Security_Policy) *to disable inline scripts and CSS. Orbeon Forms 2018.1 doesn't include any inline scripts and CSS anymore by default.*

### Strength of CSS rules

Bootstrap, XForms engine, Form Runner and Form Builder CSS rules are contained within an enclosing `.orbeon` CSS class. This ensures that the Orbeon CSS rules only apply within an element with that class. It also makes Orbeon CSS rules a bit stronger (more *specific*) than before. You might have to update your custom CSS to take this into account.

See [here for more on CSS specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity).

When defining your own CSS, make sure to use a strong selector, so its precedence is higher than CSS provide by Orbeon Forms, e.g. something like:

```css
.orbeon .fr-grid .my-class .xforms-input-input {
    ...rule...
}
```

### Twitter Bootstrap

Since Orbeon Forms 4.0, Form Runner uses [Twitter Bootstrap](https://getbootstrap.com/2.3.2/) for some aspects of its layout and styling.

*NOTE: If you have custom CSS which works with Orbeon Forms 3.9, it is likely that you will have to update it to work with Orbeon Forms 4.0.*

## Configuring the presentation of automatic PDF output

See [Automatic PDF](https://doc.orbeon.com/form-runner/styling/automatic-pdf).

## Changing the page width

The [default width with Bootstrap](http://getbootstrap.com/2.3.2/scaffolding.html) is 940px, but you can change this by overriding the Bootstrap/Orbeon CSS. As usual, to do so, we recommend you use a tool like the [Chrome DevTools](https://developer.chrome.com/devtools) to find the exact rules you need to override in your environment. For instance, with an out-of-the-box Orbeon Forms deployed as a servlet, you can set the width to 720px with:

```css
.orbeon .container, .orbeon .span12 { width: 720px }
```

## See also

* [Grids CSS](https://doc.orbeon.com/form-runner/styling/grids)
* [Automatic PDF](https://doc.orbeon.com/form-runner/styling/automatic-pdf)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://doc.orbeon.com/form-runner/styling/css.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
