Interface Skinning


public interface Skinning

Skinning / Theming

Skinning (aka "theming" or "branding") is the process of modifying Smart GWT's default look and feel to match the desired look and feel for your application. Smart GWT supports an extremely powerful and simple skinning system that allows designers with a basic grasp of CSS and JSON to skin any Smart GWT component.

See the Skin Editor overview for information about the most modern approach to skinning a Smart GWT application.

Basics

  • Smart GWT components create their visual appearance by dynamically generating HTML, within the browser, using JavaScript.
  • the HTML generated by Smart GWT components contains CSS style names and URLs to images
  • Smart GWT components can be skinned by replacing the CSS styles and images that the components use by default, or by setting properties on components to configure them to use new CSS styles and new image URLs.
  • You can change the appearance of an individual Smart GWT component by calling setter methods such as setStyleName() or setBackgroundColor(), or you can skin all components of the same class at once, by using Canvas.setDefaultProperties() to change the defaults for the class.
  • CSS is used to control details of appearance such as fonts, borders and background colors and gradients, but component properties are used to control layout and positioning of components. See CSSStyleName for more details about correct usage.
  • A "skin" consists of:
    • skin_styles.css - a CSS stylesheet containing all CSS styles used by Smart GWT components
    • images/ - a directory tree of images organized by component
    • load_skin.js - a JavaScript file that loads the CSS stylesheet, applies the images and modifies any other component or framework default settings required for the skin
  • The example skins that come with Smart GWT are inside smartgwt.jar and smartgwt-skins.jar as GWT modules. The standard directory layout for a skin is:
             skin_styles.css
             load_skin.js
             images/
                 Actions/
                     add.png 
                     ...
                 ListGrid/
                     sort_ascending.png
                     ...
                 Tab/
                 ... other directories containing
                     component or shared media ...
      
  • A skin is implicitly loaded when you add an <inherits> tag in your .gwt.xml file to include SmartGWT components (name="com.smartgwt(ee).SmartGWT(Pro|Power|EE)"). To switch skins, add the "NoTheme" suffix to the "name" attribute of this <inherits> tag, then add <inherits name="com.smartclient.theme.enterpriseblue.SkinName"/>. These tags cause a <SCRIPT SRC=> tag to be injected into your bootstrap .html page, which loads load_skin.js for the appropriate skin. load_skin.js loads the stylesheet and sets the CSS styleNames and media URLs that Smart GWT components will use.
  • The modern "Flat" skins (such as Tahoe and Shiva) are customized through CSS variables and a JSON skin definition - see the Customizing Skins overview.

Browser support

The recent skins - and all of Smart GWT's skinning tools - style the interface with modern CSS, including CSS custom properties and features such as oklch() and color-mix(), which current browsers support directly. There is nothing to enable.

Some very old, legacy skins predate full CSS support in browsers (notably older versions of Internet Explorer) and rendered details such as borders, rounded edges and button backgrounds with images instead. Those skins are standalone; they are not related to the modern skins, the Skin Editor, or compact skins.

Changing Density

Smart GWT provides APIs that allow the general spaciousness of an application to be increased beyond the design of the loaded skin. You can see the feature in use in our online showcase, by loading a sample and picking options from the Density picker shown above it.

The Density mechanism effectively zooms the application, by calling Canvas.resizeFonts() and Canvas.resizeControls(), APIs which uniformly alter the sizes of fonts in the skin's CSS-styles, and the heights of most builtin widgets, by the pixel amounts passed to them. These calls must be made after the skin is loaded, but before any components have been created.

You can apply any amounts you wish, to get your desired look - the Densities available in the online Showcases are achieved with the following calls to resizeFonts and resizeControls:

DensitySettings
DenseresizeFonts(0) & resizeControls(0)
CompactresizeFonts(1) & resizeControls(2)
MediumresizeFonts(2) & resizeControls(4)
ExpandedresizeFonts(2) & resizeControls(6)
SpaciousresizeFonts(3) & resizeControls(10)

Spriting

Smart GWT also makes use of a CSS technique known as "spriting" to improve performance when rendering certain user interface images. This technique improves performance when rendering a number of small images within an application. Instead of loading a separate image file for each element, this technique involves creating a single composite image file consisting of smaller images sewn together, and using css background-sizing and offset to display the desired portion of this larger image within elements on a page.

