1. Eclipse and declarative styling

The visual appearance of your Eclipse application can be styled using external files based on the CSS 2.1 standard. CSS selectors used in Eclipse relate to widgets or other elements, for example, via predefined pseudo classes. Non-standard properties are prefixed with either swt- or eclipse-.

The following CSS file defines the styling for an Eclipse application.

@import url("platform:/plugin/com.vogella.eclipse.css/css/fonts.css");

Label, Button {
    background-color: #e0e0e0;
    color: black;
}

Table, Tree {
    background-color: #f2f2f2;
    swt-header-background-color: #d0d0d0;
    swt-header-color: black;
    color: black;
}

Composite Text {
    background-color: white;
    color: black;
}

SashForm {
    background-color: #c1d5ef;
}

.MTrimBar {
    color: white;
}

Shell, Composite, .MTrimBar {
    background-color: #e0e0e0;
}

CTabItem:selected {
    background-color: #d0d0d0;
    color: black;
}

CTabFolder {
    /* the swt-* tab properties only work with this renderer */
    swt-tab-renderer: url('bundleclass://org.eclipse.e4.ui.workbench.renderers.swt/org.eclipse.e4.ui.workbench.renderers.swt.CTabRendering');
    swt-selected-tab-highlight: #8a8a8a;
    swt-selected-highlight-top: false;
    swt-tab-outline: #c8c8c8;
    swt-outer-keyline-color: #c8c8c8;
}

CTabFolder.active {
    swt-selected-tab-highlight: #2160bb;
}

SWT has certain limitations concerning component styling. These are caused by restrictions of the underlying operating system or of SWT itself. For example, it is not possible to style menus because this is not supported by SWT. Each Eclipse release reduces these limitations.

In most cases, you can overcome the styling restrictions of SWT in RCP applications. For example, you can use NatTable to display your tables. NatTable is a flexible table and tree implementation that allows full styling. For other components, you can use custom widgets or a PaintListener to draw on top of the widget.

NOTE: To turn off styling completely, pass -cssTheme none as a launch argument.

2. Styling using themes

Styling can be defined in two ways:

  • themes, which allow dynamic theme switching

  • the applicationCSS property, which defines a fixed styling

You define themes via extensions for the org.eclipse.e4.ui.css.swt.theme extension point in the plugin.xml file. Such an extension defines an ID for the theme and a pointer to the CSS file.

You define the default theme via the cssTheme property in your org.eclipse.core.runtime.products extension.

You need to set cssTheme, otherwise the theming service is not available at runtime.

The Eclipse platform provides the theme service as an instance of the IThemeEngine interface. Via this instance, you can change the active theme at runtime. The following handler switches the theme.

package com.vogella.tasks.ui.handlers;

import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.css.swt.theme.ITheme;
import org.eclipse.e4.ui.css.swt.theme.IThemeEngine;

public class ThemeSwitchHandler {
    private static final String DEFAULT_THEME = "com.vogella.eclipse.css.default";
    private static final String RAINBOW_THEME = "com.vogella.eclipse.css.rainbow";

    @Execute
    public void switchTheme(IThemeEngine engine) {
        ITheme activeTheme = engine.getActiveTheme();
        String nextTheme = activeTheme != null && DEFAULT_THEME.equals(activeTheme.getId())
                ? RAINBOW_THEME
                : DEFAULT_THEME;
        // true persists the choice so that it is restored on restart
        engine.setTheme(nextTheme, true);
    }
}

You can also specify a fixed styling of your application via the applicationCSS property of the org.eclipse.core.runtime.products extension in the plugin.xml file.

The value of the applicationCSS property points to your CSS file via a URI. The URI follows the platform:/plugin/BundleSymbolicName/path/file convention. The following example shows such a URI.

platform:/plugin/com.vogella.tasks.ui/css/default.css

The screenshot shows an example of the plugin.xml file with a defined applicationCSS property.

Extensions tab with the applicationCSS property of the product

The corresponding file looks like this.

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>

 <extension
   id="product"
   point="org.eclipse.core.runtime.products">
  <product
     application="org.eclipse.e4.ui.workbench.swt.E4Application"
     name="to-do">
   <property
     name="appName"
     value="to-do">
   </property>
   <property
     name="applicationCSS"
     value="platform:/plugin/com.vogella.tasks.ui/css/default.css">
   </property>
  </product>
 </extension>

</plugin>

3. CSS support for standard Eclipse elements

3.1. CSS attributes and selectors

CSS selectors used in Eclipse are identifiers that relate to widgets or other elements, for example, predefined pseudo classes. Non-standard properties are prefixed with either swt- or eclipse-.

You can use the swt-data-class attribute to query the class hierarchy of an object. For example, the following selector identifies all Shell elements from a JFace dialog.

Shell[swt-data-class ~= 'org.eclipse.jface.dialogs.Dialog'] {
    background-color: rgb(236, 245, 250);
    swt-background-mode: force;
}

The CSS attributes for SWT widgets that can be styled are listed in the CSS documentation of the Eclipse platform.

Model elements of your Eclipse application, for example, MPartStack or MPart, can be used as selectors for styling. The CSS selectors are based on the Java classes for the model elements. Some examples are given in the following table.

Table 1. Model elements and CSS selectors
Model element CSS selector

MPart

.MPart

MPartStack

.MPartStack

MPartSashContainer

.MPartSashContainer

For example, you can hide the minimize and maximize buttons of an MPartStack via the following CSS rule.

.MPartStack {
    swt-maximize-visible: false;
    swt-minimize-visible: false;
}

3.2. CSS pseudo classes in Eclipse

Eclipse supports CSS pseudo classes, but these are disabled by default. You can enable them via the Java system property org.eclipse.e4.ui.css.dynamic=true.

The following table lists several of the available pseudo classes.

Table 2. CSS pseudo classes in Eclipse
CSS pseudo class Description

Button:checked

Selects checked buttons.

:active

For example, Shell:active selects the active shell.

:selected

Allows you to style a selected element, for example, a part in a part stack.

Button {
    background: yellow;
}

Button:checked {
    background: blue;
}

Button:disabled {
    background: green;
}

You can test the effect of this CSS with the following code.

Button pushButton = ButtonFactory.newButton(SWT.PUSH).text("Press me").create(parent);
Button checkButton = ButtonFactory.newButton(SWT.CHECK).text("Press me")
        .onSelect(e -> pushButton.setEnabled(!pushButton.getEnabled())).create(parent);
checkButton.setSelection(true);
The push button keeps the style it received when it was created. The engine only restyles a widget while the application runs for the :focus, :hover, :checked and :active states, and only if the application is started with -Dorg.eclipse.e4.ui.css.dynamic=true. :enabled, :disabled and :visible are read from the widget whenever styles are applied, but a setEnabled() call does not start such a run, so the green style only shows if the button is already disabled when it is created. See Pseudo classes for the full list.

See Pseudo classes in SWT for the project documentation.

3.3. Styling based on a CSS class or ID

You can assign a CSS ID or class to widgets in your source code and use them as selectors for styling. An identifier is supposed to be unique, while a class can be assigned to several elements.

The following example demonstrates how to set an identifier and a class on SWT widgets.

@Inject
IStylingEngine engine;

// more code....

