Views
Foundation Package API Reference Guide
Product Documentation:
Views Documentation Home
Views Style Sheet Syntax

Views Style Sheet Syntax

Views Style Sheet syntax and terminology mostly follow the HTML CSS version 3 standard. Review the following sections to learn about the specific syntax rules, selector types, pseudo-states and how conflicts between style rules are resolved.

Style Rules

Style sheets are simple text files that define a set of style rules. Style rules are comprised of a selector and a declaration. The selector specifies which Views gadgets are affected by the rule and the declaration specifies a set of properties to be applied to the gadget. For example:

IlvButton {
color: blue;
background-color: white;
}

In the style rule above, IlvButton is the selector and { color: blue; background-color: white; } is the declaration. The style rule declaration defines text color for the IlvButton to be blue and the background color of the IlvButton to be white. The style rule will apply strictly to IlvButton and not to any subclasses that extends it. Similar rules need be defined to apply to any extending classes.

Style sheet rules are generally case insensitive including cases where a Views gadget class name is specified as the selector.

Several style rule selectors may be combined together as comma separated list of selectors. For example, the rule:

IlvButton, IlvMessageLabel {
background-color: green;
}

is equivalent to:

IlvButton {
background-color: green;
}
IlvMessageLabel {
background-color: green;
}

Style rule declarations are made up of property: value pairs, enclosed by braces, { }. Multiple property value pairs are separated by semicolons.

Selector Types

Style sheet selectors are patterns used to select the element(s) you want to style. The following sections describe the different types of selectors supported by Views Style Sheets.

Universal Selector

The universal selector specifies that the style rule should be applied to all Views gadgets. An asterisk is used to specify the universal selector.

* {
background-color: white;
}

In the above example, all Views gadgets will have their background color set to white.

Element Type Selector

Element type selectors, simply referred to as "type selectors", match the Views gadget's C++ class name with the name specified for the type selector. For example, the following example specifies that all IlvButton gadgets have a white background.

IlvButton {
background-color: white;
}

ID Selector

An ID selector is used to define a style rule for a specific gadget element. The selector is specified by using a hash, or pound symbol (#) and then a case sensitive string name for the ID. The selector string is used to match a specific Views gadget that also has the ID set. By default, the gadget ID's is initially set with the name property of the gadget, but the ID can also be set with the setCssId method call. For example, the following CSS defines rules for a gadget with ID #MyButton:

#MyButton {
padding: 10px;
background-color: #ccc;
}

The corresponding Views code sets the name and ID of the IlvButton to be "MyButton", matching the defined ID selector rule.

// Create a new IlvButton and set its name and ID to "MyButton"
IlvButton* button = new IlvButton(display, "MyButton", IlvRect(50, 70, 250, 40));

The ID of a gadget can also be set using the setCssId method call.

IlvButton* button = new IlvButton(display, "Button", IlvRect(50, 70, 250, 40));
// Set the ID of the button to "MyButton"
button->setCssId("MyButton");

An ID of a Views gadget is case sensitive and should be unique so that only one gadget uses the ID. If more than one gadget ends up with the same ID the style rule will still be applied to them but use of the non-unique ID is not valid from a technical standpoint.

Using a lot of ID selectors creates a very inflexible set of CSS rules but they can be useful if a specific gadget needs to be targeted.

Class Selector

A Class selector is used to define a style rule for a set of gadgets all associated by a specific class name. The selector is specified by using a dot (.) and then a string name for the class name. Views gadgets do not support class selector names yet but will in an upcoming release.

Descendant Combinator

A descendant selector, technically called a descendant combinator, lets you combine two or more selectors so that the rule is more specific. For example:

IlvContainer IlvButton {
padding: 15px;
}

This declaration block will apply a 15 pixel padding to all IlvButton gadgets within a IlvContainer. Any IlvButton that is a descendant of IlvContainer will be applied the styling in the block.

Use of descendant combinators should be deliberate and not overused. Specifying too many strict descendant combinators can make your style sheet code too specific and inflexible.

Child Combinator

A child combinator is a selector that is similar to a descendant combinator, except it only targets immediate child elements. The following is an example:

IlvContainer > IlvButton {
padding: 15px;
}

In this case, instead of applying a 15 pixel padding to all IlvButton gadgets within IlvContainers, it will only apply the padding to IlvButton's that are direct children to an IlvContainer and not descendants of other children.

As with descendant combinators, making too much use of child combinators can result in style sheet rules that are too specific and inflexible. They can be useful when needing to target a set of child gadgets that may be part of a list.

