wp-compass

TUTORIAL: Using Sass and Compass for managing CSS in WordPress

I don’t often write tutorials but since the rebuild of the WP Engine website some months ago, I have been turned on to the use of a brilliant combination of tools made for development in a Ruby on Rails environment. That doesn’t mean we can’t make it work for WordPress too.

The tools are Compass combined with Sass (which means Sytactically Awesome Stylesheets or some random crap like that).

Sass is cool because it lets you do a whole bunch of stuff with CSS that you couldn’t normally. It’s a kind of abstraction layer above CSS which means you can write normal CSS if you want, but then why wouldn’t you just write normal CSS instead of using Sass?

I’m getting slightly ahead of myself, but With Sass you can do awesome things like variable/placeholders which is awesome for things like defining core elements of a stylesheet such as a palette of colors.

1
2
3
4
$cloud-blue: #d9e7f3;
$light-blue: #f0f7fc;
$dark-blue: #036;
$green: #7ca60a;

Then using those variables, you can just use these placeholders in your SCSS (Sassy CSS) file:

1
2
a { color: $dark-blue; }
a:hover { color: $light-blue; }

You can also write Mixins. Mixins are essentially reusable blocks of CSS that look a lot like functions you would see in languages like JavaScript, PHP or Ruby:

1
2
3
4
5
6
7
8
$radius:5px;

@mixin border-radius($radius)
{
border-radius:$radius;
-moz-border-radius: $radius;
-webkit-border-radius: $radius;
}

You can use that in your SCSS file as such:

1
form input { @include border-radius(5px); }

But again, I’m getting ahead of myself.

When I talked about using Sass and Compass on Twitter, other WordPress devs made comments that made me want to write this tutorial. One person said that they were tired of Rails developers having all the toys – and it’s true. There are so many awesome things out there for Rails developers that we as PHP and WordPress developers don’t benefit from. This tutorial is non-exhaustive. There are tons of things that you can do with this that I won’t cover. But this should get you going with Mac OS X Lion, developing WordPress locally on your own machine and uploading to a theme file called “test” on a remote server.

Prerequisites

First of all, you need to have a local version of WordPress running. There are a variety of ways to do this, but I use the approach of installing XAMPP. Here’s a tutorial on that. Follow the rabbit trail to configure Apache to look to your Sites directory, as I have, or make that translation in your head to what the default is. There’s plenty of instruction on how to do that on the internet.

For the specifics of this tutorial, it’s very important that you have the latest version of Ruby. The best way to do this is with a tool called rvm, or Ruby Version Manager. Install this with the following Terminal command:

1
bash < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)

Once rvm is installed, use it to install 1.9.3-p0, the only current version compatible with OS X Lion, and refresh your Terminal profile settings. The last command sets 1.9.3-p0 (or whatever future version you choose to use) as your default.

1
2
3
4
rvm install 1.9.3-p0
rvm reload
source ~/.bash_profile
rvm --default use 1.9.3-p0

If you wish to verify that you’ve got the proper version of Ruby active, verify it with the ruby -v command.

My system reported:

1
ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-darwin11.2.0]

Now, there are some gems that need to be installed. For developers unfamiliar with Ruby – or Rails – gems, are essentially additional libraries that are installed into the Ruby framework, much like PHP PEAR or PECL modules.

The first is Builder, which is used for building XML structures. The second one is Compass which will give us the ability to leverage Sass for CSS authoring.

1
2
gem install builder
gem install compass

Creating a Sass Project

Once we have everything installed properly, we can start a new project. I keep this out of my web directory (i.e. WordPress structure). Personally, I’ve created a sass directory under my user profile (/Users/aaron/sass) and run my projects out of it with a separate directory for each project.

Now we have to create our compass project. We do that with compass create from our ~/sass directory and then moving into the newly created directory.

1
2
compass create test
cd test

Doing a directory listing should show something along these lines:

1
2
3
4
5
6
7
8
NCC-1701:test aaron$ ls -la
total 8
drwxr-xr-x 6 aaron staff 204 Nov 2 11:36 .
drwxr-xr-x 4 aaron staff 136 Nov 2 11:36 ..
drwxr-xr-x 5 aaron staff 170 Nov 2 11:36 .sass-cache
-rw-r--r-- 1 aaron staff 861 Nov 2 11:36 config.rb
drwxr-xr-x 5 aaron staff 170 Nov 2 11:36 sass
drwxr-xr-x 5 aaron staff 170 Nov 2 11:36 stylesheets

Good. Our project is created but we need to make some changes to make this work with WordPress. To do this, we need to edit the config.rb file which is the project configuration file. You can edit this file in Textmate, vi, or whatever you choose as your preferred text editor.

The default configuration is:

1
2
3
4
5
http_path = "/"
css_dir = "stylesheets"
sass_dir = "sass"
images_dir = "images"
javascripts_dir = "javascripts"

My config file looks like this:

1
2
3
4
5
6
7
8
http_path = "../../Sites"
css_dir = "../../Sites/wp-content/themes/test/css"
sass_dir = "sass"
images_dir = "images"
javascripts_dir = "js"
project_type = :stand_alone
output_style = :nested
line_comments = false

Important changes here:

  • The http_path is a relative path to my DOCROOT – for some reason, things got whacked when using an absolute path.
  • The css_dir is a relative path to the css directory in my WordPress theme directory. At this time, there is no configuration option to control the name of the CSS files being generated so we will have to use @import inside the required WordPress style.css template file to incorporate Compass generated CSS files.
  • You can change the images_dir and javascripts_dir as needed to reflect your taste. Personally, I prefer shorter names, so that is reflected in the config file.
  • The project_type flag is required because, if omitted, Compass assumes we are working in a Rails environment on a Rails project with Rails conventions… WordPress is none of that.
  • The output_style flag has been set to :nested but could be :expanded, :compact or :compressed depending on your tastes.
  • The line_comments flag has been set to false to remove debug information from the generated CSS

All configuration options can be referenced in the Compass docs.

Having modified the config file, we can take one of two approaches to generating the CSS in our WordPress theme. We can use the compass compile which will generate the files one time. Everytime modifications are made, however, this command would have to be re-run. I prefer, instead, to use compass watch which is a small process that remains running and watches your Sass project for changes and recompiles automatically when changes are made.

Simply run this command from inside the Sass project:

1
2
3
4
5
6
7
8
9
compass watch
>>> Change detected to: ie.scss
create ../../Sites/wp-content/themes/test/ie.css
create ../../Sites/wp-content/themes/test/print.css
create ../../Sites/wp-content/themes/test/screen.css
/Users/aaron/.rvm/gems/ruby-1.9.3-p0/gems/fssm-0.2.7/lib/fssm/support.rb:40: Use RbConfig instead of obsolete and deprecated Config.
FSSM -> An optimized backend is available for this platform!
FSSM -> gem install rb-fsevent
>>> Compass is polling for changes. Press Ctrl-C to Stop.

At this point, if you want to develop locally, all you have to do is have your WordPress style.css import these stylesheets.

1
2
3
4
5
6
7
8
9
10
11
/*
Theme Name: Test Theme
Author: Aaron Brazell
Author URI: http://emmense.com
Description: A test theme demonstrating Sass and Compass
Version: 1.0
*/


@import url('css/screen.css');
@import url('css/print.css');
@import url('css/ie.css');

Uploading to a Remote WordPress Install

Fortunately, with a little Ruby magic and some built in Compass hooks, we can also upload these newly created CSS files to our WordPress theme. In order to do this, you have to make sure the remote server has the theme directory created and if you are uploading to a subdirectory of that theme (e.g. theme_dir/css), that that directory is created as well.

In our case, the theme directory is test/ and I want to upload to a subdirectory test/css/.

Next we have to install two new gems – the Net::SSH and Net::SFTP gems. Installing these is as straightforward as the earlier gems:

1
2
gem install net-ssh
gem install net-sftp

Once this has done, include these in your config.rb file. I did this at the top which is best practice with Ruby.

1
2
require 'net/ssh'
require 'net/sftp'

Below all the previous configurations, add some configuration lines and replace values as needed for your own project:

1
2
3
4
5
6
7
8
# note that this is the directory that CSS files will be written. It can be the theme dir
# or a subdirectory (e.g. theme_dir/css). Whatever this path is MUST exist
remote_theme_dir_absolute = '/home/sites/emmense.com/httpdocs/wp-content/themes/test/css'

# SFTP Connection Details - Does not support alternate ports os SSHKeys, but could with mods
sftp_host = 'hostname.com' # Can be an IP
sftp_user = 'username' # SFTP Username
sftp_pass = 'password' # SFTP Password

Finally, we can leverage Compass’ built-in on_stylesheet_saved hook to upload to the remote server using your SFTP credentials:

1
2
3
4
5
6
7
8
9
# Callback to be used when a file change is written. This will upload to a remote WP install
on_stylesheet_saved do |filename|
  $local_path_to_css_file = css_dir + '/' + File.basename(filename)

  Net::SFTP.start( sftp_host, sftp_user, :password =&gt; sftp_pass ) do |sftp|
    puts sftp.upload! $local_path_to_css_file, remote_theme_dir_absolute + File.basename(filename)
    end
  puts ">>> Compass is polling for changes. Press Ctrl-C to Stop"
end

Restart Compass, save one of your Sass .scss files with a change of some sort (from where CSS will be compiled), and watch your files be saved locally and remotely.

At this point, my full config.rb file looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# Require any additional compass plugins here.
require 'net/ssh'
require 'net/sftp'

# Set this to the root of your project when deployed:
http_path = "../../Sites"
css_dir = "../../Sites/wp-content/themes/test/css"
sass_dir = "sass"
images_dir = "images"
javascripts_dir = "javascripts"

project_type = :stand_alone
output_style = :nested
line_comments = false

# note that this is the directory that CSS files will be written. It can be the theme dir
# or a subdirectory (e.g. theme_dir/css). Whatever this path is MUST exist
remote_theme_dir_absolute = '/home/sites/emmense.com/httpdocs/wp-content/themes/test/css'

# SFTP Connection Details - Does not support alternate ports os SSHKeys, but could with mods
sftp_host = 'hostname.com' # Can be an IP
sftp_user = 'username' # SFTP Username
sftp_pass = 'password' # SFTP Password

# Callback to be used when a file change is written. This will upload to a remote WP install
on_stylesheet_saved do |filename|
  $local_path_to_css_file = css_dir + '/' + File.basename(filename)

  Net::SFTP.start( sftp_host, sftp_user, :password =&gt; sftp_pass ) do |sftp|
    puts sftp.upload! $local_path_to_css_file, remote_theme_dir_absolute + File.basename(filename)
    end
  puts ">>>> Compass is polling for changes. Press Ctrl-C to Stop"
end

Conclusion

Rails developers have all the fun. It’s true. But with Compass, Sass and a little bit of Ruby, PHP developers (including WordPress theme developers) have a great tool that will make workflows more efficient, CSS more readable and structured and central management more coherent.

Obviously, I did not get too far into the details of using Compass and Sass. That’s a whole tutorial to itself. For information on that, I’d recommend checking out these fine articles written on the topic:

(Protip: I love being able to nest CSS… try it)

Disclaimer: I am a PHP developer, not a Ruby developer. My Ruby code could probably be improved upon by someone who is more in tune with the Ruby language.

Read More

216334845_821aaf4823_o

WordPress and PHP 5: Be the Change You Want to See

The other day, I wrote the popular 10 Things You Need to Know About WordPress 2.9. As usual, most people are very excited about the new release which is now in beta and available for testing. In the article, I made a few fundamental errors which I have since corrected.

Notably, I mentioned that WordPress 3.0 would be going to PHP 5. This was based on conversations I had with a core developer which I now realized I misunderstood. Kinda. WordPress will probably not be dropping PHP 4 support in WordPress 3.0 but as core developer Mark Jaquith suggests:

Some things already require PHP 5, like time zone support or oEmbed. There are no plans that I know of to remove PHP 4 support in 3.0 “” last I checked we still had 12% of WP installs using PHP 4.

I see more of a natural and gradual deprecation of PHP 4. We’re very much open to making new features require PHP 5 if it would be a pain to make them PHP 4 compatible.