Label label = new Label(parent, SWT.NONE);
Text text = new Text(parent, SWT.BORDER);

// set the ID, must be unique in the same window
engine.setId(label, "MyCSSTagForLabel");

// set the class, can be used several times
engine.setClassname(text, "error");

The setId and setClassname methods use the setData method on the widget. You can also use the SWT setData method directly, as demonstrated in the following example.

// more code....

Label label = new Label(parent, SWT.NONE);
Text text = new Text(parent, SWT.BORDER);

// set the ID, must be unique in the same window
label.setData("org.eclipse.e4.ui.css.id", "MyCSSTagForLabel");

// set the class, can be used several times
text.setData("org.eclipse.e4.ui.css.CssClassName", "error");

These IDs or classes can be addressed in the CSS file via the # or the . selector.

#MyCSSTagForLabel {
    color: blue;
}

.error {
    border: 1px red;
}

Another example is the assignment of an image to a label via CSS.

#logo {
    background-image: url('platform:/plugin/com.vogella.rcp.customization/icons/img_login.png');
}

On the label, set the CSS ID or the class.

imgLabel.setData("org.eclipse.e4.ui.css.id", "logo");

3.4. Ignore certain widgets during styling

The org.eclipse.e4.ui.css.disabled key can be used to instruct the CSS engine to ignore certain widgets.

// more code....
yourWidget.setData("org.eclipse.e4.ui.css.disabled", Boolean.TRUE);

3.5. Colors and gradients

Colors can be defined in different ways. For example, the color white can be described as white, rgb(255,255,255) or #ffffff.

Color constants from SWT can be used, for example, SWT.COLOR_BLACK or SWT.COLOR_WIDGET_BACKGROUND.

Text {
    color: COLOR-CYAN;
    background-color: COLOR-WIDGET-BACKGROUND;
}

.MPart .InfoPane {
    color: COLOR-INFO-FOREGROUND;
    background-color: COLOR-INFO-BACKGROUND;
}
The CSS value uses a "-" whereas the SWT constants use an "_".

Styling supports gradients for the background color of user interface widgets. Linear and radial gradients are supported. The definition of gradients is demonstrated in the following listing.

/* linear gradient */
/* background-color: gradient linear color_1 [color_2]* [percentage]* */

/* for example */
background-color: gradient linear white black;
background-color: gradient linear white black blue;
background-color: gradient linear white black 50%;
background-color: gradient linear white black 50% 20%;

/* radial gradient */
/* background-color: gradient radial color_1 [color_2]* [percentage]* */

/* for example */
background-color: gradient radial white black;
background-color: gradient radial white black 50%;

With the optional percentage, the color change happens at the defined percentage. The following picture shows the result of different settings.

Different Gradient settings
The current gradient specification is not compliant with the CSS specification and it might change in the future.

3.6. CSS imports

Eclipse supports the import of existing stylesheets via the @import directive using the platform URI notation.

For example, the following stylesheet imports an existing dark theme of the org.vogella.ui.themes plug-in.

@import url("platform:/plugin/org.vogella.ui.themes/css/e4-dark.css");

/* add new CSS rules here. You can also override settings defined in the imported CSS
by using the same selector-property combination */
The plug-in that contains the imported CSS file must be included in your runtime.

3.7. Extending an existing theme

You can add additional styling to an existing theme. For example, if you defined additional settings for the default dark theme of the Eclipse IDE in a file called css/additional.css, you can register it with the following extension.

<extension
      point="org.eclipse.e4.ui.css.swt.theme">
   <stylesheet
         uri="css/additional.css">
      <themeid
            refid="org.eclipse.e4.ui.css.theme.e4_dark">
      </themeid>
   </stylesheet>
</extension>

3.8. Example: Hide the close button

The swt-show-close property that older documentation suggests for this was removed from the CSS engine in Eclipse 2024-03 and is silently ignored today. Whether a part can be closed is a property of the application model, set the closeable flag of the MPart instead.

CSS can still hide the close button on the tabs that are not selected.

CTabFolder {
    swt-unselected-close-visible: false;
}

4. CSS support for custom widgets

The CSS support offers two extension points for adding CSS capabilities to custom widgets:

  • org.eclipse.e4.ui.css.core.elementProvider

  • org.eclipse.e4.ui.css.core.propertyHandler

Those extension points are defined in the org.eclipse.e4.ui.css.core plug-in. You find some predefined implementations for SWT in the org.eclipse.e4.ui.css.swt plug-in.

4.1. The org.eclipse.e4.ui.css.core.elementProvider extension point

Under this extension, you can specify for which entries in the CSS style sheet the IElementProvider is responsible. The org.eclipse.e4.ui.css.core.elementProvider extension defines an IElementProvider that returns the widget’s adapter (ElementAdapter). IElementProvider returns an org.w3c.dom.Element.

ElementAdapter type hierarchy

In general, the returned org.w3c.dom.Element is an instance of an ElementAdapter. By the widget properties under the provider, you point to the class of the actual widget, like org.eclipse.swt.widgets.Control, for which the provider is responsible.

The SWTElementProvider, for instance, contains those ElementAdapter implementations that are shown in the type hierarchy screenshot and looks like this:

/**
 * Returns the CSS class which is responsible for styling a SWT widget
 *
 * Registered via the "org.eclipse.e4.ui.css.core.elementProvider" extension
 * point for the SWT widgets
 *
 *
 *
 * {@link IElementProvider} SWT implementation to retrieve w3c Element
 * {@link SWTElement} linked to SWT widget.
 *
 */
public class SWTElementProvider implements IElementProvider {

    public static final IElementProvider INSTANCE = new SWTElementProvider();

    @Override
    public Element getElement(Object element, CSSEngine engine) {
        if (element instanceof Text) {
            return new TextElement((Text) element, engine);
        }
        if (element instanceof Button) {
            return new ButtonElement((Button) element, engine);
        }
        if (element instanceof Scale) {
            return new ScaleElement((Scale) element, engine);
        }
        if (element instanceof Shell) {
            return new ShellElement((Shell) element, engine);
        }
        if (element instanceof CTabFolder) {
            return new CTabFolderElement((CTabFolder) element, engine);
        }
        if (element instanceof ToolBar) {
            return new ToolBarElement((ToolBar) element, engine);
        }
        if (element instanceof Composite) {
            return new CompositeElement((Composite) element, engine);
        }
        if (element instanceof Control) {
            return new ControlElement((Control) element, engine);
        }
        if (element instanceof CTabItem) {
            return new CTabItemElement((CTabItem) element, engine);
        }
        if (element instanceof TableItem) {
            return new TableItemElement((TableItem) element, engine);
        }
        if (element instanceof ToolItem) {
            return new ToolItemElement((ToolItem) element, engine);
        }
        if (element instanceof Item) {
            return new ItemElement((Item) element, engine);
        }
        if (element instanceof Widget) {
            return new WidgetElement((Widget) element, engine);
        }
        return null;
    }
}

4.2. The org.eclipse.e4.ui.css.core.propertyHandler extension point

In the org.eclipse.e4.ui.css.core.propertyHandler extension point, you define an adapter of type ElementAdapter for your widget that is used by the CSS engine. Here you specify an implementation of an ICSSPropertyHandler, where different property-names for the widget can be defined. This implementation is responsible for applying the CSS properties to the underlying widget.

