Skip to main content

Mobomo webinars-now on demand! | learn more.

Some of the best known features of Sass are the availability of mixins, variables, and the ability to extend selectors. However, what you might not know is that you can also define functions for use in your rulesets.

What is a Sass Function?

If you've used any of Sass's Operations, then you've used a function. Alternately, if you've used Compass or Bourbon, you've probably used a function. They look like this:

p {   # Pure Sass   background-color: transparentize($coolBlue, 0.25);    # Compass   margin: 0 auto rhythm(3, 42px);    # Bourbon   font-size: em(16, 14); } 

Why do I care?

While it's not uncommon to see mixins get used for this purpose, they're often undesirably verbose or rigid. More importantly, using mixins alone encourages some bad behavior, making monolithically large functions that do too many things. In practice, it's better to have small discrete functions that just do one thing, but do it very well.

My most common use case is similar to what you see in the Bourbon example above, that of converting a pixel-based font size to a relative font size (em or rem).

Defining a function

The syntax for defining a function is similar to what's used to define a mixin:

@function myFunction($var: default) {   // function logic ...   @return $someValue; } 

To create a rem function like the em one that is shown above, we'll actually need to define two functions, one for the actual conversion of pixels to rems, and another to strip the units off of a number. Why do we need to strip the units? Because, due to the way that Sass's math functions accommodate the presence of units, if we leave them there we won't get the value that we desire.

First we'll define strip-units:

@function strip-units($number) {   @return $number / ($number * 0 + 1); } 

Then the rem function:

@function rem($pxl, $base: 16) {   @if not unitless($pxl) {     $pxl: strip-units($pxl);   }    @if not unitless($base) {     $base: strip-units($base);   }    @return ($pxl / $base) * 1rem; } 

Note that we’re using yet another function, unitless, which is provided by Sass (read the docs). Though you don't need to have that check (the strip-units will work even on numbers that don't have units), it's good to not do more computation than necessary.

Once this is added to your Sass environment, you can call it at any point by simply writing your rule:

font-size: rem(24); // This will be output as "font-size: 1.5rem;", // since it will take 24 and divide that by the // default value of 16 that we set in the function 

Functions, Functions, Everywhere

With functions, our Sass files can be even more efficient, the amount of code generated can be reduced, and maintaining these files is even easier. When trying to decide if you should write a mixin or a function, the easiest barometer is this, functions should return a value of some sort, mixins should return rules.

You can read more about the @function directive in the Sass documentation.

Got any questions? Let us know! Also, for more DIY tips + tricks, check these out:

  • How to Refresh an iOS Hybrid App
  • Get Clearer Code with Underscore.js Chaining Syntax
  • Using Storable and Faker to Create Mock Collections
Categories
Author

In the previous SASS recipe post we discussed using loops to create complex series of CSS classes. This week we explore more helper functions tucked away at the SASS Helper Reference

Lighten and Darken

Sometimes when creating accent colors it can be useful to handle it programmatically. lighten() and darken() accept a color and a percentage to increase or decrease that color.

lighten(#000, 20%) => #333333 darken(#ccc, %44) => #5c5c5c 

Lightness

When passed a color, either hexademic prefixed with # or a standard color string, return that color's lightness as a percentage between 0% and 100%. Be sure to pass your color with the # prefix of you'll get a syntax error.

lightness(#ccc) => 80% lightness(#d17b7f) => 65.098% lightness(abcabc) => 'SyntaxError: "abcabc" is not a color for `lightness'' 

Putting it to use

So now we've got a lightness percentage, what can we do with it? How about automatically adjusting colors based on the background color of a button, like so:

=btn-color($gradientStart, $gradientEnd, $innerShadow)   +vertical-gradient($gradientStart, $gradientEnd)     @if lightness($gradientStart) > lightness(#aaaaaa)     color: #4a4a4a     +text-shadow(0 1px 0 rgba(#fff, .4))   @else     color: #fafafa     +text-shadow(0 -1px 0 rgba(#000, .75))     &:active, &.active     box-shadow: 0 1px 5px $innerShadow inset 

If the lightness of top gradient color ($gradientStart) is lighter than the lightness of a pretty light color (#aaaaaa), then we make our text color dark (#4a4a4a) and give it a white text shadow. If $gradientStart is darker than #aaaaaa, make the text color dark (#fafafa) and give it a light text shadow.

These sorts of things will certainly require tweaking, but the end result are styles that intelligently take care of themselves. Combining our last SASS recipe with these techniques will yield concise yet powerful stylesheets that can be modified solely by editing a list of colors.

Continued tinkering

Be sure to look through the HSL functions of the SASS reference to see all sorts of awesome things you have available. Things like adjusting hue, saturation, converting colors to grayscale, and even getting a color's compliment are all possible through SASS.

Acknowledgments

Again my thanks go to Ian for his inspiring code which taught me these cool techniques.

Categories
Tags
Author

Emacs vs Vim. iPhone vs Android. Of all of the nerd arguments, none hits closer to home for Ruby developers than HAML vs ERB. Proponents of HAML look at writing HTML as a dirty practice to be avoided at all costs and look down upon "mere" ERB authors. Meanwhile there's SASS, a language syntactically close kin to HAML and, until last week, one that even rode along inside the HAML gem. HAML abstracts HTML, SASS abstracts CSS. I'm not here to stop you from using HAML if you like it. Go for it. However, I'm tired of having an aesthetic choice that some developers make bandied about as if it were "the only way" to do things.

The Difference Between HAML and SASS

HAML is an abstraction of HTML that allows for terse description of HTML elements in a meaningful-whitespace format. Rather than writing:

<div id="profile">   <div class="left column">     <div id="date"><%= print_date %></div>     <div id="address"><%= current_user.address %></div>   </div>   <div class="right column">     <div id="email"><%= current_user.email %></div>     <div id="bio"><%= current_user.bio %></div>   </div> </div> 

You can instead write:

#profile   .left.column     #date= print_date     #address= current_user.address   .right.column     #email= current_user.email     #bio= current_user.bio 

SASS, similarly, is an abstraction of CSS that allows for terse description by allowing for nesting and other conveniences. SASS also includes an SCSS format that looks nearly identical to CSS. For SASS, you go from this:

table.hl {   margin: 2em 0; } table.hl td.ln {   text-align: right; }  li {   font-family: serif;   font-weight: bold;   font-size: 1.2em; } 

To this:

table.hl   margin: 2em 0   td.ln     text-align: right  li   font:     family: serif     weight: bold     size: 1.2em 

OK, so that's HAML and SASS. They both accomplish roughly the same thing, right? Not so much. Here are some of the differences between HAML and SASS:

SASS looks a LOT like CSS. CSS is a series of rule declarations that already follows a relatively terse format. SASS simply adds on the notion of meaningful whitespace and nesting of rules to prevent repetition.

HAML is an abstraction, SASS is an improvement. While HAML and CoffeeScript could be (in my opinion) successfully compared (each provides a syntax that some find more pleasant for writing a certain type of textual content), SASS does something that neither HAML nor CoffeeScript can: it provides functionality that is impossible to achieve in the target compiled language. There's no such thing as a variable, mixin, or function in CSS. SASS provides a thin layer on top of CSS that adds immense power that wasn't there before. Personally, I like CoffeeScript, but I also don't mind writing plain Javascript. I doubt I'll ever again work on a web project where I don't use SASS, because it is simply too useful to ever be without.

Learnability. If I sat down with a designer who was familiar with CSS, I could teach them SASS in less than an hour. Despite trying a couple times at various points, I still have to constantly defer to the reference when I'm writing HAML. I'm not saying that HAML doesn't help some people write HTML templates more efficiently, I'm saying that writing your project in HAML simply guarantees a relatively long and obnoxious learning process for every person who needs to work in the views. Maybe you have a small, fixed team that makes that a possibility, but in many (if not most) real-world scenarios wasting time to teach a templating language that is simply a convenient abstraction is not going to be worth it.

Breadth and Scope. HAML works essentially as a subset of the things you can do in ERB. There are some things that HAML simply won't do (some of these encourage good programming practices, but the statement is true nonetheless). SASS is a superset of CSS; you can do everything you can do in CSS and significantly more. This difference means that SASS will never tie your hands for styling a site but HAML may tie your hands to a specific means of execution in some scenarios. Again, not to say this is always a bad thing, but it's a true thing.

Freedom of Choice

I don't really care if you want to use HAML. I actually can understand how, for developers who don't like writing HTML and CSS (I work on both sides of the development/design fence) it may feel more productive to be able to write things that way. So go for it, use HAML. Just don't tell me that my choice is inferior. We're talking aesthetics here, there is no right and wrong.

There are other ways to accomplish the same terseness that HAML provides while generating pure HTML templates, things like Zen Coding or even just judicious use of some more advanced features of your editor of choice.

TL;DR. SASS and HAML solve two completely different problems. Liking SASS doesn't imply wrongness in disliking HAML. Using HAML is fine if that's your bag, but don't act like it's the only way. It's just an aesthetic choice.

Categories
Author

Here is a quick tip for users who like the idea of using SASS-powered stylesheets, but may not want to bother setting up a development framework to do so.

A Really Quick Intro to SASS

If you’re not familiar, SASS (“semantically awesome stylesheets”) builds off your existing CSS knowledge, but tosses some dynamic spice into the mix. The result leaves you with increased power and flexibility as a coder/designer.

The result is code that is easier to read, takes up less space, and supports the very helpful nesting of styling rules. Another tremendously useful feature is the ability to use variables throughout all of your stylesheets — something that becomes invaluable when working on larger websites or applications. SASS also supports mixins, operations, and beyond — learn more at the SASS website, or by reading Michael Bleigh’s excellent SASS intro.

SASS with static websites, you say?

Until somewhat recently, I’d only used SASS when jumping in to help with design work on pre-existing, larger Rails applications. This works great, as the markup is already in place and changes are easy to make. My SASS experience in this regard has been a good one.

When coding a new, larger site from scratch, however, I’ve never found a satisfying approach to use SASS from square one. I’ve dabbled with a few different SASS-compatible static website frameworks (Middleman, StaticMatic, etc) — but never felt comfortable enough with these to full integrate them into the beginning of my HTML/CSS coding process. As such, my preference has remained: build the layout in static HTML, and when fully coded & styled, integrate into the Rails app. Sadly, SASS fell by the wayside too often with this approach.

But finally, thanks to the latest beta versions of the HAML/SASS gem, an accessible solution lies in wait. This setup will auto-compile your SASS into CSS whenever changes are made. Best of all, no additional framework setup or files are needed… just what I’ve been looking for. Make it happen as follows:

1. Install the latest HAML/SASS gem

When I discovered this technique, the latest gem was installed as follows:

gem install haml-edge

However, in the meantime there have been beta releases of SASS 3.0, which should achieve the same ends. install this gem as follows:

gem install haml --pre

If you’re curious if anything more recent has been released, check out the HAML/SASS blog.

2. Setup your local project directory

Do this however you like: I usually start with an index.html and fresh directories for stylesheets, images, and javascript. Populate with any templates/frameworks you may have, as desired. Just make sure you have a directory for you SASS files in place. Here is an absolute bare-bones version to show how this technique applies:

3. Summon the sass --watch kraken

Finally, from the command line, run this line to make the magic happen:

sass --watch path_to_sass:path_to_css

The path before the colon is wherever your SASS files are located… the path after the colon is where you want the CSS to be generated. Of course, your HTML should reference the location of the CSS files. Keep in mind: when styling this way, any changes you make to a CSS file will be lost if/when the SASS file is changed (the overwrite is automatic).

Also note that you will need to run this step each time you want to enable auto-compiling SASS. It will run in the background, and instantly take action if a SASS file has been changed.

And that’s it. Whenever you make changes to any SASS files in the directory you specified, the corresponding CSS files will be automatically updated (and created, if necessary). This lets you benefit from the dynamic nature of SASS without requiring any framework setup.

Categories
Author

I am a huge fan of SASS (Syntactically Awesome Stylesheets) for styling Rails applications. I have been using it on all of my projects for quite a while now and have developed some great techniques that make it much easier to organize, write, and read stylesheets in an application.

Unlike HAML, SASS retains most of the same “feel” when writing the code as vanilla CSS. It simply adds more power and better organizational tools, making it an easy choice as a go-to replacement. You can teach someone the basics of SASS in about 30 seconds: use two spaces to indent everything, put the colon before the declaration and no semicolon afterwards. In fact, I’ve even written regular expressions to convert CSS to SASS mechanically in some cases. It’s easy to pick up and once you do you will start reaping real benefits.

The 20-Second “Get Up And Running”

To use SASS, you must have the HAML gem installed on your Rails app. Add it to your environment.rb:

config.gem 'haml', :version => '>= 2.0.6'

Now you can create SASS stylesheets simply by making .sass files in a public/stylesheets/sass directory.

Basic Example: Building a Menu the SASS Way

The best way to start explaining the power of SASS may be through one of the more common styling tasks one encounters: styling a menu. Here we’ll assume a menu structure like this:

<ul id='menu'>   <li><a href='/'>Home</a></li>   <li><a href='/about'>About</a></li>   <li><a href='/services'>Services</a></li>   <li><a href='/contact'>Contact</a></li> </ul>

To style this menu in CSS, we might do something like this:

#menu {   margin: 0;   list-style: none; }  #menu li {   float: left; }  #menu li a {   display: block;   float: left;   padding: 4px 8px;   text-decoration: none;   background: #2277aa;   color: white; }

SASS allows you to use indentation to indicate hierarchy, saving much repetition and space. The same code in SASS looks like this:

!menu_bg = #2277aa    #menu   :margin 0   :list-style none   li     :float left     a       :display block       :float left       :padding 4px 8px       :text-decoration none       :color white       :background = !menu_bg

Hierarchical selectors mean that if you indent something, the selector it falls under will automatically be prepended to it, so the two examples above generate the same output. You’ll also notice !menu_bg in the SASS code. SASS allows you to declare constants that can be reused throughout the code, a very useful feature when dealing with colors.

Now we have our basic setup for the menu, but let’s handle some better cases. I want the color to change when I hover over the menu options and I want to highlight the current menu option (we’ll assume that the <li> encapsulating the current menu item will have class ‘current’ when it is selected). Let’s add these features first using CSS, then SASS. With CSS:

#menu {   margin: 0;   list-style: none; }  #menu li {   float: left; }  #menu li a {   display: block;   float: left;   padding: 4px 8px;   text-decoration: none;   background: #2277aa;   color: white; }  #menu li a:hover {   background: #116699; }  /* Make sure the color doesn't change when the current option is hovered. */ #menu li.current a, #menu li.current a:hover {   background: white;   color: black; }

This isn’t too bad, but our selectors keep getting longer and longer. Let’s look at the same thing in SASS.

#menu   :margin 0   :list-style none   li     :float left     a       :display block       :float left       :padding 4px 8px       :text-decoration none       :color white       :background = !menu_bg       &:hover         :background = !menu_bg - #111111     &.current       a, a:hover         :background white         :color black

The ampersand (&) in SASS is a shortcut to insert the entire parent selector at that point. By using &.current I am saying “the parent selector with a class of current.” &:hover means “the parent selector when hovered.” This makes it easy to write complex selectors in a compact, easy-to-read manner.

Another great thing about SASS is it has built in CSS color math. Note where I declared :background = !menu_bg - #111111. That is equivalent to subtracting 1 from each of the values of the constant’s color, which in this case yields #116699. This is great, because now I can change the color of the menu and the hover state will automatically change without me having to manually find it and recalculate it for a new color. Note that whenever you are using constants or performing calculations you need to add the equals sign to your declaration.

Getting organized with a master.sass

Another way you can use SASS is to organize all of your CSS into a single file without having to worry about it in your view. I have recently started using this approach for a number of reasons:

  1. It allows me to control stylesheet inclusion from within the stylesheets themselves, making the structure more readable.
  2. I can define global colors that can then be used in any of the child stylesheets.
  3. It’s really easy!

In a new project, I always create a master.sass that will look something like this:

// Define app-specific colors first !green = #191 !gray = #555  // Now define globally applicable, general styles  body   :font-family Arial, sans-serif    a   :color = !green   :text-decoration none   :font-weight bold  // Now import all of your other SASS files, they will be // automatically included in the same generated CSS file // at compile time.  @import menu.sass @import content.sass @import admin.sass @import users.sass

Using this structure I have a modular, easily expandable collection of stylesheets with global color constants and basic styles. In addition, I can add this to my Rails application with the simplest of calls:

<%= stylesheet_link_tag 'master' %>

Wrapping Up

Hopefully this gives you a taste of the easy awesomeness that is possible with SASS. The greatest thing about the library is you don’t lose touch with writing CSS because SASS is CSS, just with a few extras and shortcuts to make power-styling easier.

Update: A commenter pointed out that I forgot the @ before my import statements in the master.sass example, this has been fixed.

Categories
Author
1
Subscribe to Sass