As a PHP developer, I am on board with calls for PHP 5 support. PHP 4 has been end of life (EOL) since August 8, 2008. That basically means that there will be no more releases, no more security patches, no more nothing. It’s done. Stick a fork in it. However, as Matt mentioned on stage at WordCamp NYC this weekend, there are still 12% of WordPress installations using PHP 4 hosting. He breaks that down as approximately 2M installs, the size of a major American city. More precisely, that’s approximately the size of Philadelphia.

This is not to defend WordPress development. I’d leave Philadelphia behind in a minute if I could get access to real object oriented PHP, reliable XML parsing, better HTTP transports and so much more. Yes, Philadelphia… I just threw you under the bus. That’s for signing Mike Vick. However, as Mark suggests, increasingly more features are being added to the core that require PHP 5.

oEmbed, which will ship in WordPress 2.9, requires XML or JSON parsing. XML parsing sucks in PHP 4. JSON ships by default in PHP 5.2. It is easier to backport JSON support to PHP 4 than try to engineer XML parsing for PHP 4. Some in the PHP community feel like backporting a PHP 5 feature to PHP 4 disincentivizes PHP 5 movement. It may, I’m not here to argue that.

Time Zone support is handled via the PHP class DateTimeZone, a PHP 5 class. Of course, on PHP 4 hosts, the user simply has to set the UTC offset (say, UTC-5 for Eastern Standard Time) manually. Graceful degradation.

I personally was one of the first people to write code for the SSH2 portion of the one click automatic upgrade feature. I, of course, did not go very far with it, but I was the one who first took a stab at creating that.

It is not worth it for PHP developers to throw mud at WordPress developers and the PHP 4 requirement if they are not willing to write code to make it better. Writing code does not, of course, mean that your feature will be incorporated. But this is an open source project. If you want to see new features, and the developers have indicated willingness through not only words, but also action, to include PHP 5 features, then you need to be the champion of those changes. In other words, you need to write the code, submit the ticket and state your case. Even if you can’t write the code, open a ticket and be a champion for the case.

Effective arguments, however, do not include holy wars over PHP 4 or PHP 5. Effective arguments do include security, usability, and feature requests that reflect “must have” features. Is it plugin territory or should it be a core feature? Why? State your case.

I will admit not being overly active in the ongoing development of WordPress. I have client work built around WordPress, so that takes up most of my time. Understanding that, I also have no room to throw mud unless I’m willing to step up and write code too. It’s sort of like voting. If I don’t bother to go vote, then I can’t complain about my elected officials.

If you want to see change in WordPress, be that change and put your words into action.

Read More

GNIP Spells a Whole New World for Data APIs

Allow me to get nerdy.

It has been a long time since I got downright giddy about something developer-oriented. Lots of new APIs are coming out all the time and I usually take a once over look at them to determine if there is something cool there. A lot of time there are cool things and I promise myself to come back and explore the possibilities later. I rarely do.

However, with the announcement of GNIP today, I finally feel like my incessant mulling of API frameworks might be coming to an end.

Let me back up. A few weeks ago, I was fiddling with a bunch of APIs trying to create some mashup I was working on. I sent Keith a direct message pitching a “crazy idea”. An API for all APIs. One API to rule them all. His response, “A meta API?”

That made sense and made me laugh because I know how much he hates the word “meta”.

My idea quickly dissipated as I realized it was probably pretty futile to create an API for all these varied services that all had different data formats and types and my need for it wasn’t all that important at the time anyway.

I could have also used the concept when I was working on Mokonji, the project that now sits dead because Trackur beat me to the punch.

The idea with GNIP, bringing this story full circle, is that it is a meta-API. It sits in front of “data producers” (Digg, Flickr, Disqus) and provides a standardized API for “data consumers” (Plaxo, MyBlogLog, even Lijit!) to exchange data.

Since this is still so very early, there are bound to be other data producers and consumers. Also notable is that the only data format is XML. XMPP and JSON are missing. That will likely change over time too.

Data Producers not yet involved that should be:

And a few Data Consumers that are also missing:

Read More