You have to define three properties for a org.eclipse.e4.ui.css.core.propertyHandler.

Table 3. Properties of the propertyHandler
Property Description

adapter

The ElementAdapter implementation adapts/wraps your custom widget for the CSS framework

composite

A boolean that specifies whether the widget is a composite or not

handler

ICSSPropertyHandler implementation that is responsible for setting a custom CSS property.

Here you can see a sample of the org.eclipse.e4.ui.css.swt projects propertyHandler extension point:

PropertyHandler extension point for org.eclipse.e4.ui.css.swt

These are the default ElementAdapter implementations for the adapter property in the screenshot above:

ElementAdapter type hierarchy

In the ICSSPropertyHandler implementation those property-names are read and applied to the actual widget.

The CSSPropertyBackgroundSWTHandler and its parent AbstractCSSPropertyBackgroundHandler are examples of such an implementation of the ICSSPropertyHandler. Here the background property is applied for certain widgets.

The AbstractCSSPropertyBackgroundHandler class delegates to the methods for the property-names. These are applied in the propertyHandler extension point to its subclasses like the CSSPropertyBackgroundSWTHandler.

    @Override
    public boolean applyCSSProperty(Object element, String property,
            CSSValue value, String pseudo, CSSEngine engine) throws Exception {
        if ("background".equals(property)) {
            applyCSSPropertyBackground(element, value, pseudo, engine);
        }
        if ("background-attachment".equals(property)) {
            applyCSSPropertyBackgroundAttachment(element, value, pseudo, engine);
        }
        if ("background-color".equals(property)) {
            applyCSSPropertyBackgroundColor(element, value, pseudo, engine);
        }
        if ("background-image".equals(property)) {
            applyCSSPropertyBackgroundImage(element, value, pseudo, engine);
        }
        if ("background-position".equals(property)) {
            applyCSSPropertyBackgroundPosition(element, value, pseudo, engine);
        }
        if ("background-repeat".equals(property)) {
            applyCSSPropertyBackgroundRepeat(element, value, pseudo, engine);
        }
        return false;
    }

The following listing is the applyCSSPropertyBackgroundColor method of the CSSPropertyBackgroundSWTHandler. It shows how the background-color property-name is applied for several widgets:

@Override
    public void applyCSSPropertyBackgroundColor(Object element, CSSValue value,
            String pseudo, CSSEngine engine) throws Exception {
        Widget widget = (Widget) ((WidgetElement) element).getNativeWidget();
        if (value.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
            Color newColor = (Color) engine.convert(value, Color.class, widget
                    .getDisplay());
            if (widget instanceof CTabItem) {
                CTabFolder folder = ((CTabItem) widget).getParent();
                if ("selected".equals(pseudo)) {
                    // tab folder selection manages gradients
                    CSSSWTColorHelper.setSelectionBackground(folder, newColor);
                } else {
                    CSSSWTColorHelper.setBackground(folder, newColor);
                }
            } else if (widget instanceof Control) {
                GradientBackgroundListener.remove((Control) widget);
                CSSSWTColorHelper.setBackground((Control) widget, newColor);
                CompositeElement.setBackgroundOverriddenByCSSMarker(widget);
            }
        } else if (value.getCssValueType() == CSSValue.CSS_VALUE_LIST) {
            Gradient grad = (Gradient) engine.convert(value, Gradient.class,
                    widget.getDisplay());
            if (grad == null) {
                return; // warn?
            }
            if (widget instanceof CTabItem) {
                CTabFolder folder = ((CTabItem) widget).getParent();
                Color[] colors = CSSSWTColorHelper.getSWTColors(grad,
                        folder.getDisplay(), engine);
                int[] percents = CSSSWTColorHelper.getPercents(grad);

                if ("selected".equals(pseudo)) {
                    folder.setSelectionBackground(colors, percents, true);
                } else {
                    folder.setBackground(colors, percents, true);
                }

            } else if (widget instanceof Control) {
                GradientBackgroundListener.handle((Control) widget, grad);
                CompositeElement.setBackgroundOverriddenByCSSMarker(widget);
            }
        }
    }

5. CSS tools

5.1. CSS Spy

The CSS spy tool shows the available styling properties and the current style settings of selected elements. It is part of the Eclipse PDE (org.eclipse.pde.spy.css plug-in).

You open the CSS spy via the Shift+Alt+F5 shortcut.

The CSS Spy in action

5.2. CSS Scratch Pad

The CSS Scratch Pad allows you to change CSS rules interactively. It is part of the same plug-in, and you open it via the Shift+Alt+F6 shortcut.

If you click the Apply button, the entered CSS is applied to your running application.

6. Exercise: Use CSS styling

In this exercise, you style your application. The user can switch the styling at runtime.

The exercises extend the task management application of the Eclipse RCP tutorial.

6.1. Create a new plug-in and add dependencies

Create a new simple plug-in named com.vogella.eclipse.css.

Add the org.eclipse.e4.ui.css.swt.theme plug-in as a plug-in dependency to the manifest file of your new plug-in.

6.2. Create the CSS files

Create a folder named css in the root of your com.vogella.eclipse.css plug-in. Create the following css/fonts.css file. The default theme and the dark theme of a later exercise import it, so both use the same fonts and lay out the widgets identically.

Label, Button, Text {
    font: Verdana 10px;
}

.MTrimBar {
    font: Verdana 8px;
}

Create the following css/default.css file. It imports the fonts via the platform URI of your plug-in.

@import url("platform:/plugin/com.vogella.eclipse.css/css/fonts.css");

Label, Button {
    background-color: #e0e0e0;
    color: black;
}

Table, Tree {
    background-color: #f2f2f2;
    swt-header-background-color: #d0d0d0;
    swt-header-color: black;
    color: black;
}

Composite Text {
    background-color: white;
    color: black;
}

SashForm {
    background-color: #c1d5ef;
}

.MTrimBar {
    color: white;
}

Shell, Composite, .MTrimBar {
    background-color: #e0e0e0;
}

CTabItem:selected {
    background-color: #d0d0d0;
    color: black;
}

CTabFolder {
    /* the swt-* tab properties only work with this renderer */
    swt-tab-renderer: url('bundleclass://org.eclipse.e4.ui.workbench.renderers.swt/org.eclipse.e4.ui.workbench.renderers.swt.CTabRendering');
    swt-selected-tab-highlight: #8a8a8a;
    swt-selected-highlight-top: false;
    swt-tab-outline: #c8c8c8;
    swt-outer-keyline-color: #c8c8c8;
}

CTabFolder.active {
    swt-selected-tab-highlight: #2160bb;
}

In addition, create the following css/rainbow.css file.

Shell {
    swt-background-mode: default;
    background-color: red orange yellow green orange 30% 60% 75% 95%;
}

.MPartStack {
    font-size: 22px;
    color: orange;
}

6.3. Create the theme extensions

Open the Extensions tab in the MANIFEST.MF editor.

If the Extensions tab does not exist, click on the Extensions link in the Overview tab.

Press the Add…​ button in the Extensions tab, select the org.eclipse.e4.ui.css.swt.theme extension point and press the Finish button.

New Extension wizard filtered for the theme extension point

