CSS / LESS

Overview

Your Servoy solution can be styled using LESS as dynamic style sheet language and/or unprocessed CSS (3.0).

CSS (Cascading Style Sheets) is the style sheet language used in the World Wide Web to describe how elements should be rendered in the presentation layer.

LESS is a CSS preprocessor that adds various features to CSS, such as variables, mixins, and functions. It allows developers to write more maintainable and reusable code by using a dynamic and expressive syntax. By using LESS, you can define variables to store common values, create mixins to reuse code snippets, and define functions for more complex tasks. In Servoy the .less file will compile into an actual .css automatically. For a detailed documentation about Less language see the Official Documentation for Less.

When creating a Servoy NG Client solution, the solution is created with the Servoy default less theme (is possible to opt-out); the theme offers configurable styles for commonly used components and a set of utility classes.

Quick Start

Servoy solutions are styled using a layered approach that combines:

  • A default theme: Defines base styling across the application (e.g., fonts, colors, spacing).

  • LESS/CSS files: Allow custom styling, variables, mixins, and layout definitions.

  • Component-level and form-level overrides: Enable scoped, local customization without affecting global styles.

If you're just getting started, begin with the Default Theme guide to understand how base styles are defined and extended.

Styling Flow in Servoy

Styling in Servoy is applied in a layered manner, where each level can override or extend the one above it. Here’s how it works:

  1. Default Theme (custom_servoy_theme_properties.less) The base layer, built into Servoy, contains foundational variables and component styles.

  2. Solution-Level LESS/CSS Global styles that apply across your entire solution. By default, Servoy generates a file named <solution-name>.less, but this can be overridden.

  3. Form-Level LESS/CSS (Scoped) Styles defined directly in the Form Editor’s Less tab, scoped to the form they belong to. Ideal for layout-specific or isolated component styling.

  4. Component-Level Styling Individual components reference class names using the styleClass property. These classes can be defined in any of the above layers.

This layered system gives you flexibility to build a unified design system at the solution level, while enabling isolated, maintainable styling within forms and components.

How it works

Servoy uses a LESS compiler to process and generate the final CSS used by the client. LESS enhances traditional CSS with features like variables, nesting, and imports — making your styles easier to manage and reuse.

Where Styles Come From

  1. Default Theme (custom_servoy_theme_properties.less) This built-in file defines Servoy's core variables and component styles. It should not be edited directly. Instead, it can be extended or overridden via your own solution-level LESS files. You can also edit theme variables using the Theme Properties Editor.

  2. Solution-Level LESS File A global stylesheet, typically <solution-name>.less, located in the media folder. This file is created automatically with your solution and can be customized or replaced.

  3. Form-Level LESS (Scoped) A recent addition to Servoy, this lets you write LESS/CSS directly in each form. These styles are encapsulated to the form, allowing class reuse across forms without collision.


Notes

  • LESS files are compiled server-side at design time; changes appear after client reload.

  • Solution-level variables can override default theme values.

  • Form-level styles are not shared; use them only for layout and local customization.

Solution-Level Styling

Overview

Solution-level styling refers to a global LESS or CSS file used across your entire application. When you create a new solution, Servoy automatically generates a LESS file named after your solution (e.g., mycrm.less) and places it in the media folder.

You are not limited to using this default file. You can configure the solution to use any .less file in the media folder instead.

To use a custom LESS file as your solution’s stylesheet, open the Solution Properties and set the stylesheet property to the desired .less file (e.g., main.less).

How It Works

  • The designated .less file is automatically compiled and applied globally.

  • Styles from this file affect all forms and components in the solution.

  • It serves as the main place to:

    • Override variables from the default theme

    • Declare global design tokens (colors, spacing, etc.)

    • Define shared layout patterns and component styles

    • Organize styles with @import to keep the codebase clean

Example

A common pattern in solution-level styling is to define design tokens (like colors or spacing) as variables, and then use them throughout your global styles. You can also break up your styles into separate modular files for better organization.

// media/mycrm.less

@primary-color: #007bff;

.btn-primary {
  background-color: @primary-color;
  color: white;
  border-radius: 4px;
  padding: 8px 16px;
}