This reduces the overall file size for the media as the combined image's size will typically be significantly less than the sum of the sizes of the smaller images. It also allows the browser to issue a single HTTP request for the composite image instead of separate requests for each image element showing parts of this composite image.
For example, the up and down arrow images of a SpinnerItem in the normal, "Focused", and "Disabled" states can be combined into one image. The file size of the combined image is typically ~65% smaller than the sum of the file sizes of the 6 constituent images, and a single HTTP request provides media for all 6 states.

Spriting typically results in reduced load times and eliminates noticeable delays in changes of component appearance while the browser downloads a required image. It is natively supported in all browsers.

One consideration when using spriting is how to handle images being rendered at different sizes on the page. Simply increasing the size of an element using CSS to display a portion of a larger background image will not change the scale of that image - instead more of the image will be revealed to the user. This can result in visual glitches, for example, the user may be able to see other sprited elements from the larger background image.
If the "native" size of the image sprite is known as well as the desired rendered size scaling can be achieved. For Smart GWT image attributes that support the special sprited image URL format, this can be specified, allowing the image to be rendered at various sizes.

Our Flat series of skins (Tahoe, Stratus, Twilight and Obsidian) make use of the sprite-URL capability to ensure that sprited images appear correctly regardless of the size at which they are being drawn.
The Enterprise, EnterpriseBlue, and Graphite skins also support spriting of user interface images, but do so via settings embedded in the css applied to certain elements instead of using the sprite-URL capability. As such if certain component metrics (such as the height of a component or padding) are changed, then the image sprites may no longer work. In this case, spriting can be disabled by setting the JavaScript global variable isc_spriting to "off" before any of the Smart GWT libraries are loaded. For example:

    <script>isc_spriting = "off";</script>
  
Possible settings are:

  • "supported" :
    (default setting) Spriting will be used in browsers that fully support it
  • "off" :
    Spriting will not be used

Note - it is also possible to arrange arbitrary SVG graphics into a format which the framework can treat as a sprite, despite SVG not being images in the traditional sense. SVG graphics scale perfectly and, in the sprite format, can be re-used and re-colored at runtime without server trips, sizable DOM modifications or flickering. See the SVG Symbols overview for more information.

Modifying Skins

Skin Editor

To create new skins and easily make bulk changes to details like colors and fonts, see our Skin Editor tool, which can be accessed online, or locally in your environment if you have a Pro or better license.

Manually

To modify a skin, first create a copy of one of the skins that comes with the Smart GWT SDK, then modify the copy. Full instructions are provided in Chapter 9 of the QuickStart Guide.

For the modern "Flat" skins (Tahoe, Shiva, Stratus, Twilight and Obsidian), the recommended approach is the Skin Editor, which provides a UI for editing the skin's CSS variables and custom styles. You can also edit a skin's config.json directly - see the Customizing Skins overview.

Locating Skinning Properties

Starting from the name of the component

Given a Smart GWT component that you want to skin, open its JavaDoc:

  • for properties that set CSS styles, look for properties whose name includes "style", eg Button.baseStyle
  • for properties that control URLs to media, look for properties whose name includes "src", "image" or "icon", such as Img.src
  • for subcomponents that also support skinning, look for properties that are documented as being "AutoChildren" and check the reference for the type of the AutoChild for settable properties. For example, Window.minimizeButton is an ImgButton and therefore supports ImgButton.src.

Starting from a running example

Specific browsers offer alternate approaches to quickly discover the images or style names being used for a part of a Smart GWT component's appearance:

  • the Firefox browser offers a dialog via Tools->"Page Info" that gives a manifest of media used in the page.
  • the Firebug extension for Firefox has an "Inspect" feature that allows you to see the HTML, CSS and media in use for a given area of the screen
  • right clicking (option-click on a Mac) on an image and choosing "Properties" shows a dialog that provides the image URL in most browsers. Tips:
    • if a Smart GWT component is showing text over an image, right-click at the very edge of the underlying image to get image properties rather than information about the text label
    • on some browsers, in order to see the full image URL, you may need to drag select the partial URL of the image shown in the properties dialog

Image URLs in Smart GWT