Right-click on the org.eclipse.e4.ui.css.swt.theme extension and select the New  theme menu entry to create a theme. Create two themes.

Context menu to create a new theme under the theme extension

The following screenshots show the extensions you should create.

Extensions tab with the Default theme extension
Extensions tab with the Default and Rainbow theme extensions

When you add the first extension via the editor, PDE marks the plug-in as singleton (Bundle-SymbolicName: com.vogella.eclipse.css;singleton:=true in the MANIFEST.MF file). If you create the plugin.xml file by hand, add this directive yourself, as the extension registry ignores the extensions of a plug-in that is not a singleton.

The plugin.xml file should look similar to the following listing.

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
   <extension
         point="org.eclipse.e4.ui.css.swt.theme">
      <theme
            basestylesheeturi="css/default.css"
            id="com.vogella.eclipse.css.default"
            label="Default">
      </theme>
      <theme
            basestylesheeturi="css/rainbow.css"
            id="com.vogella.eclipse.css.rainbow"
            label="Rainbow">
      </theme>
   </extension>
</plugin>

6.4. Adjust the build.properties file

Ensure that all CSS files are included in your build via the build.properties file of your plug-in. This makes them available in the exported application.

The build.properties file should look similar to the following listing.

source.. = src/
output.. = bin/
bin.includes = META-INF/,\
               .,\
               plugin.xml,\
               css/

6.5. Setting the default theme in the application

Configure the default theme via a property of your product extension.

For this, open the plugin.xml file in your com.vogella.tasks.ui plug-in and select the Extensions tab. Add the cssTheme property to your product and point to the com.vogella.eclipse.css.default theme.

To add a new property, right-click on the product and select New  property. Do not press the Add…​ button.

Context menu to add a property to the product extension
Extensions tab with the cssTheme property of the product

This must be done in the com.vogella.tasks.ui plug-in, not in the com.vogella.eclipse.css plug-in.

If present, remove an existing entry for applicationCSS. applicationCSS is an alternative way to define fixed styling for the application, but it is not used in this exercise.

Ensure that the cssTheme property is correctly set. Without it, the IThemeEngine does not work.

The entry in the plugin.xml of com.vogella.tasks.ui should look similar to the following.

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>

   <extension
         id="product"
         point="org.eclipse.core.runtime.products">
      <product
            name="taskmanagement"
            application="org.eclipse.e4.ui.workbench.swt.E4Application">
         <property
               name="appName"
               value="Task Management">
         </property>
         <property
               name="cssTheme"
               value="com.vogella.eclipse.css.default">
         </property>
      </product>
   </extension>
</plugin>

6.6. Add the new plug-in to the product (via the feature)

Add your com.vogella.eclipse.css plug-in to your feature. Afterward, start the application via the product configuration file.

6.7. Validate

Start your application and ensure that the application is styled according to the cssTheme property setting. Your application might look similar to the following (screenshot from Linux).

Task application styled with the default theme

6.8. Improve the styling

Try adjusting the colors and styling of your application to achieve a visually appealing design.

7. Exercise: Implementing dynamic theme switching

In this exercise, you use the IThemeEngine service to change the theme at runtime.

IThemeEngine is not official API, so you see the message The type 'IThemeEngine' is not API. There is no official API for theme switching yet, so you rely on this provisional one.

7.1. Ensure you have a plug-in or package dependency on the theme engine

Ensure that the manifest file of com.vogella.tasks.ui has a plug-in or package dependency on the theme engine org.eclipse.e4.ui.css.swt.theme.

An existing dependency is filtered from the list of the Add…​ dialog.

7.2. Implement a new menu entry

Create a new Java class that allows you to switch between the themes.

package com.vogella.tasks.ui.handlers;

import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.css.swt.theme.ITheme;
import org.eclipse.e4.ui.css.swt.theme.IThemeEngine;

public class ThemeSwitchHandler {
    private static final String DEFAULT_THEME = "com.vogella.eclipse.css.default";
    private static final String RAINBOW_THEME = "com.vogella.eclipse.css.rainbow";

    @Execute
    public void switchTheme(IThemeEngine engine) {
        ITheme activeTheme = engine.getActiveTheme();
        String nextTheme = activeTheme != null && DEFAULT_THEME.equals(activeTheme.getId())
                ? RAINBOW_THEME
                : DEFAULT_THEME;
        // true persists the choice so that it is restored on restart
        engine.setTheme(nextTheme, true);
    }
}

Define a new command with the com.vogella.tasks.ui.command.theme.switch ID and a handler in your application model for switching the style. Assign the above class to the handler.

Add a menu entry to the application model to use your handler for style switching.

7.3. Validate theme switching

Start the application and select your new menu entry. Afterwards, the styling of your application should use the rainbow theme.

Task application styled with the rainbow theme

Changes in styling may require a restart of your application. The CSS engine resets the majority of the SWT properties, but not all widgets respond to this reset.

8. Optional exercise: Implement a dark theme

Define a new theme in the plugin.xml file of com.vogella.eclipse.css, next to the existing ones.

<theme
      basestylesheeturi="css/dark.css"
      id="com.vogella.eclipse.css.dark"
      label="Dark">
</theme>

The following css/dark.css file defines the dark theme.

@import url("platform:/plugin/com.vogella.eclipse.css/css/fonts.css");

CTabFolder {
    /* the swt-* tab properties only work with this renderer */
    swt-tab-renderer: url('bundleclass://org.eclipse.e4.ui.workbench.renderers.swt/org.eclipse.e4.ui.workbench.renderers.swt.CTabRendering');
    background-color: #2b2b2b;
    color: #999999;
    swt-unselected-tabs-color: #2b2b2b;
    swt-selected-tab-fill: #3d3d3d;
    swt-tab-outline: #2b2b2b;
    swt-outer-keyline-color: #2b2b2b;
    swt-unselected-hot-tab-color-background: #353535;
    swt-selected-tab-highlight: #a6a6a6;
    swt-selected-highlight-top: false;
}

CTabFolder.active {
    swt-selected-tab-highlight: #2b79d7;
}

CTabItem:selected {
    color: #e0e0e0;
}

/* type selectors match only the exact SWT class, so the part content needs .MPart */
Shell, Composite, .MPart, ScrolledComposite, SashForm, Sash, Group, ToolBar, Label, Button, Link {
    background-color: #3d3d3d;
    color: #e0e0e0;
}

Text, Combo, Spinner, DateTime {
    background-color: #2b2b2b;
    color: #e0e0e0;
}

Table, Tree {
    background-color: #2b2b2b;
    color: #e0e0e0;
    swt-header-background-color: #333333;
    swt-header-color: #d0d0d0;
}

Link {
    swt-link-foreground-color: #8ab4f8;
}

/* the segmented bar fills the area around its segments with its background */
SegmentedBar {
    background-color: #2b2b2b;
}

Menus are native widgets that follow the theme of the operating system, so the CSS does not style them.

The handler of the previous exercise toggles between two fixed themes, so it cannot select the dark theme. Change it to read the theme ID from a command parameter named themeId.

package com.vogella.tasks.ui.handlers;

import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.ui.css.swt.theme.IThemeEngine;

import jakarta.inject.Named;

public class ThemeSwitchHandler {

