StyleSheets (CSS)
Overview
This page provides an overview of CSS-based styling in CDP Studio widgets. While many widgets support visual customization through SVG files, some widgets rely solely on CSS for styling. For example, widgets like scroll bars, group boxes, and frames do not support SVG and are typically styled using CSS rules defined in a stylesheet (e.g., main.css) applied via the cssFile property on the main window.
Conversely, certain custom-styled widgets, such as meters, are rendered exclusively using SVG and do not support CSS-based styling. Most interactive widgets like buttons and labels, however, support both SVG and CSS, allowing developers to choose the most suitable method or combine them as needed. This guide explains how to apply CSS rules using the styleSheet property on individual widgets or globally through an external CSS file. It also outlines best practices, selector syntax, theme integration, and the limitations of CSS styling in the CDP widget system.
See also CDP Widgets Themes (SVG) for SVG-based styling and theme integration.
How to Apply CSS Styling
There are multiple ways to apply CSS styling to widgets. The method depends on the type of widget you're working with.
- Using the styleSheetproperty: You can define custom styling directly on a widget using itsstyleSheetproperty.- This is often used for quick overrides or widgets that don’t support external styling.
- See Theme-Based Styling Using Container for an example demonstrating how to use styleSheetwith theme-aware styling.
 
- Using the cssFileproperty: For widgets that support external styling, such as buttons and containers, you can assign a.cssfile using thecssFileproperty.- This allows for more reusable and consistent styling across widgets.
- See Theme-Specific CSS Files for an example demonstrating how to use cssFilewith theme-aware styling.
 
- Depending on the widget: For example, Buttonsupports both approaches:- Set type= NoFile to use thestyleSheetdirectly, or to enable styling by parent.
- Set type= CSS to use an external file via thecssFileproperty.
 