You can modularize styles by importing them from subfolders:

@import "styles/variables.less";   // All design tokens
@import "styles/layout.less";      // Grid, containers, spacing
@import "styles/components.less";  // Shared UI components like buttons, cards, etc.

These imported files should also be placed inside the media folder or a subdirectory within it.

Use Cases

  • Building and maintaining a centralized design system

  • Defining consistent styles for reusable UI components (e.g., buttons, cards, inputs)

  • Setting up layout scaffolding for global templates (e.g., header/footer containers)

  • Overriding default theme values for typography, borders, spacing, and color schemes

Best Practices

  • Keep your styles modular by using @import, for example for:

    • variables.less for color/spacing/fonts

    • layout.less for structural containers

    • components.less for reusable UI parts

  • Use clear, reusable class names (e.g., .app-header, .form-section, .btn-primary)

  • Centralize all shared styles here so they can be consistently reused across forms

  • Reserve form-level styling only for local exceptions or layouts that aren’t shared

Form-Level Styling (Scoped)

Overview

Form-level styling in Servoy allows you to write form-specific LESS or CSS that applies only to the components on that form. This approach ensures styles are fully encapsulated, meaning class names, layout rules, and overrides cannot conflict with styles- globals or on other forms — even if the same class names are reused.

🎯 Form styles are automatically scoped — .my-class on Form A is completely independent from .my-class on Form B.

This feature was introduced to solve stylesheet encapsulation challenges and to enable cleaner styling practices in larger solutions, where global stylesheets often became bloated with rules used in isolated places.

How It Works

  • Each form has a Less tab in the Form Editor.

  • Click the Create Form Less file button to generate a .less file tied specifically to that form.

  • The styles written in this file:

    • Are compiled and applied only to the form they belong to.

    • Can use full LESS features: variables, mixins, nesting, etc.

    • Override global styles (e.g., from solution-level LESS or default theme), if class selectors match.

    • Are inherited by child forms in form hierarchies.

Why Form-Level Styling Matters

✅ Encapsulation: No naming conflicts between styles in different forms. ✅ Maintainability: Keeps form-specific styles close to the form logic. ✅ Override capability: Can locally override global styles for layout or appearance tweaks. ✅ Cleaner solution-level styling: No need to pollute your global .less with one-off or niche form rules. ✅ Layout freedom: Makes it easy to use CSS Grid or Flexbox per form, adapting responsive layout structures without affecting others.

Examples:

Example: Overriding a Global Style in Form-Level LESS

This example demonstrates how the same class name (.content-text) can be reused across multiple forms, each with its own styling, thanks to form-level encapsulation in Servoy's LESS support. It shows how form-level styles override global styles without conflict, allowing per-form visual customization without risk of unintended side effects.

Use Case You want to apply a class called .content-text to label components across multiple forms. Each form should display the text in a different color, using the same class name, without modifying the global stylesheet or affecting other forms.

What the Forms Contain Each of the three forms (Form A, Form B, and Form C) contains:

  • A title label (e.g., "Form A")

  • A content label (e.g., description of the applied style)

  • Both labels have the styleClass property set to content-text.

LESS Code

  • Solution-Level LESS (Global): In media/<solution>.less (e.g., mySolution.less):

    .content-text {
    color: blue;
    }

    This is the default style used by Form A and available to any form that does not override it.

  • Form B - Form-Level LESS: In Form B’s Less tab:

    .content-text {
    color: red;
    }

    Form B uses the same class name, but styles it differently. This red text applies only within Form B.

  • Form C - Form-Level LESS: In Form C’s Less tab:

    .content-text {
    color: green;
    }

    Form C also uses .content-text, independently overriding both the global and Form B versions.

Visual Result:

Form-Level LESS vs. Global Style

Key Takeaways

  • 🔒 Scoped LESS allows safely reusing class names across forms.

  • 🧼 Reduces clutter in global styles by moving isolated rules to local form context.

  • 🔄 Allows per-form overrides without touching or duplicating solution-wide styles.

  • 📦 Keeps form logic and styling self-contained and maintainable.