    @Execute
    public void switchTheme(@Optional @Named("themeId") String theme, IThemeEngine themeEngine) {
        if (theme != null) {
            themeEngine.setTheme(theme, true);
        }
    }
}

Add a command parameter with the ID themeId to your command. The handler ignores a call without this parameter, so the existing menu entry for the default or rainbow theme needs the themeId parameter too, or you replace it. Add one menu entry for each theme to your application model and give each entry a parameter named themeId whose value is the ID of the theme, for example, com.vogella.eclipse.css.dark.

The result may look similar to the following screenshot (taken under Linux).

Task application with a dark theme

The DateTime widget cannot be styled via CSS under Windows. This is a limitation in the Windows API.

New task wizard in the dark theme under Windows

9. Optional exercise: Use the CSS spy

Start the CSS spy in your Eclipse IDE via Window  Spies  CSS Spy or Shift+Alt+F5.

Add the spies temporarily to your runtime application, as described in the model spy exercise of the Eclipse platform development tutorial. Use it to analyze the widgets and their CSS properties.

Optional: Open the CSS Scratch Pad via Shift+Alt+F6, enter Shell { background-color: #e0f0ff; } and press Apply to see the change immediately.

Only a few CSS attributes can be changed via the CSS spy at runtime. The CSS spy is open source, so you can contribute support for more attributes.

10. Optional exercise: Styling the login screen

In this exercise, you style the widgets created by the lifecycle handler of your application. It builds on the Manager lifecycle class and the PasswordDialog login screen of the Eclipse RCP tutorial.

10.1. Implement styling

Change your Manager class to apply one of your CSS files to the widgets in the login screen.

package com.vogella.tasks.ui.lifecycle;

import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine;
import org.eclipse.e4.ui.workbench.IWorkbench;
import org.eclipse.e4.ui.workbench.lifecycle.PostContextCreate;
import org.eclipse.equinox.app.IApplicationContext;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Monitor;
import org.eclipse.swt.widgets.Shell;

import com.vogella.tasks.ui.dialogs.PasswordDialog;

public class Manager {

    @PostContextCreate
    public void postContextCreate(IApplicationContext appContext, Display display, IEclipseContext context) {

        final Shell shell = new Shell(SWT.SHELL_TRIM);
        PasswordDialog dialog = new PasswordDialog(shell);

        // close the static splash screen
        appContext.applicationRunning();

        // position the shell
        setLocation(display, shell);

        // style the shell with the CSS file
        String cssURI = "platform:/plugin/com.vogella.eclipse.css/css/rainbow.css";
        context.set(IWorkbench.CSS_URI_ARG, cssURI);
        PartRenderingEngine.initializeStyling(shell.getDisplay(), context);

        // open the dialog
        if (dialog.open() != Window.OK) {
            // close the application
            System.exit(-1);
        }
    }

    private void setLocation(Display display, Shell shell) {
        Monitor monitor = display.getPrimaryMonitor();
        Rectangle monitorRect = monitor.getBounds();
        Rectangle shellRect = shell.getBounds();
        int x = monitorRect.x + (monitorRect.width - shellRect.width) / 2;
        int y = monitorRect.y + (monitorRect.height - shellRect.height) / 2;
        shell.setLocation(x, y);
    }
}

10.2. Validate

Start your application and ensure the splash screen is styled according to your settings.

Styled splash screen

11. Exercise: Define a custom CSS selector and CSS property

In this exercise, you will implement your custom CSS selector and property for styling the header of a user profile widget. The aim is to apply custom styling to the custom widget, called UserProfileWidget.

You will define a new UserProfileWidget CSS selector and a new header-background-color CSS property. The result may look like that, where the user profile widget is embedded in a Tooltip:

UserProfileWidget sample

11.1. Add dependencies

Add the org.eclipse.e4.ui.css.core and the org.eclipse.e4.ui.css.swt plug-ins as a dependency to your application.

11.2. Adjust custom CSS to your CSS file

Add the following CSS to your CSS file, which is used in your application plug-in.

UserProfileWidget { (1)
   header-background-color: red; (2)
}
1 Custom CSS selector
2 Custom CSS property

11.3. Create the user profile widget

To learn how to implement customizations for CSS, we need a custom widget that should be styled. We implement a simple custom widget, which is a Composite that consists of three other Composites for the header, image, and description area. For the following widget, you should create a widget package in your plug-in and place the UserProfileWidget class into it.

package com.vogella.rcp.css.custom.widget;

import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.resource.ResourceManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;

public class UserProfileWidget extends Composite {
    private ResourceManager resourceManager;

    private String text = "";
    private String headerText = "";
    private ImageDescriptor imageDescriptor;

    private Label imageLabel;
    private Label headerLabel;
    private Label labelText;

    private Composite head;

    public UserProfileWidget(Composite parent, int style) {
        super(parent, style);
        GridLayoutFactory.swtDefaults().numColumns(2).applyTo(this);

        head = new Composite(this, SWT.NONE);
        GridLayoutFactory.fillDefaults().applyTo(head);
        GridDataFactory.fillDefaults().span(2, 1).grab(true, false).applyTo(head);
        headerLabel = new Label(head, SWT.NONE);
        headerLabel.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false));
        headerLabel.setText(getHeaderText());

        Composite imageComposite = new Composite(this, SWT.NONE);
        GridLayoutFactory.fillDefaults().applyTo(imageComposite);
        GridDataFactory.fillDefaults().applyTo(imageComposite);
        imageLabel = new Label(imageComposite, SWT.NONE);
        ImageDescriptor imgDescriptor = getImage();
        if (imgDescriptor != null) {
            imageLabel.setImage(getResourceManager().create(imgDescriptor));
        }

        Composite textComposite = new Composite(this, SWT.NONE);
        GridLayoutFactory.fillDefaults().applyTo(textComposite);
        GridDataFactory.fillDefaults().grab(true, true).applyTo(textComposite);
        labelText = new Label(textComposite, SWT.NONE);
        labelText.setText(getText());
    }

    protected ResourceManager getResourceManager() {
        if (null == resourceManager) {
            resourceManager = new LocalResourceManager(JFaceResources.getResources(), this);
        }
        return resourceManager;
    }

    protected String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
        if(labelText != null) {
            labelText.setText(text);
        }
    }

    protected String getHeaderText() {
        return headerText;
    }

    public void setHeaderText(String headerText) {
        this.headerText = headerText;
        if (headerLabel != null) {
            headerLabel.setText(headerText);
        }
    }

    protected ImageDescriptor getImage() {
        return imageDescriptor;
    }

    public void setImage(ImageDescriptor imageDescriptor) {
        this.imageDescriptor = imageDescriptor;
        if (imageLabel != null) {
            imageLabel.setImage(getResourceManager().create(imageDescriptor));
        }
    }

    public Color getHeaderColor() {
        return head.getBackground();
    }

    public void setHeaderColor(Color color) {
        head.setBackground(color);
        headerLabel.setBackground(color);
    }
}

The most important method for our custom CSS here is the last setHeaderColor() method, which we will use for our header-background-color CSS property. To test this widget, you can place it on a new part in your application or in a tooltip as it is depicted in the screenshot above. Afterwards, you should set a certain header-text, an image, and a description-text to the UserProfileWidget.