- Set 
Widgets without a type property, such as Frame, Scrollbar, and GroupBox, are automatically styled by the main.css file provided by the main window. To override the default styling for a specific widget, simply use its styleSheet property.
Note: CSS styling is inherited from parent widgets to their children. If you want to apply the same style to multiple widgets, it's recommended to place them inside a Container. The Container also supports the cssFile property, which will apply its styles to all its child widgets.
CSS Styling Syntax
Here's a basic example of how to style widgets using a container's cssFile or styleSheet property:
CDPBaseButton {
    background-color: #444;
    color: white;
    border-radius: 4px;
}
CDPBaseLabel {
    color: black;
}
CDPBaseLabel[text="warning"] {
    color: orange;
}
In this example:
- All CDPBaseButtonwidgets will have a dark background and rounded corners.
- Any CDPBaseLabelwith itstextproperty initially set to"warning"will be styled in orange; others will remain black by default.
Note: If the CSS is applied on a top-level Container, all child widgets such as CDPBaseButton and CDPBaseLabel must have their stylingType property set to NoFile. This allows them to inherit and be styled by the parent container's CSS.
Note: The text selector only reflects the value when the stylesheet is initially applied. If the text changes at runtime, the style is not updated automatically. To re-evaluate CSS selectors that depend on properties such as text, you must call the polishStyle() slot on the container that owns the stylesheet. This will reapply the CSS and update all affected widgets, as described in the following section.
For a complete overview of supported selectors, properties, and pseudo-states, refer to the official Qt Style Sheet Reference:
Reapplying CSS Due to Value Changes
In the earlier example, we used the following CSS rules:
CDPBaseLabel {
    color: black;
}
CDPBaseLabel[text="warning"] {
    color: orange;
}
The first rule applies a default black color to all CDPBaseLabel widgets. The second rule overrides this color and applies orange to any label whose text property is initially set to "warning".
However, if the text property is updated dynamically at runtime, the selector [text="warning"] is no longer matched, but the style remains unchanged. This is because widget stylesheets are static and do not automatically re-evaluate property-based selectors.
As a result, a label that initially displays the text "warning" will remain orange even if the text changes to "ok", unless the stylesheet is explicitly reapplied.
Assuming a Container is used to provide the stylesheet, there are two ways to reapply the CSS when a value changes.
Manual Refresh
The most direct approach is to add a button that the user can click to trigger a refresh of the container’s stylesheet.
Connect the button’s clicked() signal to the container’s polishStyle() slot using a  signal and slot connection.
This will reapply the stylesheet on demand. For infrequent updates or low-priority visuals, this approach is typically sufficient.
Automatic Refresh Based on Value Changes
To reapply the stylesheet automatically when a value changes, connect a widget’s signal (typically valueChanged) to the container’s polishStyle() slot.
Since CDPBaseLabel does not emit a signal when its text changes, it cannot trigger the refresh directly. In such cases, a Com Widget can be used to detect value changes and apply the style update:
- Use a ComWidgetto receive the value (e.g., a warning string) from the control system.
- Connect the ComWidget’svalueChanged(QString)signal to the container’spolishStyle()slot.
This setup ensures that whenever the value updates (and thus the label text changes), the stylesheet is reapplied and selectors like [text="warning"] are re-evaluated accordingly.
Making CSS Styling Theme-Aware
To ensure that custom CSS styling adapts to the currently selected theme in CDP Studio, you can use one of two main approaches. Without theme-awareness, styles may become inconsistent or unreadable when switching between themes like flat_gray or flat_gray_light.
Theme-Based Styling Using Container
The Container provides a theme property that reflects the name of the active theme. This allows you to write conditional CSS rules scoped to the theme by targeting this property.
CDPBaseContainer[theme="flat_gray"] CDPBaseLabel { color: red; } CDPBaseContainer[theme="flat_gray_light"] CDPBaseLabel { color: yellow; }
This approach works well for inline styles or shared stylesheets.
Ensure child widgets do not override styling with their own styleSheet or conflicting stylingType.
Theme-Specific CSS Files
A cleaner and more scalable approach is to define separate CSS files for each theme. These files are typically placed in dedicated theme folders (e.g., themes/flat_gray/), and the appropriate file is selected automatically by updating the cssFile path when the theme changes.
To ensure the CSS files are deployed along with the rest of the UI, place them in the Application directory within the project. This is the same directory that contains the mainwidget.ui file. The folder can be accessed in CDP Studio Design mode by right-clicking the file in the top selector and choosing Show Containing Folder from the context menu.
In the following example, separate CSS files are used to apply different label colors for the flat_gray and flat_gray_light themes. The label will appear red in the flat_gray theme and yellow in the flat_gray_light theme.
Directory structure:
themes/ flat_gray/ myStyle.css flat_gray_light/ myStyle.css
Content of themes/flat_gray/myStyle.css:
CDPBaseLabel {
  color: red;
}
Content of themes/flat_gray_light/myStyle.css:
CDPBaseLabel {
  color: yellow;
}
Value assigned to the cssFile property in the Container:
themes/flat_gray_light/myStyle.css
WebUI note: To use these files in the Web UI, add the folder paths to the WebFilesToServe property in the Application, using CDP Studio Configure mode:
;themes/flat_gray_light;themes/flat_gray
With this setup, there is no need for conditional logic within the CSS itself. Each file applies only to its corresponding theme, and the system ensures that the correct file is loaded based on the active theme.
Note: To ensure that labels inherit the container's CSS, they must have stylingType set to NoFile and an empty styleSheet.
Setting Properties with CSS
In both of the above approaches, you can also style widget properties using the qproperty- prefix. This is especially useful for setting text or boolean flags directly from CSS.
Example – Setting Label Text Based on Theme:
CDPBaseContainer[theme="flat_gray"] CDPBaseLabel { qproperty-text: "Red"; } CDPBaseContainer[theme="flat_gray_light"] CDPBaseLabel { qproperty-text: "Yellow"; }
This does not introduce a new styling method, but rather expands the utility of the existing approaches by allowing direct control over widget properties.
Summary
- Use styleSheetfor inline CSS orcssFilefor external styling, depending on the widget.
- Set stylingType= NoFile to allow widgets to inherit styles from a parent container.
- CSS selectors like [text="value"]are only evaluated when the stylesheet is first applied.
- Call polishStyle()on the container to refresh styling after runtime property changes.
- Use the themeproperty or theme-specific CSS files for consistent styling across themes.
- Use qproperty-syntax to set widget properties such as text, colors, or booleans from CSS.
Get started with CDP Studio today
Let us help you take your great ideas and turn them into the products your customer will love.