Skip to content

Styling Web Applications

Managing Web Control Visibility
Modal Dialog Processing

Introduction

Styling web applications can be done in different ways and at different levels. The basic principle when thinking about styling is that the framework generates HTML. This HTML is generated at runtime and runs in the browser. Controls are the building blocks of web applications, and every control generates its own piece of HTML depending on the property settings it receives from the application. The look of a control is defined in Cascading Style Sheets (CSS). Both HTML and CSS are industry standards that a web designer should be able to work with.

Styling web applications means changing the CSS to alter the appearance of the controls. The screen layout and HTML structure are defined by the application and need to be modified at those levels.

Levels of Styling

Themes

Styling the application can be done at three different levels. The first level is the theme, which determines the look and color scheme of the controls. The theme consists of a single CSS file that is located together with the images it uses in a folder in AppHtml\CssThemes\ within the workspace. The default themes provided with the framework will have a folder name starting with Df_. Choosing a theme can be done by setting the psTheme property on the oWebApp object.

The standard set of themes includes Df_Material, Df_Flat_Touch, Df_Flat_Desktop, and a number of older themes that are mainly supplied for backward compatibility.

The DataFlex Styler

The DataFlex Styler is an online resource for customizing the standard themes included in DataFlex. It supports customizing the colors of the Material, Flat Touch, and Flat Desktop themes. For the Material theme, the Styler further supports the customization of fonts and many aspects of the List and Grids, Web Controls, and Buttons used in your web applications. Using the DataFlex Styler to modify the look and feel of your web applications does not require any special knowledge of CSS or how it is used in the Web Framework.

Read more about how to use the DataFlex Styler.

Further Customization of Themes

Customization of themes beyond what is supported in the DataFlex Styler is possible through editing the Theme.css file. You can start by using the DataFlex Styler to make initial modifications to the CSS structure and then edit the theme further to change other aspects of the user interface. Creating custom themes (beyond what is easily modified in the DataFlex Styler) is considered an advanced technique that requires good knowledge of CSS and the ability to inspect the HTML structure of the different controls in the framework.

CSS Classes

The second level of styling is the ability to assign custom CSS classes to controls. This is the best way to define a style for one or multiple controls without having to write a custom theme. Setting the psCSSClass property will add the CSS class to the outermost HTML wrapper element of that control. Using this class, custom CSS can be written for that control. Setting the same CSS class to other controls allows multiple controls to be styled at once.

The custom CSS should be placed inside the AppHtml\CssStyle\Application.css file, which is automatically included by the framework. Note that most controls consist of multiple nested HTML elements. All these HTML elements have their own function within this control. Setting dimensions, paddings, and margins on the wrong element can be dangerous because they might break the layout system. The CSS rules will usually have to override the rules defined by the theme. To make them stronger, you should always include an ID at the beginning of the selector. The outermost web app has the OWEBAPP ID that can be used for this.

The following sample shows how to apply a big border to a cWebForm:

#OWEBAPP .KeyField .WebFrm_Wrapper {
    border: 2px solid orange;
}

Where this class named KeyField is assigned using:

Object oCustomer_Number is a cWebForm
    Set psLabel to "Customer Num:"
    Entry_Item Customer.Customer_Number
    Set psCSSClass to "KeyField"
End_Object

Styling Properties

The third level of styling is by setting the styling properties available on the DataFlex classes. These properties are applied by the framework directly on the HTML elements, so they always override the CSS from the theme and the custom classes. Only a minimal set of styling properties is available on the controls. This is because these properties impose an overhead on the system, and the CSS classes and themes are a more proper way for changing the look and feel.

Examples of properties are psBackgroundColor and psTextColor. These colors map directly to CSS colors and can be set to, for example, "#FF0000", "Red", or "RGB(255,0,0)".

CSS Structure

The basic principle of CSS is that a selector is written that selects one or more elements on which styling properties are set. If multiple selectors select the same elements, the sets of properties are merged. If these selectors set the same properties, the value of the strongest property will win and is applied. The strength of a selector is determined by its position in the source code and the usage of tag names, class names, and IDs. An ID is always stronger than a class name, and a class name always takes precedence over a tag name. This is called CSS precedence.

System.css, Theme.css, Application.css

Within the framework, the basic styles that the framework needs to function properly are defined in system.css. The system.css is part of the framework and should never be changed by the designer. The theme.css extends and overrides the system styles to define the looks of the controls. The theme.css typically defines colors, borders, fonts, and margins. For example, the theme.css would make all buttons blue. The application.css is by default empty and is meant to contain application-specific styles that style specific instances of a control. So where theme.css would make all buttons blue, the application.css would, for example, make this single red button green.

