James Wilson

Web developer. Drupal enthusiast. Surfer and musician. I craft bespoke websites at Bluespark.

Add source maps to Omega 4.x projects

UPDATE: fubhy (the Omega theme maintainer) has committed code to the Omega 7.x-4.x branch that adds Source Maps functionality. Just grab the latest dev release, create a sub theme from the starter kit and test! Leave your feedback on [Issue #2311593](https://www.drupal.org/node/2311593).

SASS 3.3 has introduced support for Sourcemaps and just recently, Chris Eppstein has created an initial Release Candidate as a lead up to a full 1.0.0 release version of Compass — which now also supports Sourcemaps.

However, the Omega 4.x theme for Drupal is running on older “stable” versions of Sass, Compass, and their respective dependencies — none of which support source maps.

While source maps are not “bleeding edge” like they were about a year ago, they are relatively new technology only really being supported in the latest versions of a few browsers like Chrome and Firefox. I consider sourcemaps to be an important tool for distributed larger projects with many components and partials, particularly for teams with multiple front-end developers.

The steps below are the ones I took to get Omega updated to work with sourcemaps. I’ve provide a patch to the Omega issue queue here:

https://www.drupal.org/node/2311593#comment-9020173

The assumption here is that you’re already following Omega’s best practices and using bundler and RVM to manage your ruby-version, and the gem set that the Omega sub theme depends on. The way to confirm this is to just run bundle install from inside your theme folder and follow that up with a bundle show sass, which should give you a path that looks something like ~/.rvm/gems/ruby-[version]@omega.themename/gems/.

If you’re not using RVM, that’s o.k., but I highly recommend you start using it to control which ruby version you’re using in any given project.

1) Update to SASS 3.3 and Compass 1.0.0.rc.0

Go to your theme folder and change the sass gem to ~>3.3 and compass gem to ~>1.0.0.rc.0 in the Gemfile file. The spermy operator ~> effectively means the last digit on the right may be equal to or greater than the value specified and is sometimes pronounced as “approximately greater than”.

In your theme's Gemfile, replace: gem 'sass' with: gem 'sass', '~>3.3', and then replace gem 'compass' with: gem 'compass', ‘~>1.0.0.rc.0'.

2) Use bundler to update the SASS and Compass gems.

$ bundle update

This has the effect of downloading new Ruby gems and updating the Gemfile.lock file. New versions of the SASS and Compass gems will be installed into the theme’s gemset — typically found inside ~/.rvm/gems/ruby-[version]@omega.themename/gems/ folder (if you’re using RVM).

3) Remove addimportpath from config.rb.

The line add_import_path 'sass' in the config.rb file was causing problems after upgrading compass because it was generating css files twice -- so I had to remove this line.

(via https://github.com/Compass/compass/issues/1737 and https://www.drupal.org/node/2177397)

4) Compile your CSS.

$ bundle exec compass compile

You’ll probably run into a handful of errors trying to compile the CSS due to other outdated and deprecated functions. In my case I got a series of compile errors that I was able to remedy one-by-one, by searching for the error message in Google and following the instructions to remedy accordingly.

Error 1: ``` WARNING: The compass/css3/shared module has been deprecated. You can silence this warning by importing compass/css3/deprecated-support instead.

on line 1 of compass-core-1.0.0.rc.0/stylesheets/compass/css3/shared.scss from line 1 of singularitygs-1.1.2/stylesheets/singularitygs/helpers/box-sizing.scss from line 8 of singularitygs-1.1.2/stylesheets/singularitygs/helpers.scss from line 36 of singularitygs-1.1.2/stylesheets/singularitygs.scss from line 4 of ~/Project/sites/all/themes/themename/sass/themename.styles.scss from line 5 of ~/Project/sites/all/themes/themename/sass/themename.no-query.scss ```

This happens because singularity.gs version 1.0.0 that comes with Omega is incompatible with Sass 3.3.

5) Update to Singularity.gs 1.2.1

In the Gemfile, update singulartygs gem to ~>1.2.1 and also add require 'singularitygs'to the config.rb file. Then run bundle update, and bundle exec compass compile. This results in another error.

Error 2:

Line 3 of sass/themename.styles.scss: File to import not found or unreadable: breakpoint.

6) Update to breakpoint 2.4.0

(Solution via https://www.drupal.org/node/2232431)

In the Gemfile, update breakpoint gem to ~>2.4.0 and also add require 'breakpoint' to config.rb.

7) Update to Sass Globbing 1.1.0

(Solution via http://stackoverflow.com/questions/22213053)

In the Gemfile, update Sass Globbing gem to ~>1.1.0 in Gemfile. Re-run bundle update and bundle exec compass compile.

This results in yet another error:

Error 3:

Line 8 of sass/themename.normalize.scss: File to import not found or unreadable: toolkit/border-box.

8) Update to Toolkit 2.5.2 and fix import statements in SCSS files

