Sencha Inc. | HTML5 Apps

Blog

Getting Sassy with CSS

June 29, 2010 | David Kaneda

SASS + Compass is a powerful combinationEarly in the development of Sencha Touch, we decided to use SASS on top of CSS3 to ensure our themes were not just beautiful, but also flexible, easy to create, and resolution independent. SASS stands for Syntactically Awesome Stylesheets and adds nested rules, variables, mixins (similar to functions), and selector inheritance to traditional CSS.  SASS stylesheets are then compiled before being deployed, which provides an extra layer of optimization. Basically, it's like writing CSS as if it's 2099.

In this article, we'll cover a few of the techniques we used in creating Sencha Touch, while demonstrating how to make some flexible button styles. We will also be using Compass, an imported SASS file which adds commonly used grid, typography, and CSS3 mixins.

SASS is an essential part of Sencha Touch.
SASS is an essential part of Sencha Touch.

Installing SASS

SASS and Compass are both offered as Ruby Gems. To install them, fire up your terminal and enter the following (Note: you may need to use sudo to gain write permissions):

$ sudo gem install haml
$ sudo gem install compass

Next create the project structure, which should be something like:

  • myproject/
    • index.html
    • css/
    • sass/

We also have to create a Ruby config file (config.rb) in the sass/ directory, which should contain:

css_dir = "../css"
sass_dir = "../sass"

With those in place, we're all set to get started.

Step 1: Using Variables

In this example, we'll use SASS to create a simple set of buttons that look good in the modern browsers used in Google Android and Apple iOS devices. First, let's create the index.html, which will hold our demo:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <link rel="stylesheet" href="css/buttons.css" type="text/css" media="screen" charset="utf-8" />
</head>
<body>
    <div class="button_demo">
        <a href="#" class="button">I&#8217;m a button!</a>
    </div>
</body>
</html>

Then we create our SASS stylesheet at sass/buttons.scss:

@import 'compass/css3';

$base_color: #5291C5;
$button_size: 30px;

body {
  font-family: Helvetica;
  margin: 50px;
}

.button {
  line-height: $button_size;
  -webkit-box-sizing: border-box;
  padding: 0 $button_size/2;
  height: $button_size;
  display: inline-block;
  @include border-radius($button_size/2);
  border: 1px solid darken($base_color, 20%);
  @include linear-gradient(color-stops(lighten($base_color, 30%), lighten($base_color, 15%) 4%, $base_color));
  color: #fff;
  text-decoration: none;

&:active {
    @include linear-gradient(color-stops(darken($base_color, 30%), darken($base_color, 15%) 4%, darken($base_color, 7%)));
  }
}

Let's go through this section by section to see what's happening. First, we import the CSS3 library from Compass. This provides mixins for various CSS3 properties, which are easier to write and cross-browser compatible. As you'll see below, writing one border-radius() mixin generates the necessary additional CSS properties with vendor specific prefixes (e.g. -webkit-border-radius for Safari support).

We then define two variables, $base_color and $button_size, which we use to style the button.

Under the .button rules, notice that we use $button_size in a few places. First, we set it as the line-height and height of the button. We then do a math operation on the variable to create the border-radius ($button_size/2). This gives us a nice "pill" shape, ensuring the rounded corners are always half of the overall height.

When we create the button's background gradient, we use several SASS/Compass features at once. First, we use the Compass CSS3 mixin, linear-gradient, and color-stop function to generate the background gradient. This provides a single way to generate the gradient, which is compiled for browsers with varying gradient implementations. We also use the SASS 3 color functions, lighten, to manipulate our $base_color and create a nice highlight, which fades into the plain $base_color at the bottom.