Example: Form Inheritance with Layered LESS Overrides

This example shows how Servoy's form-specific LESS works in a form inheritance chain. It demonstrates how styles defined in a base form can be reused and selectively overridden in child forms, using the same class names — with each form's styling fully encapsulated.

Use Case You want a shared base form (baseForm) that defines reusable layout and style rules. Child forms (FormA, FormB, FormC, and FormD) should inherit those styles but optionally override them with their own scoped LESS — without affecting each other or the base form.

What the Forms Contain

  • baseForm:

    • 2 labels:

      • Title → styleClass = "title"

      • Content → styleClass = "content-text"

    • Has its own form-level LESS that overrides the global style:

    .title {
     font-size: 40px;
     color: black;
    }
    
    .content-text {
     color: black;
    font-size: 30px;
    }
  • Form A:

    • Extends baseForm

    • Own LESS overrides .title only:

    .title {
      color: blue;
    background-color: cyan;
    }
  • Form B

    • Extends baseForm

    • Own LESS overrides .content-text only:

    .content-text {
    color: red;
    background-color: #ECEBEA;
    }
  • Form C

    • Extends baseForm

    • Own LESS overrides both .title and .content-text:

    .title {
    font-size: 20px;
    color: green;
    background-color: #cef3d5;
    }
    
    .content-text {
     color: green;
    }
  • Form D

    • Extends baseForm

    • No form-level LESS; uses inherited styles as-is

Visual Result:

Form Inheritance with Scoped LESS Overrides

LESS Inheritance Resolution: Order of Precedence When using form-level LESS with inheritance, Servoy resolves styles in the following order, from lowest to highest priority:

  1. Global (Solution-Level) LESS

    • Declared in the solution's .less file (e.g., mySolution.less)

    • Applies universally unless overridden at a more specific level

  2. Base Form LESS

    • Defined in the base form's own Less tab

    • Overrides global styles within that form and all forms that inherit it

  3. Child Form LESS

    • Defined in a child form that extends a base form

    • Has the highest priority and overrides both base form and solution-level styles

🧠 Even when using the same class name, Servoy ensures styles are scoped and isolated per form. A .content-text in Form C does not affect the same class in Form B, even though both inherit from the same base form.

Key Takeaways

  • 🧬 Form-level LESS follows inheritance rules — child forms receive styles from parent forms.

  • 🔁 Each form can selectively override inherited styles using the same class names.

  • 🔒 All overrides remain encapsulated to the form; no cross-form conflicts.

  • 🧹 Helps maintain clean and modular styling across large solutions with shared layouts.


Example: Responsive Form: Two-Row Flex Layout (3 Items per Row)

This version of the layout uses form-scoped LESS to create a responsive layout with two rows, each containing exactly three flex items.

What the Form Contains

Responsive Form's Setup
  • 1 Bootstrap Flex Container

  • 6 child components (flex items), each one with a button inside for example purposes

Visual goal:

[ item 1 ] [ item 2 ] [ item 3 ]
[ item 4 ] [ item 5 ] [ item 6 ]

Form-Level LESS Inside the form’s Less tab, click Create Form Less file, then add the custom style:

.flex {
  display: flex;
  flex-wrap: wrap;
  flex-direction: row;
  align-items: stretch;
  justify-content: flex-start;
  gap: 16px;
  padding: 16px;
  background-color: #f8f8f8;
}

.flex-item {
  flex: 0 1 calc(33.333% - 16px); // 3 items per row with spacing
  min-width: 200px;
  box-sizing: border-box;
  background-color: #e0e0e0;
  border: 1px solid #ccc;
  padding: 12px;
  text-align: center;
}

Explanation

  • flex-wrap: wrap enables wrapping into multiple rows.

  • flex: 0 1 calc(33.333% - 16px) ensures three items per row, adjusting for gap.

  • The layout will always break into two rows with three items each, as long as the container is wide enough.

  • If the screen becomes too narrow, items will start to wrap again (you can constrain with max-width or add media queries if needed).

Visual Result:

Form-Level LESS