General Sibling Combinator

Styling all sibling gadgets, which are gadgets that are all "beside" each other in their relationship is accomplished using a general sibling combinator. For example, given the following code that adds buttons and a label to Views containers:

IlvDisplay* display = new IlvDisplay("CSS Look and Feel", "", argc, argv);
display->setLookFeelHandler(display->getLookFeelHandler(IlGetSymbol("css")));
IlvContainer* container1 = new IlvContainer(display, "Container 1", "General Sibling Combinator", IlvRect(0, 0, 350, 400));
IlvContainer* container2 = new IlvContainer(container1, IlvRect(0, 280, 350, 200));
IlvButton* button1 = new IlvButton(display, "Button 1", IlvRect(50, 130, 250, 40));
IlvButton* button2 = new IlvButton(display, "Button 2", IlvRect(50, 180, 250, 40));
IlvButton* button3 = new IlvButton(display, "Button 3", IlvRect(50, 230, 250, 40));
IlvButton* button4 = new IlvButton(display, "Button 4", IlvRect(50, 0, 250, 40));
IlvMessageLabel* label = new IlvMessageLabel(display, "Message", IlvRect(50, 80, 250, 40));
// Add the gadgets, order will dictate application of general sibling combinator rule
container1->addObject("Label", label);
container1->addObject("Button1", button1);
container1->addObject("Button2", button2);
container1->addObject("Button3", button3);
container2->addObject("Button4", button4);
// Apply the general sibling combinator style
std::string CSS = "IlvMessageLabel ~ IlvButton { color: blue; }";
display->setStyleSheet(CSS.c_str(), CSS.length());

The order in which the gadgets are added to the container will dictate the application of the general sibling combinator rule.

The following general sibling combinator, specified with a tilde (~), will set blue color only for IlvButton gadgets 1, 2 and 3 since they are siblings to IlvMessageLabel but the rule will not be applied to button 4 since it is not a sibling of the message label.

IlvMessageLabel ~ IlvButton {
color: blue;
}

The general sibling combinator will apply the rule to all sibling gadgets, that is, gadgets that are at the same level as the named gadget.

Adjacent Sibling Combinator

Similar to the general sibling combinator, the adjacent sibling combinator also will apply the given rule to siblings but in the adjacent sibling case all the siblings must be adjacent to each other. For example, given the following adjacent sibling combinator rule:

IlvButton + IlvButton {
color: blue;
}

In this case, the adjacent sibling combinator, defined with a plus sign (+), will only apply to the IlvButton gadget's siblings that are immediately beside each other. Given the Views code below:

IlvDisplay* display = new IlvDisplay("CSS Look and Feel", "", argc, argv);
display->setLookFeelHandler(display->getLookFeelHandler(IlGetSymbol("css")));
IlvContainer* container = new IlvContainer(display, "Container", "Adjacent Sibling Combinator", IlvRect(0, 0, 350, 500));
IlvButton* button1 = new IlvButton(display, "Button 1", IlvRect(50, 80, 250, 40));
IlvButton* button2 = new IlvButton(display, "Button 2", IlvRect(50, 130, 250, 40));
IlvButton* button3 = new IlvButton(display, "Button 3", IlvRect(50, 180, 250, 40));
IlvButton* button4 = new IlvButton(display, "Button 4", IlvRect(50, 300, 250, 40));
IlvButton* button5 = new IlvButton(display, "Button 5", IlvRect(50, 360, 250, 40));
IlvMessageLabel* label = new IlvMessageLabel(display, "Message", IlvRect(50, 240, 250, 40));
// Add the gadgets, order will dictate application of adjacent sibling combinator rule
container->addObject("Button1", button1);
container->addObject("Button2", button2);
container->addObject("Button3", button3);
container->addObject("Label", label);
container->addObject("Button4", button4);
container->addObject("Button5", button5);
// Apply the adjacent sibling combinator style
std::string CSS = "IlvButton + IlvButton { color: blue; }";
display->setStyleSheet(CSS.c_str(), CSS.length());

The order in which the gadgets are added to the container will dictate the application of the adjacent sibling combinator rule.

The rule would only be applied to Button2, Button3 and Button5.

Attribute Selector

An Attribute selector is used to define a style rule for a set of gadgets all associated by a specific attribute name and optional value. The selector is specified by using square brackets and a name and optional value for the attribute name. Views gadgets do not support class selector names yet but will in an upcoming release.