(Solution via https://www.drupal.org/node/2259101).

This requires three changes:

  1. In Gemfile, update the toolkit gem to ~> 2.5.2
  2. In sass/themename.styles.scss, change from @import "toolkit-no-css" to @import "toolkit".
  3. In sass/themename.normalize.scss, change from @import "toolkit/border-box" to @import "toolkit/kickstart".

9) Update to Susy 2.1.2

Update the susy gem to ~>2.1.2 in the Gemfile.

I just did this because there was another error related to susy, and wanted to be sure we were on the latest version. Unfortunately, I don’t remember the error message now.

10) Run and re-run bundle exec compass compile until there are no more errors.

Following the methodology in the previous steps above to troubleshoot and upgrade libraries as necessary, as you hit errors.

11) Enable Compass Sourcemap configuration in config.rb.

Once there are no more errors, you can finally enable the source map configuration. On the line for sass_options in config.rb, add :sourcemap => true inside the curly braces.

My setup looks like this:

sass_options = {
  :debug_info => false,
  :line_comments => false,
  :sourcemap => true
}

I have output_style = :expanded and debug_info hardcoded to false for two reasons:

We don’t use the :development or :production configurations provided by ruby and available to Compass to distinguish between how compressed the css output is. Drupal has built in functionality to aggregate and minify all the CSS, which we turn on only on testing and production environments.

We commit the compiled CSS to our repository, because we don’t run compass or bundler on our production servers. Thus it is far better to store compiled css in an expanded format so that diffs and commit history from other front-end developers can easily be read by a human.

12) Generate source maps!

Run bundle exec compass compile once more to compile the css again and generate the source maps.

You will end up with new files in your theme’s css/ directory that look like css/themename.style.css.map etc.

13) Commit the changes.

Commit all the changes in your theme, including in the Gemfile, the Gemfile.lock, the config.rb, the changes to your SASS files, and the newly generated your new CSS map files into your version control repository.

$ git commit .  -m "Added sourcemaps!”

Right-To-Left Theming in Drupal with Directional SCSS

Directional SCSS is a useful set of SASS functions and mixins created by Tyson Matanich in 2013 that facilitates theming multi-language sites with both left- to-right (LTR) languages such as English, French, German, and Spanish, as well as right-to-left (RTL) languages such as Arabic, Hebrew, and Persian (Farsi).

Before we get started with Directional, it’s important to understand a bit about Drupal’s built-in RTL mechanism. The standard Drupal site-building workflow assumes that when you want a site that supports both LTR and RTL, the LTR styles will be the default [see footnote 1].

When you add an RTL language the entire design is expected to be essentially flipped horizontally. If the menu was floated to the left, then in an RTL language the menu should be floated to the right.

In terms of implementation, the site's default stylesheets will contain the left-to-right styles. Then, any styles that break the site’s RTL mirror-image design must be copied into a similarly named stylesheet with the “-rtl.css” suffix added to the filename.

On RTL pages, Drupal automatically scans the directory structure looking for a RTL stylesheet counterpart for every normal LTR CSS file present on the site and when one is found it is added to the page request.

The menu styles as found on an RTL language page might include code that looks something like the following example, which has been stripped down to the bare essentials, for brevity and clarity:

/* styles.css - Default LTR styles */
.menu {
  float: left;
  margin-left: 15px;
}
.menu li {
  display: inline-block;
}

/* styles-rtl.css - Override rules from styles.css */
.menu {
  margin-left: 0;
  margin-right: 15px;
  float: right;
}

There are a couple drawbacks to note with this implementation. The first and most obvious is that any LTR styles that may bleed into the RTL must be overridden and “nulled”. For example, the margin-left: 0 inside styles-rtl.css of the example above does exactly this — it removes the margin-left: 15px required for LTR only.

The second less obvious drawback is that you have write duplicate code in two separate files and then maintain these two files in sync by hand as your design evolves.

Maintaining the LTR and RTL files in sync, to me is a deal breaker. When design or layout changes require that margin to be adjusted, better not forget to change it in both places! If the margin is removed altogether, you better not forget to clean up that margin-left: 0 too!

Ultimately, this methodology of inheriting LTR styles reinforces a development strategy that makes it easier on the themer to think about RTL after the design is finished. Drupallers have come up with a methodology to help them remember which lines need to be kept in sync using a comment in the LTR stylesheet:

  float: left;  /* LTR */
  margin-left: 15px;  /* LTR */

But this still leaves a lot to be desired. Fortunately, if you’re already using SASS in your own theme, then you can do better and hopefully save yourself some time while developing your theme.

With Directional SCSS, we can take Drupal’s RTL methodology one step further, to let you write all your styles once and use SASS to compile the output to two separate stylesheets.

After downloading the “directional.scss” file from Github into your theme’s “sass” folder, and rename it to a partial: “_directional.scss”, placing an underscore at the front of the file name so that SASS doesn’t generate an empty stylesheet for it in the “css” output folder. Some themes like the Omega 4.x framework organize custom mixins into subfolders, eg "sass/abstractions/" folder. Next, just include the partial into your main stylesheet, and rewrite your LTR-specific rules using the tools available rules that are compatible with Directional SCSS.