11.4. Adding the org.eclipse.e4.ui.css.core.propertyHandler extension point

Select the Extensions tab in the editor for the plugin.xml file and add the org.eclipse.e4.ui.css.core.propertyHandler extension point. You create an extension in the Extensions tab by pressing the Add…​ button.

Select the org.eclipse.e4.ui.css.core.propertyHandler extension point and press the Finish button.

Selecting
propertyHandler handler definition

By clicking on the adapter hyperlink of the handler in the plugin.xml, a "New Java Class" dialog appears, where you define the CompositeElement as superclass. Call the class itself UserProfileElementAdapter and place it into a css package.

new class dialog user profile element adapter

The UserProfileElementAdapter class should look like this:

package com.vogella.rcp.css.custom.css;

import org.eclipse.e4.ui.css.core.engine.CSSEngine;
import org.eclipse.e4.ui.css.swt.dom.CompositeElement;

import com.vogella.rcp.css.custom.widget.UserProfileWidget;

public class UserProfileElementAdapter extends CompositeElement {

    public UserProfileElementAdapter(UserProfileWidget composite, CSSEngine engine) {
        super(composite, engine);
    }
}

In this case, we only have a custom composite that needs to be adapted. The propertyHandler needs a handler that has to be an implementation of the ICSSPropertyHandler interface. Therefore, we need to click on the handler hyperlink in the plugin.xml, and the following "New Java Class" dialog appears:

new class dialog user profile css handler

The AbstractCSSPropertySWTHandler is an abstraction of the ICSSPropertyHandler interface for SWT widgets. It handles the cast to an SWT Control, which is then passed to the applyCSSProperty and retrieveCSSProperty methods. In the UserProfileCSSHandler implementation we apply the header-background-color to our UserProfileWidget.

package com.vogella.rcp.css.custom.css;

import org.eclipse.e4.ui.css.core.dom.properties.converters.ICSSValueConverter;
import org.eclipse.e4.ui.css.core.engine.CSSEngine;
import org.eclipse.e4.ui.css.swt.properties.AbstractCSSPropertySWTHandler;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Control;
import org.w3c.dom.css.CSSValue;

import com.vogella.rcp.css.custom.widget.UserProfileWidget;

public class UserProfileCSSHandler extends AbstractCSSPropertySWTHandler {

    private static final String HEADER_COLOR = "header-background-color";

    @Override
    protected void applyCSSProperty(Control control, String property, CSSValue value, String pseudo, CSSEngine engine)
            throws Exception {
        if (control instanceof UserProfileWidget) {
            UserProfileWidget userProfileWidget = (UserProfileWidget) control;
            if (HEADER_COLOR.equalsIgnoreCase(property) && (value.getCssValueType() == CSSValue.CSS_PRIMITIVE_VALUE)) {
                Color newColor = (Color) engine.convert(value, Color.class, control.getDisplay());
                userProfileWidget.setHeaderColor(newColor);
            }
        }
    }

    @Override
    protected String retrieveCSSProperty(Control control, String property, String pseudo, CSSEngine engine)
            throws Exception {
        if (control instanceof UserProfileWidget) {
            UserProfileWidget userProfileWidget = (UserProfileWidget) control;
            if (HEADER_COLOR.equalsIgnoreCase(property)) {
                ICSSValueConverter cssValueConverter = engine.getCSSValueConverter(String.class);
                return cssValueConverter.convert(userProfileWidget.getHeaderColor(), engine, null);
            }
        }
        return null;
    }

}

At first, we check if the given Control is a UserProfileWidget and cast it. Then we check if the property that should be applied is our header-background-color. In case these checks are valid, the CSSEngine can be used to convert the given CSSValue in our case to a Color. The value arrives as an org.w3c.dom.css.CSSValue, which the CSS engine of Eclipse 4.41 (2026-09) builds with its own parser, so let the engine convert it instead of reading the W3C accessors. Finally, we set this color for the header of our custom widget.

If you are using a different UI toolkit than SWT, you must only implement the ICSSPropertyHandler interface rather than the AbstractCSSPropertySWTHandler. This interface passes a java.lang.Object and does not check for an SWT Control.

The last thing we need to do for the propertyHandler extension is to define for which property-name this handler is responsible:

property handler property name

11.5. Adding the org.eclipse.e4.ui.css.core.elementProvider extension point

Now the second and last extension point has to be added:

element provider extension

After adding the org.eclipse.e4.ui.css.core.elementProvider extension point, we can add an IElementProvider to it. For this, click on the class hyperlink and give the class the name UserProfileWidgetElementProvider.

element provider provider definition

The widget property you can see in the screenshot above points to the fully qualified name of the UserProfileWidget (com.vogella.rcp.css.custom.widget.UserProfileWidget). The widget property may be used several times, so that one IElementProvider implementation can be in charge of several widgets. The UserProfileWidgetElementProvider class we just created by clicking the class hyperlink in the plugin.xml implements the IElementProvider interface and should look like this:

package com.vogella.rcp.css.custom.css;

import org.eclipse.e4.ui.css.core.dom.IElementProvider;
import org.eclipse.e4.ui.css.core.engine.CSSEngine;
import org.w3c.dom.Element;

import com.vogella.rcp.css.custom.widget.UserProfileWidget;

public class UserProfileWidgetElementProvider implements IElementProvider {

    @Override
    public Element getElement(Object element, CSSEngine engine) {
        if(element instanceof UserProfileWidget) {
            return new UserProfileElementAdapter((UserProfileWidget) element, engine);
        }
        
        return null;
    }

}

In this IElementProvider implementation, we return the UserProfileElementAdapter, which we previously defined when we attached this adapter to the propertyHandler.

11.6. Validate

Now we can check if our custom CSS definitions are applied to the UserProfileWidget. Make sure that you have completed all the steps and then start your application.

  • The UserProfileWidget has been applied to a Part, and a sample header-text, image, and description-text has been set for the widget.

  • The CSS snippet has been added to the active CSS file

  • You have configured the org.eclipse.e4.ui.css.core.propertyHandler and org.eclipse.e4.ui.css.core.elementProvider extension points correctly

12. Reference: CSS selectors and properties

This chapter lists the selectors, properties and pseudo classes the Eclipse CSS engine understands. The property tables are taken from the handlers registered in the org.eclipse.e4.ui.css.swt, org.eclipse.ui.forms and org.eclipse.ui.views.properties.tabbed plug-ins. Values written as '#some-id' refer to a ColorDefinition or FontDefinition, see Theme definitions and preferences.

12.1. Selectors

Table 4. Supported selector forms
Selector Matches Example

Element name

SWT widget class, the simple class name without the package

Button, CTabFolder, Shell

#id

Widget with org.eclipse.e4.ui.css.id data or the model element id with . replaced by -

#org-eclipse-ui-editorss CTabFolder

.class

Widget with org.eclipse.e4.ui.css.CssClassName data. The renderer writes the model element type and all its tags into that data, so a model element is matched as a class, not as an element name

.MPartStack, .MPart.busy, .MPartStack.active

[key='value']

Widget data set with setData(key, value)

*[foo='bar']

[style~='SWT.X']

SWT style bits passed to the constructor