At the bottom of the .button rule, you also notice a rule starting with &:active {. This is another great feature of SASS: the ability to nest rules. In addition to standard nesting, you can also reference the parent node in a child rule, which we do here with the ampersand. This helps keep our CSS rules organized and easy to read. This rule is the "pressed" state of our button, where we reverse the gradient (using darken() instead of lighten()) to give the impression that the button is being pushed down.

Compiling SASS to CSS

Now that we have the start of our SASS stylesheet, we'll need to compile it. To compile, open your terminal again and type:

compass compile sass

This generates the CSS file and places it in the css directory. We don't need to edit the CSS file at all (as it is generated by SASS/Compass), but for the sake of explanation, here's what the button class looks like in our CSS:

.button {
  line-height: 30px;
  -webkit-box-sizing: border-box;
  padding: 0 15px;
  height: 30px;
  display: inline-block;
  -moz-border-radius: 15px;
  -webkit-border-radius: 15px;
  -o-border-radius: 15px;
  -ms-border-radius: 15px;
  -khtml-border-radius: 15px;
  border-radius: 15px;
  border: 1px solid #2c5d85;
  background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #78a9d2), color-stop(4%, #9ec2df), color-stop(100%, #5291c5));
  background-image: -moz-linear-gradient(top, #78a9d2 0%, #9ec2df 4%, #5291c5 100%);
  color: #fff;
  text-decoration: none;
}

Notice that SASS and Compass take our $button_size variable (30px) and use it throughout the stylesheet, including when border-radius (15px) is calculated. Compass also includes the vendor-prefixed CSS for border radius and gradients for each browser that supports those modules.

Preview this step in a WebKit or Mozilla browser like Firefox, Safari, or Chrome.

Pass 2

Step 2: Converting button style into a mixin

The new .button class looks great, but what if we want to use different $base_colors and $button_heights for different classes/IDs? To make our new style more flexible, we'll convert it to a mixin:

@import 'compass/css3';

@mixin buttonize($base_color: #5291C5, $button_size: 30px) {
    -webkit-box-sizing: border-box;
    display: inline-block;
    color: #fff;
    text-decoration: none;

line-height: $button_size;

padding: 0 $button_size/2;
height: $button_size;
@include border-radius($button_size/2);

border: 1px solid darken($base_color, 20%);
@include linear-gradient(color-stops(lighten($base_color, 30%), lighten($base_color, 15%) 4%, $base_color));
text-shadow: darken($base_color, 10%) 0 -1px 0;

&:active {
  @include linear-gradient(color-stops(darken($base_color, 30%), darken($base_color, 15%) 4%, darken($base_color, 7%)));
}

}

body {
    font-family: Helvetica;
    margin: 50px;
  }
  .button {
    @include buttonize;
  }

  .green_button {
    @include buttonize(#3A8A20); // Green
  }

As you can see, mixins are defined by using @mixin, and accept parameters like functions in traditional programming languages. Likewise, these parameters can have default values. As you see, we take all the style declarations out of .button and put them in a new mixin, buttonize. We then call buttonize by using @include.

To demonstrate how this makes everything more flexible, we've added a new button class, .green_button, which passes a green color as the first parameter ($base_color). There is no second parameter set, so it will use our default of 30px. Now, if we add a second link in our HTML, like <a href="#" class="green_button">Text</a> we get a new button on the page that is just as rich as the first, but green instead of blue.

Preview this step in a WebKit or Mozilla browser like Firefox, Safari, or Chrome.

Pass 3

Using @extend

In addition to creating mixins, another powerful piece of SASS is the ability to extend previously defined classes. For this last iteration of our demo, we'll first convert our default $button_size variable to be 2em. This makes our sizing be relative to the element's font-size, a powerful technique we use in Sencha Touch to achieve resolution independence. Then we'll add one more rule to our stylesheet:

.biggreenbutton {
    @extend .green_button;
    font-size: 2em;
}

Here we extend our .green_button class, so that all of its rules are automatically inherited, and also specify a larger font-size, which scales the entire button effectively.

Preview this step in a WebKit or Mozilla browser like Firefox, Safari, or Chrome.

Pass 4

As you can see from our demo, SASS and Compass provide a fantastic layer on top of CSS that makes our styling code shorter, clearer, and more accessible to various browsers. It has become an integral part of our theming structure and process, with amazing results. We'll be discussing our use of SASS/Compass in Sencha Touch more thoroughly soon, but as a teaser, check out our Android theme SASS file. Also, be sure to download the example code from this article to get started creating with SASS.

For readers in the Bay Area: We will be demoing and discussing our use of SASS/Compass at the SASS Meetup tonight!

Additional Reference

There are 32 responses. Add yours.

Chris Scott

4 years ago

Nice.  Good to see Sencha’s got Sass on the radar.  Keep your eyes on Less too.  http://lesscss.org/

Jackson

4 years ago

Thanks for sharing this article, clearly explained.

Mats

4 years ago

Looks superb, great work! smile

/Mats

Michael

4 years ago

That command line tool is truly outrageous. Truly, truly, truly outrageous.

Sergiu

4 years ago

Very nice. Is there a Windows solution for this?

Paul Irish

4 years ago

This is awesome beyond words. :x

Nah truly this is a great guide. SCSS makes sass so much more attractive now..
One thing I was hoping to get out of this.. can you explain the difference between sass and compass? I still don’t grok why they aren’t the same thing. :/

Awesomee Bob

4 years ago

The large buttons don’t seem to render correctly in Chrome when you click on them. All buttons in that example all display a dark rectangle slightly smaller than the buttons themselves. Just a little QA feedback.

Hans Kristian

4 years ago

Great article David. Thanks.
One minor thing I found when playing around - When pressing the “third step” - buttons in Chrome 5 (Win), the darkened rectangle is not rounded. It works fine in Firefox

Henry P

4 years ago

Great Job

Conor Armstrong

4 years ago

Will something similar work for themes in Ext JS?

Steffen Hiller

4 years ago

Very valuable such posts in which we see how you guys roll it.

Though, I wonder why not LESS?
I was never an instant fan of SASS, rather an instant fan of LESS.

E.g. extending other classes by just writing
#header {
  .rounded_corners;
}
is pretty clever and beautiful I think, instead of using explicitly @extend.

Also using dashes in variable names feels more CSSy, and using @ more Ruby than PHP. wink

After all this is just syntax sugar stuff, still would be interesting to know why not Less?
By accident stumbled about this post of you in Google: http://9-bits.com/post/126438804/less-css

Either way, switching from pure CSS to a more clever CSS implementation is a brave and smart move. smile

B

4 years ago

Nicely done and great examples. Sass here I come.

David Kaneda

4 years ago

Thanks for the comments everyone!

A few people asked about our choice of SASS over Less. In the beginning, we spent a fair amount of time debating this, and our decision boiled down to a few things:

* More people in the office were familiar with SASS than Less (I used to use Less myself).
* SASS seemed to build faster
* The color functions in SASS are more robust (one feature which we use very heavily)
* The compass extensions were quite useful

Again, these decision makers aren’t definitive, and Less is still a great, similar, alternative.

@Paul: I kind of feel the same way, in that there shouldn’t be competition that is this similar. From what I heard last night, there are a lot of architectural differences, but on the surface, they’re still VERY similar. As mentioned, the color functions in SASS (and the Compass extensions) were the tipping points for us.

@Dustin: Thanks for the link on auto-compiling or “watching” directories. I wanted to get into some of that (and also how to set up Textmate to compile on save), but figured it was outside the scope of this article.

@Conor: We definitely have an advantage in Touch with the amount of CSS3 we can leverage, but we’re certainly exploring the possibility of using in Ext JS 4.

Steven Roussey

4 years ago

The one thing Less has going for it is that it can run in Javascript itself, rather than yet another language to have to install. It also means that you can do live stuff in the browser, and offline web apps.

Now if SASS had a compiler in JS…

Chris Eppstein

4 years ago

@paulirish Here’s a blog post that I wrote to describe the differences between sass and compass: http://chriseppstein.github.com/blog/2009/09/30/what-is-compass/

@steffen Unlike Less, Sass offers true inheritance—what less provides is a mixin-like behavior that doesn’t always provide the expected effect when working with complex selectors. See here for more info: http://nex-3.com/posts/99-selector-inheritance-the-easy-way-introducing-extend

Joeri Sebrechts

4 years ago

For ExtJS 4, perhaps you could consider abandoning the notion that all browsers have to render visually identical. With simplified markup and a CSS3 theme you could have a very rich UI on IE9, FF4 and newer webkit, and fall back to a simpler look on older browsers (without gradients, shadows or rounded corners).

Jez

4 years ago

Re: Less vs Sass,

We used Less for a previous project, but ended up moving to Sass

The Sass compiler was (is?) more mature, and the language feels more consistent (see the ‘&’ operator in Sass vs the :hover special case in Less). The editor/tool support was quite a bit better too.

Sass doesn’t have a javascript in-browser implementation (afaik), but for rapid development it can watch a folder/file for changes and automatically recompile to static CSS files.

Plus there’s a firebug plugin, so you get Sass line numbers / references instead of compiled CSS line numbers: https://addons.mozilla.org/en-US/firefox/addon/103988/

Toddy

4 years ago

Wonderful. I hope to see much more tutorials on sass and sencha theming in the future. I’m considering to use Sencha to develop a Phonegap based application.

Oliver Sumpton

4 years ago

nice, sounds like CSS Scaffold smile

George Penston

4 years ago

This is a great post and could use plenty more of these detailing how to use tools like these to make the most of web development for modern web and mobile browsers.

One little silly point I wanted to make though. From what I’ve been reading up on HTML5, there’s no need to include type, media, and charset in your CSS link code. HTML5 expects a style tag to be CSS now (as it does with script tags as well). Something I’ve picked up on the great Dive into HTML5 site (http://diveintohtml5.org/) and the new HTML5 for Web Designers book from Jeremy Keith. So far a great read.

Stanley

4 years ago

The link to the Android sass file is broken

Dairo

4 years ago

Great tutorial. It helped me a lot.

@Sergiu I tried this tutorial on a windows computer and it worked fine. The only difference is that you have to use your windows commandline (cmd.exe).
To install SASS and Compass just enter ‘gem install haml’ into your commandline to install SASS and ‘gem install compass’ to install compass. That’s the only difference. GOOD LUCK!

web tasar?m fiyatlar?

4 years ago

It’s very useful….

Thanks a lot….

laurent j

4 years ago

Hi,

I was looking about a way to easier my life with css and i discover this week, less, then saas then the html5 boiler plate project.

I’m on mac so there’s an “less app” that compile automatically .less in .css when we save less file in the IDE.

I didn’t try saas at the moment but i will try.

What do you think about turbine project ?
http://turbine.peterkroener.de/docs.php

Andrew Lenards

4 years ago

The link to the Android theme is *still* broken.

Shaggy

4 years ago

“$button_size/2”
Nice example but not really necessary a large border radius will never exceed what’s needed.
Put a large radius like 1em on something and check it in browsers.. It looks fine.
Someone let me know if I’m wrong here but it seems to auto adjust.

Color manipulation seems to be the greatest use of variable css. like “give me the main color but 50% lighter”

Nice stuff though.

mark josephat

4 years ago

david, the article is great, and the buttons work on the latest firefox, safari and chrome, but alas they do not work in Opera 11 *sad face*

Edgar

4 years ago

Windows tutorial from scratch
I spent some time to figure out how to do this on Windows. Here’s my solution

1. Download and install Ruby (google: “Ruby installer windows” ). When installing, select the two check boxes: adding executables to PATH, and associate *.rb files to Ruby.

2. Download Ruby Gems (google: “Ruby Gems”). Uncompress and run Instal.rb

3. Now you are ready to run start this tutorial and run the follwing command lines (on the top of this page):

C:\> gem install haml
Successfully installed haml-3.0.25
1 gem installed
Installing ri documentation for haml-3.0.25…
Installing RDoc documentation for haml-3.0.25…
C:\>

and

C:\> gem install compass
Successfully installed compass-0.10.6
1 gem installed
Installing ri documentation for compass-0.10.6…
Installing RDoc documentation for compass-0.10.6…
C:\>

Lee Probert

4 years ago

compiler warning informs me that ...

The linear-gradient mixin is deprecated. Instead use: @include background-image(linear-gradient(#20425e, #336a98 4%, #3d7fb6))

The change works and is implemented like so ...

@include background-image(linear-gradient(color-stops(darken($base_color, 30%), darken($base_color, 15%) 4%, darken($base_color, 7%))));

Rogie

3 years ago

i love how it is simply assumed that if you are a developer, you work on a mac smilesmile i tried to explain something over the phone to a friend and “Now fire up your terminal.” was countered by “What is that? Like the Command Prompt?”. Needless to say, i couldn’t help my friend.

TheeKKD

3 years ago

**Windows Users** Ruby 1.9.2-p180 has an error in the _transition.scss file.

The file can be found at ~\Ruby192\lib\ruby\gems\1.9.1\gems\compass-0.11.4\frameworks\compass\stylesheets\compass\css3

on my laptop it was C:\Ruby192\lib\ruby\gems\1.9.1\gems\compass- 0.11.4\frameworks\compass\stylesheets\compass\css3

Correct [line 106]

if($transition-3, $transition-3, $default-transition-fuciton)

With

if($transition-3, $transition-3, $default-transition-function)

As you can see at the end of the original “function” is spelled incorrectly, consequently stopping your .scss file from generating. Simply making this correction should resolve any generating problems such as the one I had.

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

Commenting is not available in this channel entry.