The system.css is included before the theme.css, and application.css is included after theme.css. This is done so that in case of an equal selector, the application.css is always the strongest. The system.css and theme.css never contain any IDs, as these are application-specific. The framework does assign an ID named OWEBAPP to the outermost div that wraps all the elements, so it can be used to ensure that application.css is always stronger. The !important statement should never be needed, and it is advised not to use it.

Controls

As controls are the building blocks for web applications, the styles are usually defined per control. The selector usually starts with the outermost class name for that control. The HTML code below is what is generated by a WebForm. It includes HTML code for the label, a prompt button, and the input field itself. The outermost divs and the label are generated by the cWebBaseControl superclass. All controls also have the WebControl CSS class, which is used to apply styles to the shared part of all controls, like the label. The WebFrm_Wrapper and nested elements are generated by the WebForm itself. Note that some inline styles are set on the outermost div to position the control within the column layout system.

Order Number:

If we want to style the label of all controls, we would start our selector with .WebControl, which selects all of the div elements having the WebControl class name set. Now we want to have the label, so we could say .WebControl label, which selects all label elements inside elements having the WebControl class name. The framework CSS actually uses .WebControl > div > label, which ensures that only this specific label element is selected and no other label elements that a control might have. Since this is a stronger selector, we would advise using this select to ensure that you are overriding the system or theme CSS.

.WebControl > div > label {
    text-decoration: underline;
}

The sample code above underlines the label of all controls. If we only wanted to underline the label of WebForms, the selector would have been .WebForm > div > label.

Note that the control will add/remove the WebCon_HasLabel class name to indicate if the label should be visible or not. The WebCon_LeftLabel indicates that the label should be positioned left, as opposed to WebCon_TopLabel and WebCon_RightLabel. There are several other cases where the framework adds and removes class names at runtime depending on the application state. Web_Enabled, Web_Disabled, and WebCon_Focus are examples of other classes like that.

Containers

The cWebBaseContainer is the base class for all controls that can contain other controls. Examples include cWebTabPage, cWebPanel, cWebView, and cWebModalDialog. All the containers use the WebContainer CSS class name. Containers can contain controls or panels and will generate completely different HTML depending on their content. There are also quite a few differences in the type of containers; most subclasses add their own wrapping HTML.

The example above shows a tab container containing controls. Important to notice is the WebCon_Sizer that is there to add scroll bars when needed. The WebCon_Content is the wrapper that paddings should be set on.

In the HTML sample above, we see the structure of a tab page with panels. The comments show where the different panels would go.

Writing Selectors

The main part of styling a component is to write proper selectors. The framework has its own style of writing selectors, and it is advised to follow that style. Within the framework, a selector usually starts with the control class name. This class name is set on the outermost element of the control and has a name that usually matches the class name. It can also be the name of a superclass or a name set in the code as the psCSSClass property. So the outermost element usually has multiple class names.

Class Name Objects / Controls
.WebUIObj All UI objects that are not controls or containers
.WebControl All controls (cWebBaseControl)
.WebContainer All containers (cWebBaseContainer)
.WebForm Forms (cWebForm)
.WebPanel Panels (cWebPanel)
.WebButton Buttons (cWebButton)
.WebLabel Labels (cWebLabel)
.WebCombo Combo forms (cWebCombo)
.WebDateForm Date forms (cWebDateForm)
.WebGrid Grids (cWebGrid)
.WebList Lists (cWebList)
.WebMenuItem Menu items (cWebMenuItem)
.WebToolbar Toolbar (cWebToolbar)
.WebMenuBar Menu bar (cWebMenuBar)
.WebToolbar .WebMenuItem Menu items inside the toolbar
.WebMenuBar .WebMenuItem Menu items inside the menu bar

The list above shows some of the class names used by the framework. Sometimes we want to style components based on how/where they are used. For example, the cWebMenuItem is used within menu bars and within toolbars. In those cases, they look completely different, which is done by using .WebToolbar .WebMenuItem, which means "all menu items inside the toolbar."

As components consist of multiple elements, the selector will usually be longer and selects specific elements within the control. For this, class names and tag names are used. To find out the HTML structure of a component, it is common practice to use a tool called a DOM inspector. Most debugging tools available for browsers contain a DOM inspector. One of the most interactive and user-friendly DOM inspectors is available in FireBug (an extension for Firefox). To style a component, it is important to first find out its HTML structure. Then, inspecting the CSS applied to the controls when running an existing theme should help understand the meaning of the different elements and indicate which styles can/should be applied.

Styles Not to Touch

Setting some styles can break framework functionality. For example, setting margins on the outermost div of a control will break the column layout system. To increase the space between controls, it is advised to change the margin on WebCon_Inner. Another example is the positioning of the label, where the sibling div of the label should have a margin to make space for the label.


Previous Topic: Managing Web Control Visibility
Next Topic: Modal Dialog Processing

See Also

Developing Web Applications