Text[style~='SWT.READ_ONLY']

[swt-data-class~='fqn']

Class hierarchy of the widget data

Shell[swt-data-class~='org.eclipse.jface.dialogs.Dialog']

Descendant, child

Nesting of widgets

CTabFolder ToolBar, Composite > StyledText

@media

Platform, OS version or installed bundle

@media (-eclipse-os: linux) { …​ }

:not(…​)

Everything its argument does not match, starting with the planned Eclipse 2026-12 release. The argument is a single simple selector: *, an element name, .class, #id or [key='value']

Composite:not(.MPartStack)

Adjacent sibling selectors (+) are not supported. A pseudo class is not accepted as the argument of :not(). The :not() itself adds nothing to the specificity of a rule, the specificity of its argument is added instead. A selector the engine rejects disables the whole rule group it belongs to, so qualify class selectors with an element type when in doubt.

Table 5. Media features for @media rules
Feature Values

-eclipse-os

linux, win32, macosx

-eclipse-ws

gtk, win32, cocoa

-eclipse-os-version, -eclipse-min-os-version, -eclipse-max-os-version

Version string, quote it if it has more than one dot, e.g. "10.15"

-eclipse-bundle

Bundle symbolic name, e.g. "org.eclipse.ui"

-eclipse-bundle-version, -eclipse-min-bundle-version, -eclipse-max-bundle-version

Symbolic name and version, e.g. "org.eclipse.ui 3.2"

12.2. Properties for all controls

Table 6. Control properties
Property Values Example

background

Shorthand, split into the background-* properties below