Properties that refer to images by URL, such as Img.src and Button.icon, are specially interpreted in Smart GWT to allow for simpler and more uniform image URLs, and to allow applications to be restructured more easily.

Unlike the URL used with an HTML <IMG> element, the image URL passed to a Smart GWT component is not assumed to be relative to the current page. See SCImgURL for a full explanation of the default application image directory, and the meaning of the "[SKIN]" prefix.

Specifying Image URLs

Default image URLs for Smart GWT components are specified in load_skin.js via JavaScript, using calls to Class.addProperties() and Class.changeDefaults(). For example, the load_skin.js file from the "Enterprise" skin includes the following code to establish the media used by Window.minimizeButton:

     isc.Window.changeDefaults("minimizeButtonDefaults", {
          src:"[SKIN]/Window/minimize.png"
     });
  

NOTE: These are JavaScript APIs and hence do not appear in SmartGWT JavaDoc - you may want to refer to the SmartClient Reference available at Isomorphic.com for these specific APIs.

Specifying Image Sizes

Many Smart GWT components must know some image sizes in advance, in order to allow those components to autosize to data or content.

For example, the ImgTabs used in TabSets are capable of automatically sizing to a variable length Tab.title. To make this possible, Smart GWT must know the sizes of the images used as "endcaps" on each tab in advance.

Like image URLs, image sizes are specified in load_skin.js. The following code sample establishes the default size of the "endcaps" for tabs, by setting a default value for ImgTab.capSize:

      isc.ImgTab.addProperties({
          capSize:4
      })
  

Statefulness and Suffixes

Some components or areas within components, including buttons and the cells within a grid, are "stateful", meaning that they can be in one of a set of states each of which has a distinct visual appearance.

Stateful components switch the CSS styles or image URLs they are using as they transition from state to state, appending state information as suffixes on the style names or URL. See Img.src and Button.baseStyle for details and examples.

Smart GWT has built-in logic to manage a series of state transitions, such as:

  • "rollover": showing a different appearance when the mouse is over a component
  • "button down": showing a different appearance when the mouse is pressed over a component
  • "disabled": showing a different appearance when a component cannot be interacted with
  • "selected": showing one of a set of components in a different state to indicate selection
Flags on some components, such as ImgButton.showRollOver, allow you to control whether the component will switch CSS style or image URL when the component transitions into a given state.

StretchImg: 3-segment stretchable images

A StretchImg is a Smart GWT component that renders out a compound image composed of 3 image files: two fixed-size end-cap images and a stretchable center segment. Like stateful components, the names of each image segment is appended to the image URL as a suffix. See StretchImg.src for details.

EdgedCanvas

Similar to a StretchImg, an EdgedCanvas provides an image-based decorative edge around and/or behind another component, with up to 9 segments (a 3x3 grid). Decorative edges can be added to any component by setting showEdges:true. EdgedCanvas is also used to construct drop-shadows, which can be enabled on any component via showShadow:true.

Advanced: setScClassName()

In rare situations, such as trying to share a skin between a SmartClient and Smart GWT application, you may have a SmartClient class that has been defined to hold certain skin settings where there is no corresponding Smart GWT class. For example, you might have a SmartClient subclass of ListGrid called "LedgerGrid" that changes cell styles to appear more like a ledger.

In this case, you can generally use the Smart GWT class that is the nearest superclass of the SmartClient class (ListGrid in this case), then use a call to setScClassName("LedgerGrid") to cause the SmartClient class to be used as the underlying SmartClient class used by the GWT ListGrid instance.

Where to put skin-related JavaScript

If you're creating a custom skin, you can place JavaScript snippets such as those shown above in your custom skin's load_skin.js file. If you prefer not to create a custom skin for small customizations, you can execute JavaScript via a JSNI method in your Java code. With this latter approach, be sure to change "isc." to "$wnd.isc." wherever it appears, and to call the JSNI method before creating any SmartGWT components.

Limitations

In most cases, using newer CSS features such as CSS3 prefix attribute selectors or CSS3 pseudo-classes in a skin will just work, provided the browser supports those CSS features. However, in some cases, Smart GWT needs to be able to extract style information from CSS style declarations. For this reason, only single class name selectors are officially supported (e.g. .myButton, .myButtonDown) and @-rules are not supported.