Fri 7 Oct 2011
A guide to custom themes in ExtJS 4
Background
I’ve never liked having to solve a problem in a different way for different browsers. Yes, I’m talking about you Internet Explorer. We’ve dropped support for IE6 at Rally (it still has to work, but is far from pixel perfect), but we still have many customers using IE7+.
Before version 4, ExtJS catered to the lowest common denominator. That meant relying on images for rounded corners, shadows, etc. Even in modern browsers that support CSS3 styles for border radius and the like ExtJS used cross-browser compatible solutions. In ExtJS 4 this changed for the better, using the capabilities of CSS3 when available and falling back to images when not.
What if you want a different look and feel than what comes for free out of the box? Will you have to override styles for both modern and legacy browsers? Yes, you could do that. Thankfully ExtJS 4 introduced some theming shortcuts using SASS and Compass.
By overriding the ExtJS default theme variables or by creating your own Component UIs (used in the ‘ui’ option of component configs), the styles for modern and legacy browsers are generated for us. The best part? The images required for older browsers can be generated too!
It took me a bit of time to track down exactly what was possible with theming. Sencha’s guide gets you most of the way. Here’s the quick and dirty.
Guide to Theming
Note: I’m running on a mac. The steps are pretty similar for other systems. This is also based on ExtJS 4.0.6.
Setup
1. Install Compass
# gem install compass
This will install Compass and its dependencies, including SASS.
2. Download and Install Sencha SDK Tools
http://www.sencha.com/products/sdk-tools/
This includes the command line utilities used to generate images.
WARNING: It’s still in Beta (currently version 1.2.3). I’ve run into several rough edges.
3. Copy theme structure from ExtJS source
I’m starting with the Application Structure as recommended by the Getting Started Guide, section 2:
+ MyApp
+ app
+ extjs
+ resources
+ css
+ images
- app.js
- index.html
Copy everything from extjs/resources/themes/templates/resources/sass to MyApp/resources/sass.
Copy everything from extjs/resources/themes/images/default to MyApp/resources/images.
If you don’t follow the structure above for your app, update MyApp/resources/sass/config.rb to point to the correct location of the extjs source:
$ext_path = “../../extjs”
4. Make sure we can compile the styles.
Go to MyApp/resources/sass. Run:
# compass compile
This should generate MyApp/resources/css/my-ext-theme.css.
Add Customizations
We have two ways to customize the look and feel. We can change global SASS variables to affect the UI of every ExtJS component (easy), or we can create custom Component UIs (harder, but more flexible).
We’re going to start with a plain Ext.window.Window (a modal dialog) and modify it with both global variables and then a custom UI.
Theming with Global SASS Variables
In MyApp/index.html:
<html>
<head>
<link rel="stylesheet" type="text/css" href="resources/css/my-ext-theme.css">
<script type="text/javascript" src="extjs/ext.js"></script>
<script type="text/javascript" src="app.js"></script>
</head>
<body></body>
</html>
And in MyApp/app.js:
Ext.application({
name: 'My App',
launch: function() {
Ext.create('Ext.window.Window',{
title: 'Custom Window',
width : 200,
height : 150,
modal: true,
layout: 'fit',
items: {
xtype: 'form',
html: 'Form Content',
border: 0,
buttons: [{
text: 'close'
}]
}
}).show();
}
});
You’ll see this window when you open index.html:

1. Update the $base-color
In MyApp/resources/sass/my-ext-theme.scss you’ll find this line:
// Insert your custom variables here.
Add a line below the comment with something like this:
$base-color: red;
2. From MyApp/resources/sass, run:
# compass compile
And we end up with this in Chrome:

You’re thinking “red? really?” Go find yourself a better color scheme: http://colorschemedesigner.com/.
Unfortunately it doesn’t look as great in IE.

