Sencha Inc. | HTML5 Apps

Blog

4 Tricks for Smaller CSS in Sencha Touch 2.2

July 11, 2013 | Ivan Jouikov

Optimizing Sencha Touch CSS I recently had the pleasure of optimizing an app written in Sencha Touch 2.2 that was taking over 5 seconds to load on an Android 2.x device. The culprit was a 1.2 MB app.css file that I managed to bring down to just over 100 kB, resolving the issue. Here I present four techniques used to achieve this goal, along with individual outcome metrics. As a precursor to this article, I highly recommend that you read the Sencha Touch Theming Guide.

Avoid Redundant @import

Result: 1.23 MB -> 253 kB

This is a common mistake and by far the biggest impact on CSS bloat. By default, you have an app.scss file that has these two lines:

@import 'sencha-touch/default';
@import 'sencha-touch/default/all';

You can do all your work in this file, but with an app of any size you will soon need to split this up. You will write some of your code in a separate file and then import that separate file back into your app.scss by adding the following line to it:

@import 'MySeparateFile';

Inside MySeparateFile.scss, you should not re-import the ‘sencha-touch/default’ and ‘sencha-touch/default/all’. Bear in mind that this causes any generated CSS to be re-included in the final app.css. In my app, the redundant import was repeated multiple times in custom .scss files, resulting in almost a megabyte of CSS bloat.

Exclude Default Font and Icons

Result: 253 kB -> 156 kB

Sencha Touch 2.2 uses web fonts for icons and by default the entire set of nearly 100 icons are base64-jammed into the compiled app.css. If you’re using custom icons, you probably don’t need this. Luckily, this is very easy to turn off by setting the following variables in your app.scss:

$include-pictos-font: false;
$include-default-icons: false;

For a better understanding of the difference between these two options, I suggest you dive into the .scss source code in the Sencha Touch resources folder. If you’re using components like search fields or select fields, which use default icons for their default behavior, you might need to override their .scss to use icons from your custom font.

Exclude Experimental CSS

Result: 156 kB -> 144 kB

This Compass article explains the concept very well. In summary, there is a lot of “experimental” CSS that Compass generates to accommodate not only the actual experimental prefixed features of common browsers, but to also account for “minority” browsers that you probably aren’t supporting anyway. All you have to do is add the following in your app.scss:

$experimental-support-for-mozilla : false;
$experimental-support-for-webkit : false;
// $support-for-original-webkit-gradients : false;
$experimental-support-for-opera : false;
$experimental-support-for-microsoft : false;
$experimental-support-for-khtml : false;

Notice how I commented out the 3rd line. My app was using a select field (aka combo box) for Android 2.x support, which uses old-style webkit gradients to achieve this effect in compact scenarios:

Optimizing Touch CSS

If I were to uncomment the 3rd line and recompile, I would see:

Optimizing Touch CSS

Exclude Unused Touch SASS

Result: 144 kB -> 120 kB

Similar to how the class dependencies in Touch allow us to compile a JavaScript file with only the parts of the framework we need, we can achieve the same effect with CSS, albeit with more effort. I should warn you: you will probably need to dive into SASS source to effectively perform this step. For instance, the SASS file for select fields uses mixins defined in the SASS file for checkboxes. This means if your app is not using checkboxes, you might want to extract that mixin from the checkbox’s .scss file, assuming you don’t want to include the rest of the checkbox SASS.

Let’s recap; the default app.scss has these two lines:

@import 'sencha-touch/default';
@import 'sencha-touch/default/all';

The source code for these files is located in:

touch2.2/resources/themes/stylesheets/sencha-touch/_default.scss
touch2.2/resources/themes/stylesheets/sencha-touch/default/_all.scss

If you follow the source, the first file pretty much imports a bunch of .scss files from the “var” folder, which sets up various SASS variables. You will probably want to keep this file.

The second file imports the actual SASS used by individual components; it looks something like this:

...
@import 'Button';
@import 'Panel';
@import 'Sheet';
@import 'MessageBox';
@import 'Toolbar';
@import 'carousel/Carousel';
@import 'form/Panel';
...

The easiest way to go about this task is to take out “all” from your app.scss:

// @import 'sencha-touch/default/all';

…and in its place put the individual imports from _all.scss; i.e. if you only use message boxes and toolbars in your app, you would add the following to app.scss:

@import 'MessageBox';
@import 'Toolbar';

When you try to compile this, you will likely run into some pathing issues. Fix:

@import 'sencha-touch/default/src/_MessageBox.scss'; 
@import 'sencha-touch/default/src/_Toolbar.scss';

Conclusion

These performance techniques can shave multiple seconds off your initial page load, without affecting visuals or functionality. On older devices with an Edge connection, time savings could even exceed 10 seconds. Users form lasting impressions during the first few seconds of the app experience; don’t let that experience be a “Loading” icon.

P.S. I highly recommend the following articles on building a custom icon font for Sencha Touch 2.2:

There are 4 responses. Add yours.

Byron Draudson

9 months ago

Are you measuring the size of the download at the client or just the time it takes to download?  If size, does your measurement methodology include all downloaded elements such as images?

Ed de Jong

9 months ago

Congratulations Ivan on a job well done. Maybe I’m a bit old fashioned and I’m certainly not really into Sencha. But I can’t understand why any sensible developer could create (let alone release) over a megabyte of CSS and wonder why it doens’t download and render quickly. CPU cycles are available and cheap today, but that doesn’t take away the developer’s responsibily to think about what they’re doing.

raye

9 months ago

I realize that is the initial time while the web app is running as a native app.  Although it is all preloaded within the device, it will take couple of seconds if the external resources is not well trimmed and minified.  We should take the responsibility of shrinking the loading time. It is not difficult, only if the programmer is aware of it.

Ivan Jouikov

9 months ago

@Byron I was talking about the size of the actual generated .css file.

@Ed Thank you and I couldn’t agree more.

@Raye In this case it wasn’t a packaged app; it was still accessed over the browser, but you’re correct as the concept applies all the same.

Comments are Gravatar enabled. Your email address will not be shown.

Commenting is not available in this channel entry.