Use Cases

  • 🧱 Form-specific layouts using Flexbox or CSS Grid Great for dashboards, sidebars, detail views, and other UIs with complex, responsive layouts.

  • 🧪 Isolated design experimentation Safely prototype new styles on a single form without breaking other parts of the app.

  • 💡 UI modularization Encapsulate styles alongside embedded forms, wizards, pop-ups, or reusable UI modules.

  • 🛡️ Conflict prevention Use identical class names across forms without risk of collision or unintended overrides.

Best Practices

  • Use clear, local naming (e.g., .customer-summary, .invoice-section).

  • Keep styles focused and scoped — don't attempt to define global utilities or shared variables here.

  • Use form-specific LESS to define layout logic and fine-tune styling for the form only.

  • Consider this approach as a way to scale style management in large, modular applications.

Styling Techniques and Best Practices

This section covers practical tips and patterns for writing LESS/CSS effectively in Servoy, including selector usage, styling components, managing specificity, and using variables.

Using Servoy’s Built-In Selectors

Every Servoy element has a default selector in its template — for example, a Bootstrap button has the class .bts-button. You can target these classes to apply consistent styling across all components of that type.

// Make the borders of all buttons slightly rounded
.bts-button {
  border-radius: 6px;
}

Applying Custom Classes with styleClass

Each component in Servoy has a styleClass property, where you can enter one or more custom class names. This is the preferred way to apply additional styles or override default ones.

Example:

styleClass="btn btn-primary my-roundy-btn"

And the LESS:

.my-roundy-btn {
  border-width: 2px;
  border-radius: 50px;
}

This allows for stacking multiple styles and combining behavior, utility, or appearance.

CSS Specificity in LESS

The final style applied to an element depends on CSS specificity. If multiple class selectors apply to the same property (e.g., border-radius), the one defined last in the compiled CSS will win if specificity is equal.

Example:

// This will be overridden by .my-roundy-btn if it appears later in the file
.bts-button {
  border-radius: 6px;
}

.my-roundy-btn {
  border-radius: 50px;
}

Info If both have the same specificity weight, the order of appearance determines the final result.

Best practice:

Define default element styles first, and custom class-based overrides (used in styleClass) after.

Using LESS Variables

LESS variables help you keep your styles consistent and easy to update. You can define them once and reuse across multiple components.

// Define a LESS variable
@my-border-radius: 6px;

// Use it across selectors
.bts-button {
  border-radius: @my-border-radius;
}

.bts-textbox,
.bts-textarea {
  border-radius: @my-border-radius;
}

This improves maintainability, ensures design consistency, and makes theming or refactoring faster.

Servoy elements Selectors

These are the specific class selectors which you can use to style servoy elements based on their types. Please note, depending on the component complexity, the component may have inner selectors to target more specific elements of their template; these inner selectors can be subjects to changes upon upgrades. The most effective way to Style your solution and easily adjust to upgrades is to use the Servoy default Theme.

Common components Selectors

Common Components
Class Selector

Label, DataLabel

.bts-label

Button

.bts-button

Image

.svy-mediafield

Calendar

.bts-calendar

Calendar inline

.bts-calendar-inline

Checkbox

.bts-check

Choice Group

.bts-radiogroup

Combobox

.bts-combobox

HTML Area

.svy-extra-htmlarea

Slider

.svy-slider

Spinner

.svy-extra-spinner

TextArea

.bts-textarea

TextBox

.bts-textbox

Textbox Group

.bts-textbox

Native Data List

.bts-list

Native Select

.bts-select

Type Ahead

.bts-typeahead

select2tokenizer

.svy-select2-autotokenizer

Note if you have an existing Servoy solution using legacy classic components the bts- prefix would be replaced by the svy- prefix, example: .svy-label .svy-button.

Floating components Selectors

All Floating components are placed within a .svy-form-floating div

Common Components
Class Selector

Floating Calendar

.bts-floatlabelcalendar

Floating Combobox

.bts-floatlabelcombobox

Floating Textarea

.bts-floatlabeltextarea

Floating Textbox

.bts-floatlabeltextbox

Floating Type Ahead

.bts-floatlabeltypeahead

Grids Selectors

Grids
Class Selector