3. To fix this, we need to generate the images for the corners. First, you have to fix a bug in Ext so that the images are pulled from the correct place.
Change line 62 of MyApp/extjs/resources/themes/lib/utils.rb from this:
images_path = File.join($ext_path, ‘resources’, ‘themes’, ‘images’, theme)
to this:
images_path = relative_path
4. Next, from the MyApp directory, run this command (Sencha SDK Tools must be installed):
# sencha slice theme -d ./extjs -c ./resources/css/my-ext-theme.css -o ./resources/images
In MyApp/resources/images/window and MyApp/resources/images/window-header we should have images with the color we set above. IE should now look like Chrome.
What types of variables can we set? They’re all listed in the extjs/resources/themes/stylesheets/ext4/default/variables directory.
Theming with Custom Component UIs
Let’s make the ‘close’ button on the window green. Instead of changing all ExtJS buttons to be green, we’ll create a component UI to do it.
Downside: The image generation support using “sencha slice theme” isn’t quite there yet. I’ve been able to generate images for custom panel UIs, but not custom buttons nor custom windows. You’ll have to revert to creating the images yourself.
1. Add a ui property to the button
The new app code:
Ext.application({
name: 'My App',
launch: function() {
Ext.create('Ext.window.Window',{
title: 'Custom Window',
width : 200,
height : 150,
modal: true,
layout: 'fit',
items: {
xtype: 'form',
html: 'Form Content',
border: 0,
buttons: [{
text: 'close',
ui: 'green'
}]
}
}).show();
}
});
The only change from what we had before was to add ui: ‘green’ to the button config.
2. Make a green button theme
in MyApp/resources/sass, create a new file called _myapp-buttons.scss, with the following content:
@include extjs-button-ui(
/* UI + Scale */
'green-small',
$border-radius: $button-small-border-radius,
$border-width: $button-small-border-width,
$border-color: green,
$border-color-over: green,
$border-color-focus: green,
$border-color-pressed: green,
$border-color-disabled: green,
$padding: $button-small-padding,
$text-padding: $button-small-text-padding,
$background-color: green,
$background-color-over: green,
$background-color-focus: green,
$background-color-pressed: green,
$background-color-disabled: green,
$background-gradient: $button-default-background-gradient,
$background-gradient-over: $button-default-background-gradient-over,
$background-gradient-focus: $button-default-background-gradient-focus,
$background-gradient-pressed: $button-default-background-gradient-pressed,
$background-gradient-disabled: $button-default-background-gradient-disabled,
$color: $button-default-color,
$color-over: $button-default-color-over,
$color-focus: $button-default-color-focus,
$color-pressed: $button-default-color-pressed,
$color-disabled: $button-default-color-disabled,
$font-size: $button-small-font-size,
$font-size-over: $button-small-font-size-over,
$font-size-focus: $button-small-font-size-focus,
$font-size-pressed: $button-small-font-size-pressed,
$font-size-disabled: $button-small-font-size-disabled,
$font-weight: $button-small-font-weight,
$font-weight-over: $button-small-font-weight-over,
$font-weight-focus: $button-small-font-weight-focus,
$font-weight-pressed: $button-small-font-weight-pressed,
$font-weight-disabled: $button-small-font-weight-disabled,
$font-family: $button-small-font-family,
$font-family-over: $button-small-font-family-over,
$font-family-focus: $button-small-font-family-focus,
$font-family-pressed: $button-small-font-family-pressed,
$font-family-disabled: $button-small-font-family-disabled,
$icon-size: $button-small-icon-size
);
Notice also that the name of the component UI is ‘green-small’, and we reference it as just ui: green. This is only for buttons, where we could define ‘green-small’, ‘green-medium’, and ‘green-large’. Most component UIs don’t have multiple sizes.
How do you know all the options? Grep the ExtJS source for their usage:
grep -rl ‘\@include extjs-.*-ui’ extjs
For example, in the results you’ll see extjs/resources/themes /stylesheets/ext4/default/widgets/_window.scss, and in that file you’ll find a usage of “@include extjs-window-ui“. I use these as a starting point for any custom UIs I create. I haven’t found them to be documented anywhere else.
3. Add to main stylesheet
In MyApp/resources/sass/my-ext-theme.scss, add this to the bottom:
@import ‘myapp-buttons’;
4. Compile SASS
Go to MyApp/resources/sass, and run:
# compass compile
(You can also run “compass watch“, which will continually monitor the SASS files for changes).
Here’s what we end up with:

(I know you love the green on red color scheme, admit it.)
And there we have it! Like I noted before, I haven’t been able to generate images for button UIs. If you’ve had better luck, please let me know!

Great tut. Thanks for making the effort to do this for the community.
It would be great if someone could also do a tutorial with custom icons (aka different tools like win 7 window buttons for example as shown in the wikiOffice desktop) to show an example of other than colouring how to create a new theme.
In order to have the button images generated you have to create a manifest.js file, within a declaration of the custom uis you created :
Ext.onReady(function() {
Ext.manifest = {
widgets : [{
xtype : 'widget.button',
ui : 'green'
}/*etc*/]
};
});
and add the following :
-m ./path/to/manifest.js
to the sencha slice theme command
The command will only generate images for the ui indicated in the manifest files, so you may have to fire the sencha slice command for both “default” and “custom” ui.
Hope it will help somebody
how i create a theme for a grid??
A guide to custom themes in ExtJS 4 ยป Rally Engineering Blog…
Thank you for submitting this cool story – Trackback from JavaPins…
I am getting this error when running sencha slice theme:
C:\workspace\theming-extjs>sencha slice theme -d ./extjs
-c ./resources/css/my-ext-theme.css -o ./resources/images -verbose
C:\Program Files (x86)\SenchaSDKTools-1.2.3\command\\src\CliOptions.js:127
TypeError: this.get is not a function
Execution error in C:\Program Files (x86)\SenchaSDKTools-1.2.3\command\sencha.js
Any idea?
I am using Sencha SDK 1.2.3