Label { background: #181818; }

background-color

Color, or two colors with a percentage for a gradient, add false for a horizontal gradient

Button { background-color: #F00 #0F0 100% false; }

background-image

url(…​) with a platform:/plugin/…​ URI

Label { background-image: url('platform:/plugin/x/icons/a.png'); }

color

Foreground color

Label { color: #CCC; }

font

Shorthand for style, size, weight and family

Label { font: italic 12 bold "Terminal"; }

font-family, font-size, font-style, font-weight

Single font attributes or a FontDefinition

.MPartStack { font-family: '#org-eclipse-ui-workbench-TAB_TEXT_FONT'; }

text-transform

none, capitalize, uppercase, lowercase

CTabItem { text-transform: uppercase; }

swt-alignment, text-align

left, lead, right, trail, center, up, down (up/down for arrow buttons)

Label { swt-alignment: center; }

cursor

CSS cursor name

Shell { cursor: crosshair; }

visibility

visible, hidden, collapse

Label { visibility: hidden; }

margin, margin-top, margin-bottom, margin-left, margin-right

Pixels, applied to the layout of the parent

Composite { margin: 5; }

border-color, border-width, border-style

Color, pixels, style, only for controls whose parent sets CSS_SUPPORTS_BORDERS

Button { border-width: 3; }

Every ToolItem also accepts background-color and color, on GTK these values are not painted.

font-adjust, font-stretch and font-variant are not supported, because an SWT font has no such attribute. Such a declaration is ignored and does not affect the other declarations of the rule.

12.3. Font sizes

An SWT font height is a point size, so a font-size is always resolved to points.

Table 7. Values accepted for font-size
Value Meaning Example

unitless

Points

Label { font-size: 12; }

pt

Points

Label { font-size: 12pt; }

px

CSS pixels, converted with 1px = 0.75pt

Label { font-size: 16px; } gives 12pt

em

Relative to the font the widget inherited

Label { font-size: 1.5em; }

%

Relative to the font the widget inherited

Label { font-size: 150%; }

larger, smaller

One step, a factor of 1.2, up or down from the font the widget inherited

Label { font-size: larger; }

Relative values are resolved against the font the widget had before it was styled, which lets a theme ask for a font a bit larger than the rest without overriding the size the user configured in the Colors and Fonts preference page. A relative size on a FontDefinition scales the font the definition was registered with. The font shorthand accepts the same values, for example Label { font: Verdana 1.5em; } or Label { font: Verdana larger; }.

Point sizes stay resolution independent, the platform converts them with the system DPI and Eclipse scales on top of that. Relative sizes, including larger and smaller, and the px conversion require the planned Eclipse 2026-12 release. Before that, px was read as a point size and em and % were ignored.

12.4. Font weights

font-weight accepts normal, bold, bolder, lighter and any number from 1 to 1000. bolder and lighter step from the weight the widget inherited, following CSS Fonts Level 4. The engine derives the inherited weight from the bold flag of the SWT font, so it is always 400 or 700, even if the font uses an intermediate face. For a regular font bolder gives 700 and lighter gives 100. For a bold font bolder gives 900 and lighter gives 400. It also accepts the face names designers use. Apart from normal and bold, these names are not standard CSS.

Table 8. Face names accepted for font-weight
Name Weight

thin, hairline

100

extra-light, ultra-light

200

light

300

normal, regular

400

medium

500

semi-bold, demi-bold

600

bold

700

extra-bold, ultra-bold

800

black, heavy

900

The names are case-insensitive and may be written without the hyphen, as in semibold, but not with a space, as in semi bold. They are only understood by font-weight, not in the font shorthand, where they could be part of a family name.

An SWT font style only knows regular and bold, but a font family can ship more faces, so a weight between them, such as 500 or 600, selects the installed face of that weight, for example Semibold. On GTK Pango picks the closest face of the family, on Windows a family such as "Segoe UI Semibold" is used when it is installed, and on macOS a face of the family with a matching name such as HelveticaNeue-Medium. Where no such face is found, a weight of 600 or more selects the bold face and anything below it the regular one. The face is chosen by rounding the weight to the nearest hundred, halves rounding up, and clamping the result to 100 to 900. So 50 uses the 100 face, 650 the bold face, and 950 and 1000 the 900 face. A number outside 1 to 1000 is ignored.

In the font shorthand normal, bold, bolder and lighter are weights too. Only a bare multiple of 100 from 100 to 900 is read as a weight there, any other bare number is a size in points. So Label { font: 600 12pt Arial; } and Label { font: 12 Arial; } both work, but in font: 1000 12pt Arial the 1000 is read as a size. When the shorthand contains several sizes the last one wins, so this declaration gives a 12pt font and font: 12pt 1000 Arial a 1000pt one. Set such a weight with font-weight instead.

The numeric weights, bolder, lighter, the face names and the face selection require the planned Eclipse 2026-12 release. Before that, only bold made a font bold and every other value made it regular.

Table 9. Container and viewer properties
Widget Property Values Example

Composite

swt-background-mode

default, force, none

Shell { swt-background-mode: force; }

Tree, Table

swt-header-color

Header foreground

Tree { swt-header-color: #CCC; }

Tree, Table

swt-header-background-color

Header background

Table { swt-header-background-color: #181818; }

Tree, Table

swt-lines-visible

true, false, also usable as attribute selector

Table[swt-lines-visible=true] { color: #FFF; }

Link

swt-link-foreground-color

Color of the link text

Link { swt-link-foreground-color: #4DAAFC; }

There is no property for the selection colors of Tree, Table and List, these come from SWT.

12.6. CTabFolder and CTabItem

Table 10. CTabFolder properties
Property Values Example

swt-tab-renderer

url('bundleclass://bundle/class'), required for the swt-selected-*, keyline and outline properties

CTabFolder { swt-tab-renderer: url('bundleclass://org.eclipse.e4.ui.workbench.renderers.swt/org.eclipse.e4.ui.workbench.renderers.swt.CTabRendering'); }

border-visible

true, false

CTabFolder { border-visible: false; }

swt-tab-position

top, bottom

CTabFolder { swt-tab-position: bottom; }

swt-tab-height

Pixels

CTabFolder { swt-tab-height: 8px; }

swt-tab-text-minimum-characters

Number

CTabFolder { swt-tab-text-minimum-characters: 5; }

swt-single, swt-simple

true, false (swt-simple is deprecated)

CTabFolder { swt-single: true; }

swt-maximized, swt-minimized

true, false

CTabFolder { swt-maximized: true; }

swt-maximize-visible, swt-minimize-visible

true, false

.MPartStack { swt-minimize-visible: false; }

swt-unselected-close-visible, swt-unselected-image-visible, swt-selected-image-visible

true, false

CTabFolder { swt-unselected-close-visible: false; }

swt-unselected-tabs-color

One color, or colors with percentages for a gradient

CTabFolder { swt-unselected-tabs-color: #181818; }

swt-selected-tabs-background

Colors with percentages

CTabFolder { swt-selected-tabs-background: #F00 #FFF 100%; }

swt-selected-tab-fill

Color of the selected tab

CTabFolder { swt-selected-tab-fill: #1F1F1F; }

swt-selected-tab-highlight

Color of the highlight line of the selected tab

.MPartStack.active { swt-selected-tab-highlight: #0078D4; }

swt-selected-highlight-top

true draws the highlight above the tab, false below

CTabFolder { swt-selected-highlight-top: true; }

swt-unselected-hot-tab-color-background

Color of a hovered unselected tab

CTabFolder { swt-unselected-hot-tab-color-background: #252526; }

swt-tab-outline, swt-inner-keyline-color, swt-outer-keyline-color

Colors of the tab outline and the keylines

CTabFolder { swt-tab-outline: #2B2B2B; }

swt-draw-custom-tab-content-background

true, false

.MPartStack { swt-draw-custom-tab-content-background: false; }

padding, padding-left, padding-right, padding-top, padding-bottom

Pixels

CTabFolder { padding: 2px; }

Use one color for swt-unselected-tabs-color. Two different colors switch the folder to a gradient image, and the controls in the tab row, the min/max bar and the chevron, then stop following the theme. Starting with the planned Eclipse 2026-12 release, a gradient whose stops are all the same color is collapsed to that solid color, so it no longer produces the image. Before that, even identical stops produced the gradient image.

Table 11. CTabItem properties
Property Values Example

color, font-*, text-transform

As for controls, :selected is honored

CTabItem:selected { color: #FFF; }

background-color

Applied to the parent CTabFolder, not to the tab label

CTabItem { background-color: #181818; }

The swt-show-close and swt-mru-visible properties listed in older documentation are no longer registered by the engine, swt-show-close was removed in Eclipse 2024-03. Use the closeable flag of the MPart to control the close button and swt-unselected-close-visible to hide it on the unselected tabs. swt-tab-outer-keyline is not registered either, swt-outer-keyline-color is the property that works.

12.7. Forms and tabbed properties

Table 12. Forms properties (org.eclipse.ui.forms)
Widget Property Example

Form

text-background-color, h-bottom-keyline-1-color, h-bottom-keyline-2-color, h-hover-light-color, h-hover-full-color, tb-toggle-color, tb-toggle-hover-color

Form { text-background-color: #1F1F1F; h-hover-full-color: #252526; }

Section

background-color-titlebar, background-color-gradient-titlebar, border-color-titlebar, swt-titlebar-color, tb-toggle-color, tb-toggle-hover-color

Section { swt-titlebar-color: #CCC; border-color-titlebar: #2B2B2B; }

ExpandableComposite

swt-titlebar-color, tb-toggle-color, tb-toggle-hover-color

ExpandableComposite { swt-titlebar-color: #CCC; }

Table 13. Tabbed properties view (org.eclipse.ui.views.properties.tabbed)
Widget Properties

TabbedPropertyTitle

swt-backgroundGradientStart-color, swt-backgroundGradientEnd-color, swt-backgroundBottomKeyline1-color, swt-backgroundBottomKeyline2-color

TabbedPropertyList

swt-tabAreaBackground-color, swt-tabBackground-color, swt-tabNormalShadow-color, swt-tabDarkShadow-color, color

12.8. Theme definitions and preferences

Color and font definitions are the entries of the theme registry, contributed by plug-ins through the org.eclipse.ui.themes extension point. The Colors and Fonts preference page is the view on that registry, so a definition a stylesheet changes is the one the user sees there. A stylesheet can change existing definitions, register new ones and write preference values when the theme is activated.

Table 14. Definition elements
Element Properties Example

ColorDefinition#id

color, category, label, description, editable

ColorDefinition#my-BG { color: #181818; category: '#org-eclipse-ui-presentation-default'; label: url('platform:/plugin/my.plugin?message=BG'); }

FontDefinition#id

font-family, font-size, font-style, font-weight, category, label, description, editable

FontDefinition#org-eclipse-jface-textfont { font-family: 'Fira Code'; font-size: 11; }

ThemesExtension

color-definition, font-definition, lists the ids of new definitions

ThemesExtension { color-definition: '#my-BG', '#my-FG'; }

IEclipsePreferences#node:qualifier

preferences, one 'key=value' string per preference

IEclipsePreferences#org-eclipse-ui-editors:org-eclipse-ui-themes { preferences: 'AbstractTextEditor.Color.Background=31,31,31'; }

The id of a definition is its Eclipse id with . replaced by -, so org.eclipse.jface.textfont becomes #org-eclipse-jface-textfont. Once registered, a definition is used as a value in any rule, e.g. color: '#my-FG';. Preference values are written when the theme is applied and stay in the preference store until the next theme switch, so hand tuned values are overwritten.

category, label, description and editable only affect the preference page, a definition with editable: false is left out of it entirely. Definitions are implemented in org.eclipse.ui.workbench, so they work in an RCP application that ships org.eclipse.ui, but a pure e4 application has none to override.

12.9. Pseudo classes

A pseudo class is evaluated whenever the engine applies styles to a widget. Only :focus, :hover, :checked and :active can also trigger a restyle while the application runs, and only if the org.eclipse.e4.ui.css.dynamic=true system property is set. Without it the engine does not attach the focus, mouse, selection and shell listeners that request the restyle.

:enabled, :disabled and :visible are read from the widget on every run, but no widget change ever starts one, so a later setEnabled() or setVisible() call does not repaint the widget in the new style.

Table 15. Pseudo classes
Widget Pseudo class Example

Control

:focus, :hover, :enabled, :disabled, :visible

Text:disabled { color: gray; }

Shell

:active, :swt-parented, :swt-unparented

Shell:active { background-color: #FFF; }

Button, ToolItem

:checked

Button:checked { background-color: blue; }

CTabFolder, CTabItem

:selected

CTabItem:selected { font-weight: bold; }

13. CSS styling resources

Home Tutorials Training Consulting Books Company Contact us


Get more...