Table to div layout migration

View the index of available developer guides

This is a documentation for the incoming feature in the Jenkins core. See JENKINS-56109: Change Jenkins configuration UI from tables to divs for details.

Jenkins core will change its form layout from 'table' to 'div' soon.

All core taglib’s and views were updated in jenkins#3895 as part of JENKINS-56109.

For 99% of plugins they do not require any changes at all as they just use the standard jelly tags in Jenkins for their forms, such as f:entry, f:textbox, f:checkbox.

Examples of area which may require changes

Below are some areas that may require you to adjust the form layout or JavaScript in your plugin:

  • Adding td / tr elements directly instead of using the f:entry tag, e.g. config-rotator-plugin#2

  • Custom JavaScript that is brittle to the Jenkins form UI layout. We’ve done our best to introduce shims, to not cause breakage here, but if you have written JavaScript that is reliant on the DOM structure you may need to make adjustments, take a look at the JavaScript changes in jenkins#3895.

  • Forking jelly taglibs from core and extending them, e.g. multiple-scms-plugin#25, it would be good to contribute fixes or enhancements to core rather than doing this where possible.

  • Using tables in the plugin for layout, e.g. jenkins-artifactory-plugin#266 and matrix-auth-plugin#83.

Maintaining support for tables and div layout

There is a jelly property set on Jenkins instances that use div’s for form layout called divBasedFormLayout, so you can adapt your plugin UI based on the presence of this property.

Jelly example:

<d:taglib uri="local">
  <d:tag name="blockWrapper">
            <j:when test="${divBasedFormLayout}">
                <table style="width:100%">


This will use a table on Jenkins instances that don’t have divBasedFormLayout and will use a div when it is set.

Note: You will likely need more tags to adapt the tr and td tags to divs see multiple-scms-plugin#25 for a full example.

Groovy example:

blockWrapper {
    p('Hello, World!')

def blockWrapper(Closure closure) {
    if (context.getVariableWithDefaultValue("divBasedFormLayout", "false") == "true") {
        div() {
    } else {
        table(style: "width: 100%") {

I still need more help?

Contact the UX sig on Gitter or on the mailing list.