/* styles.scss */
@import "abstractions/directional";
.menu {
  float: $left;
  margin-#{$left}: 15px;
}
.menu li {
  display: inline-block;
}

/* styles-rtl.scss */
$dir: rtl;
@import "styles";

The above code will generate the following CSS stylesheets:

/* styles.css */
.menu {
  float: left;
  margin-left: 15px;
}
.menu li {
  display: inline-block;
}

/* styles-rtl.css */
.menu {
  float: right;
  margin-right: 15px;
}
.menu li {
  display: inline-block;
}

Watch out for a major caveat here: All of the code from the LTR stylesheet is added to the RTL stylesheet, including those that are not related to RTL. By itself, this is not a big deal, but the problem is compounded by Drupal because the RTL files are added but the LTR files are not removed — which has two big effects:

RTL language pages will download both styles.css and styles-rtl.css, effectively imposing a tax of twice the bandwidth! Styles from LTR are not nulled out in RTL. This would produce the unwanted effect of having padding- left:15px be present on the RTL version, when in reality, we only wanted and expected the inverse: padding-right: 15px. Thanks Drupal! Well, fortunately, this is super easy to mitigate by adding the code in the following gist to your Drupal theme’s template.php file.

This snippet of code searches through the list of stylesheets and removes the original LTR CSS files on pages whose language is RTL. It is careful to only remove those provided by your theme, leaving the rest of the stylesheets from other modules and Drupal core alone.

That is pretty much all there is to it. I recommend you dive into Directional SCSS and read up about its helpful mixins and functions that help make your Sass-based design right-to-left-friendly with Tyson Matanich’s blog post introduction to Directional:

http://www.matanich.com/2013/09/06/rtl-css-with-sass/

One nice feature I like to use is the side-values function:

/* styles.scss */
.sidebar-first {
  float: $left;
  padding: side-values(10px 5px 60px 20px);
  border-#{$left}: 1px solid #ccc;
}

It swaps the 5px with 20px and vice-versa for the RTL layout producing:

/* styles.css */
.sidebar-first {
  float: left;
  padding: 10px 5px 60px 20px;
  border-left: 1px solid #ccc;
}

/* styles-rtl.css */
.sidebar-first {
  float: right;
  padding: 10px 20px 60px 5px;
  border-right: 1px solid #ccc;
}

Neat!

footnote 1. It’s certainly debatable if Drupal’s assumption about RTL inheriting LTR styles a good one or not, but that’s neither here nor there. I’ve written this post from my own point of view, as a westerner implementing a site designed for researchers of topics about the Middle East, who may speak English, Arabic, Persian, or Hebrew. English in this case IS the default language. I presume that for Middle Easterners who are implementing a site in Arabic, having LTR as the default is probably a large inconvenience to them when they want to go add English to their site.

2014 Sticky Footer Solutions

We’re working on a Drupal distribution of sorts that offers a number of different themes included, and I needed to do some research into to the cleanest solution for including a generic, reusable and inheritable Sticky Footer to be packaged in a base theme, and easily turned on or off in sub-themes as necessary.

Searching Google always turns up a number of solutions, so I thought I would condense the options down into a list of 4 basic options, and list the pros and cons of each.

1. The Classic CSS Sticky Footer (html5 version here):

Pros:

  • CSS/HTML only.
  • No javascript or extra HTTP requests needed.

Cons:

  • Requires the footer height be known, and set to a fixed value in CSS.
  • Requires non-semantic HTML code structure changes.
  • Doesn't work well when using dynamic content such as from a CMS.
  • Doesn't work well for responsive designs, where height may change dynamically based on contents and width of screen.

2. A Responsive Sticky Footer CSS solution using display:table-row

Pros:

  • Don't need to know the height of the footer.
  • Is a responsive solution.

Cons:

  • Could be considered a hack, due to CSS use of .
  • Can cause layout/display issues or break the site design of some sites, requiring more time and attention to fix.

3. The CSS Flexbox solution.

Pros:

  • Zero HTML code changes required.
  • Very little CSS code (5 or 6 lines).
  • Snappy response time and no display issues (requires no JS event listeners or processing).
  • Could be the best choice as a progressive enhancement if stakeholders are willing to accept limited browser support.

Cons:

  • Flexbox still has rather poor browser support,, many current browsers still require vendor prefixes.
  • Would require a fallback solution for supporting IE9 and below.

4. A Javascript-based responsive solution.

Pros:

  • Encapsulated solution - contained in a single javascript file, may be placed in the base Casa theme, and then automatically inherited (or specifically disabled) by any sub-theme.

Cons:

  • Performance - extra HTTP requests.
  • Maintainability - Adds more jQuery/javascript bloat.
  • Hacky - Requires extra code to listen for screen resize, and to restrict itself from overloading the browser.

Here is the above information condensed into a table format:

Solution Responsive Browser Support Pure CSS Clean (No hacks)
No Yes Yes
No; some non-semantic html is required.
Yes
Yes
Yes Maybe; some consider using display:tables-row is not good use of CSS.
Yes No Yes Yes
Yes Yes No Maybe; requires extra code to listen for screen resize and to restrict itself from overloading the browser.