Pseudo-class

A pseudo-class is used to define rule for a pseudo-state that a Views gadget might be in. For example, a designer may want a button's background color to be #404040 and the text to bold whenever a user hovers their mouse over a button. This would be defined with the following pseudo-class rule:

IlvButton:hover {
background-color: #404040;
font-style: bold;
}

Pseudo-class rules are defined using the element and pseudo-state, separated by a colon. In the example above, all IlvButton gadgets in a hover state will have the rule applied to them. See the Views Style Sheets Reference for the full set of pseudo-states that are supported by each Views gadget.

Pseudo-class rules can be negated with the exclamation operator. As shown in the following example, all IlvButton's text will be blue when they are not in hover state.

IlvButton:!hover {
color: blue;
}

More than one pseudo state may apply to a Views gadget. For example, an IlvToggle has a checked and hover state. Defining a CSS rule to apply to multiple states in a logical AND operation is accomplished through pseudo-state chains. The following example sets the text color to red for IlvToggle gadgets that are being hovered over and are checked. The text color is set to green when being hovered over and not checked.

IlvToggle:hover:checked {
color: red;
}
IlvToggle:hover:!checked {
color: green;
}

Finally, applying pseudo states in a logical OR operation is accomplished by separating the selectors by a comma. In the following case the text of the IlvToggle is set to red if the gadget is checked or in hover state.

IlvToggle:hover, IlvToggle:checked {
color: red;
}

See Views Style Sheets Reference for the full list of supported pseudo states for each Views gadget.

Sub-Controls

Several Views gadgets contain inner components that are part of the overall complex construction. To style inner components of complex gadgets subcontrols are used in conjunction with the selector. As an example, The OpenMenu subcontrol is used to style the button to show the dropdown menu for an IlvComboBox.

IlvComboBox OpenMenu {
background-color: #ccc;
}

Pseudo states can also be combined with subcontrols to further specify rules. In the following example, the IlvComboBox dropdown menu button's background color is changed to blue when the menu is hovered over.

IlvComboBox OpenMenu:hover {
background-color: blue;
}

See the Views Style Sheets Example documentation for the full list of supported subcontrols for each Views gadget.

Rule Conflict Resolution

As multiple rules are added to a stylesheet conflicts will arise on how to apply them. For example, the following two rules apply a text color for a IlvMessageLabel.

IlvMessageLabel#cancelButton {
color: blue;
}
IlvMessageLabel {
color: black;
}

Both rules apply to IlvMessageLabels but there is a conflict on when to set the color property. To resolve the conflict, the specificity of the rules must be taken into account. In this case, the first rule is more specific and only applies to an IlvMessageLabel with the ID cancelButton, overriding the second rule applies which sets the text color to black for all IlvMessageLabel gadgets.

Specificity can also apply to pseudo-states. In the following example, the hover pseudo-state is more specific to the IlvButton and will override the general rule for IlvButtons.

IlvButton:hover {
background-color: lightblue;
}
IlvButton {
background-color: blue;
}

In the case where specificity is the same then conflict resolution is accomplished based on the order of the rules. In the following example, the specificity of the pseudo-states is the same. All enabled IlvButtons will have lightblue text but when hovered over their text color will be changed to blue.

IlvButton:enabled {
color: lightblue;
}
IlvButton:hover {
color: blue;
}

To change how the rules are applied simply reorder the rules.

IlvButton:hover {
color: blue;
}
IlvButton:enabled {
color: lightblue;
}

Or, change the specificity of the rules so it is clear when to apply one rule over the other.

IlvButton:hover:enabled {
color: blue;
}
IlvButton:enabled {
color: lightblue;
}

Views style sheets follow the CSS2 rules for specificity.

A selector's specificity is calculated as follows:

  • count the number of ID attributes in the selector (= a)
  • count the number of ID attributes in the selector (= b)
  • count the number of other attributes and pseudo-classes in the selector (= c)
  • count the number of element names and pseudo-elements in the selector (= d)

Concatenating the four numbers a-b-c-d (in a number system with a large base) gives the specificity.

Some examples:

*             {}  /* a=0 b=0 c=0 d=0 -> specificity = 0,0,0,0 */
li            {}  /* a=0 b=0 c=0 d=1 -> specificity = 0,0,0,1 */
ul li         {}  /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */
ul ol+li      {}  /* a=0 b=0 c=0 d=3 -> specificity = 0,0,0,3 */
h1 + *[rel=up]{}  /* a=0 b=0 c=1 d=1 -> specificity = 0,0,1,1 */
ul ol li.red  {}  /* a=0 b=0 c=1 d=3 -> specificity = 0,0,1,3 */
li.red.level  {}  /* a=0 b=0 c=2 d=1 -> specificity = 0,0,2,1 */
#x34y         {}  /* a=0 b=1 c=0 d=0 -> specificity = 0,1,0,0 */

Styling at the Application, Container and Gadget Levels

In Views, CSS rules are applied through a stylist and stylists are applied to the children of the stylist. The following sections describe how to apply styles across an entire Views application through the display, at the container level and for the future, how they will be applied at the gadget level. For an running example, see the multiple_stylists sample.

Applying CSS to the Views application

A View's application display object, type IlvDisplay, contains a stylist that is utilized by all containers and gadgets in the application. The most common approach for applying CSS rules to an application is to set a style sheet on the display. The following code snippet shows an example.

// Define an inline set of CSS rules
const std::string DEFAULT_CSS = R"(
IlvButton { color: white; background: red; }
IlvButton:hover { background: #6214ef; }
)";
int main(int argc, char *argv[])
{
IlvDisplay* display = new IlvDisplay("LookFeel", "", argc, argv);
// Specify the css Look and Feel handler for this display
display->setLookFeelHandler(display->getLookFeelHandler(IlGetSymbol("css")));
...
// Set the overall style sheet rules for the application stylist through the display
display->setStyleSheet(DEFAULT_CSS.c_str(), DEFAULT_CSS.length());
}

In this example a default set of CSS rules are applied to the Views display. All gadgets within the application will utilize the style sheet rules and any IlvButton will have white text with a red background. When the button is in hover state, the background color will be changed to #6214ef.

Applying style sheet rules at the container level

Within the Views application, CSS rules are set at either the IlvDisplay or IlvContainer level through their stylists. When defining CSS rules at the container level gadgets within the container will apply rules from the container level after any rules are applied from the display level, allowing any of the rules at the display level to be overriden. For example, if a rule is set at the IlvDisplay level to set an IlvButton's background color to be red is redefined to be blue then the final background color for the gadget will be blue. The following example exhibits this scenario in code.

// Define an inline set of CSS rules for the application
const std::string DEFAULT_CSS = R"(
IlvButton { color: white; background: red; }
IlvButton:hover { background: #6214ef; }
)";
// Define an inline set of CSS rules for the container
const std::string CONTAINER_CSS = R"(
IlvButton { color: black; background: white; }
)";
int main(int argc, char *argv[])
{
IlvDisplay* display = new IlvDisplay("LookFeel", "", argc, argv);
// Specify the css Look and Feel handler for this display
display->setLookFeelHandler(display->getLookFeelHandler(IlGetSymbol("css")));
...
// Set the overall style sheet rules for the application stylist through the display
display->setStyleSheet(DEFAULT_CSS.c_str(), DEFAULT_CSS.length());
// Create a container for gadgets and apply CSS to its stylist
IlvGadgetContainer* container = new IlvGadgetContainer(display, "My Container", "My Container", IlvRect(0, 0, 220, 110), false, true);
container->setStyleSheet(CONTAINER_CSS.c_str(), CONTAINER_CSS.length());
}

In this example, buttons in "My Container" will have a white background and black text, overriding the white text and red background defined at the display stylist level. When the button is in hover state though, background color #6214ef will still be applied.

Applying style sheet rules at the gadget level

Views gadgets use the stylist from the container they are within or, if no styles are defined at that level, the overall display level stylist.

« Overview of Views Style Sheets Views Style Sheets Reference »

IlvRect
Geometric class.
Definition: IlvBaseGeometry.h:805
IlvDisplay::getLookFeelHandler
IlvLookFeelHandler * getLookFeelHandler(IlSymbol *name) const
Returns the look and feel handler whose name is specified.
IlvContainer
View container class.
Definition: contain.h:212
IlvDisplay
Display class.
Definition: ilv.h:354
IlvDisplay::setLookFeelHandler
void setLookFeelHandler(IlvLookFeelHandler *lfh)
Sets the current look and feel handler.
Definition: ilv.h:2435
IlvContainer::addObject
virtual void addObject(IlvGraphic *obj, IlBoolean redraw=IlFalse)
Adds an object at the top of the container list.
IlvStylist::setStyleSheet
IlBoolean setStyleSheet(std::istream &file)
Applies styling information to this stylist.