Data Grid, Power Grid

.ag-table

Tanle

.svy-table

Other components Selectors

Other Components
Class Selector

Navbar

.bts-extra-navbar

Sidenav

.svy-extra-sidenav

Treeview

.treeview

DBTreeview

.dbtreeview

Form Containers Selectors

Form Containers
Class Selector

Form Container

.svy-container

Tab Panel

.bts-tabpanel

Accordion

.bts-accordion

Split Panel

.svy-extra-splitpane

Collapse

.svy-collapse

Form Component

.svy-formcomponent

List Form Component

.svy-listformcomponent

Form parts Selectors

Form Parts
Class Selector

Form

.svy-form

Header

.svy-header

Body

.svy-body

Footer

.svy-footer

Reconnecting feedback

When the NGClient detects communication issues with the server, a message is shown. This message can be styled and the text can be set using servoy i18n.

The message is a div styled using class svy-reconnecting:

.svy-reconnecting {
    color: red;
}

The message is defined by key servoy.ngclient.reconnecting:

Loading Indicator

By default NGClient will set the wait mouse cursor on body and all its elements - when a request to the server takes a while. Starting with Servoy 2019.03 it will also show a default loading animation (bottom of page).

The default loading animation can be customized directly from the solution's .css (or .less) file. It is made up of a parent div (with class "loading-i-holder") and 5 child divs (with class "lii-shape" on all of them and then each with it's own class from "lii-1" up to "lii-5"). You can change colors, position, animation and whatever is supported by CSS. For example if you want to make the shapes blue instead of orange you just add this to the solution style sheet:

// changing default loading indicator color(s)
.lii-shape {
    background-color: blue;
}

If you want for example the animation to not be shown at all you could for example add this to solution .css:

// hiding the indicator completely
.loading-i-holder {
    display: none;
}

There is another class selector, svy-reconnecting-overlay, which is used to define the css transition. The transition also has a delay (default) half a second in order to avoid this message showing when there is a network hiccup. The delay can be changed from solution css:

.svy-reconnecting-overlay.ng-hide-remove {
  transition-delay: 10s !important;
}

Using media file from LESS/CSS

Is possible to import other LESS/CSS files and reference other media files such as images or icons.

If mymedia.gif exists in media files, you can use if in the style as background-image: url("mymedia.gif"); or background-image: url("myimages/mymedia.gif"); if the image is placed in the subfolder myimages.

Importing other .less/.css files in the main solution .less/.css

In the .css/.less file that you choose as a property of the solution you can also reference other .css/.less files from solution media.

You can import other LESS files using the import statement: example @import "mySecondStyle.less";

If you import other .css files, you need to add to the url the argument "t=##last-changed-timestamp##"; this is required in order to discard the browser cached version of the css, when a new WAR is deployed (##last-changed-timestamp## will be replaced during WAR export with the last changed timestamp of the parent CSS).

For example if you have another .css file in media "stylesheets/ui_customisation.css" (the path is relative inside media to the solution-css-or-less file that does the import) you can reference that by adding this line at the beginning of you solution's .css/.less: @import "stylesheets/ui_customisation.css?t=##last-changed-timestamp##";

Dynamic Styling

Style sheets can be changed programmatically, allowing a developer to change styles to different users' taste or to have periodic style changes in their applications. This can be done using the overrideStyle function.

The override style can be used to apply to the solution any style from an existing CSS/LESS file present in the media files or with a generated CSS/LESS file. In the example below the solution's default style is replaced with the style tenantX.less which is a different LESS file present in the media folder of the solution.

application.overrideStyle('mySolution.less', 'tenantX.less'); // tenant.less can be a solution model changed or generated file, then it will be recompiled at runtime.

In this example instead the solution's style is replaced with a newly generated style. Using LESS variables in style allows you to easily adjust the theme with the overrideStyle by setting only few variables value dinamically.

var media = solutionModel.getMedia('myDynamicStyle.less');
media.setAsString('@import "mySolution.less"; @main-color:green; @my-border-radius:2px;');

application.overrideStyle('mySolution.less', 'myDynamicStyle.less');

Last updated

Was this helpful?