Jim Neath

Manchester based Ruby on Rails & Facebook App Developer

Showing blog posts tagged as "CSS"

Note: MailStyle was originally called Shemail but was changed due to a general negative response to the name from the public.

Background

Writing inline styles for HTML emails is dull and boring but unfortunately a necessary evil. Rather than do it by hand we thought it would be nicer to let our app do it for us. So we wrote MailStyle.

Enter MailStyle

MailStyle allows you to write the css for your html emails as you normally would, then writes the styles inline when you send your emails. It also makes sure that your image paths are absolute rather than relative.

Installation

First install the dependencies:

sudo gem install nokogiri css_parser

Then install MailStyle to your rails app:

script/plugin install http://github.com/purify/mail_style

Usage

Rendering CSS Inline

Simply add the css method to your deliver actions:

class Notifier < ActionMailer::Base
  def welcome_email
    css :email

    subject 'Welcome Aboard'
    recipients 'someone@example.com'
    from 'jimneath@googlemail.com'
    sent_on Time.now
  end
end

This will look for a css file called email.css in your public/stylesheets folder. The css method can take either a string or a symbol. You can also pass the css file name with or without the .css extension.

MailStyle will now write the styles from email.css into html part of the welcome email (eg. welcome_email.text.html.erb). It won’t touch the plain text part, neither will it do anything if you’re only sending a single part email (eg. welcome_email.html.erb). You shouldn’t be sending html emails without a plain text version anyway.

Say that our email.css file looks like the following:

body { background: #000 }
p { color: #f00; line-height: 1.5 }
.text { font-size: 14px }

And our welcome_email.text.html.erb looks like this:

<p class="text">Hello World</p>

Then the resulting html that will be sent out will resemble the following:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  </head>
  <body style="background: #000">
    <p style="color: #f00;line-height:1.5;font-size: 14px">Hello World</p>
  </body>
</html>

Fixing Image URLs

If you have default_url_options:host set in your mailer, then MailStyle will do it’s best to make the urls of images absolute.

In your mailer
ActionMailer::Base.default_url_options[:host] = "example.com"
Example CSS
p { background-image: url(../images/chunky-bacon.png) }
Example HTML View
<img src="/images/header.jpg">
<p>Hello World</p>
Example Output
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  </head>
  <body>
    <img src="http://example.com/images/header.jpg">
    <p style="background-image: url(http://example.com/images/chunky-bacon.png)">Hello World</p>
  </body>
</html>

How You Can Help

The main issue at the moment is speed, so any help speeding things up would be awesome. As always, you can fork the repo at Github.

Further Reading

Below are a couple of links you may find useful regarding HTML emails:

Creating PDF Documents in Ruby on Rails

Those of you that follow me on Twitter will probably know that I’ve spent the last week or so trying to find a decent way of generating PDF documents from a Rails application. I finally found a solution that suited my needs so I thought I’d share it with you lovely people.

Initial Probing

After my first round of googling I came across 2 solutions that people seem to be using:

I’ll admit I didn’t really look too much into PDF::Writer but I did spend a couple of days playing around with Prawn.

All was going well until I ran into certain situations. The two main problems I had with Prawn were that it’s too difficult to style things as I wanted to and generating a table of contents. I might be missing something but I couldn’t get my head around how to solve the latter.

I don’t want to learn a new syntax to define my PDF documents. I don’t want to learn a new way of styling things. I like my HTML and CSS.

WHERE’S MY HTML AND CSS?!

Introducing Prince

Prince XML is a command line program that takes your spiffy html and css and returns a nicely formatted PDF document for you.

Prince is a computer program that converts XML and HTML into PDF documents. Prince can read many XML formats, including XHTML and SVG. Prince formats documents according to style sheets written in CSS.

See, I told you.

So, we’ve got prince xml, but what about hooking it up with rails?

Introducing Princely

Princely is a fantastic plugin by Michael Bleigh, author of other great plugins, such as subdomain-fu and acts-as-taggable-on.

Princely is basically a wrapper around the Prince API. It allows you to define your PDF views as templates like show.pdf.erb. You can write your views as you would normal html views and Princely will return a pdf when you hit those pages.

def show
  respond_to do |format|
    format.html
    format.pdf do
      render :pdf => "filename", :stylesheets => ["application", "prince"], :layout => "pdf"
    end
  end
end

Awesome, right?

Installing Prince and Princely

To install Prince XML, visit the download page and chose the package which suits your needs. Done.

Next, to install Princely, run the following command from your Rails app.

script/plugin install git://github.com/mbleigh/princely.git

Page Numbering

To set the page numbers of you PDFs you’ll need to use the counter attribute of CSS3.

@page {
  @bottom-left {
    content: counter(page);
  }
}

This snippet of code will, funnily enough, add the current page number to the bottom left of each page. That’s all there is to it.

If you’d prefer to show the page number along with the total number of pages, you can use the following:

@page {
  @bottom-left {
    content: "Page " counter(page) " of " counter(pages);
  }
}

Table of Contents

If you’re creating a large PDF with a few sections, it’s generally a good idea to include a table of contents at the start of your document.

The first thing you need to do, is output a list of links at the start of you document that link to internal anchors:

<ul id="toc">
  <li><a href="#ruby">Chapter 1: An Introduction to Ruby</a></li>
  <li><a href="#rails">Chapter 2: Hello, Rails!</a></li>
  <li><a href="#prince">Chapter 3: Pump it up, Prince!</a></li>
</ul>

This will give you a list, that looks something along the lines of the following image:

toc

Now with a bit of CSS magic, we can add the page numbers from our PDF to the table of contents. Ready for this? Go!

ul#toc a::after
{
  content: leader('.') target-counter(attr(href), page);
}

That’s it. attr(href) finds the target of the link. target-counter finds the page that the anchor is on and the leader call just pads the left had side with periods. Win.

That nifty bit of CSS should leave you with something looking like this:

toc unstyled

A bit more CSS to tidy it up a bit:

ul#toc ul {
	margin: 0;
	list-style: none;
	padding: 0;
}

ul#toc a {
	text-decoration: none;
}

ul#toc li {
	margin: 0;
	padding: 0;
	list-style: none;
}

And then we should have something that looks a bit nicer:

toc styled

That’s all there is to it. Easy, right?

Metadata

Prince writes metadata to your PDFs via the meta tags in your html. You can set the document author, subject and keywords using the following:

<head>
  <title>PDF Generation</title>
  <meta name="author" content="Jim Neath"/>
  <meta name="subject" content="Generating PDFs with Prince"/>
  <meta name="keywords" content="PDF, prince, ruby, rails"/>
</head>

Further Reading

Self Clearing Floats in CSS

This is a quickie mainly to remind myself. My friend and fellow Fudge developer, Mike ”1312” Byrne showed me a CSS trick to have divs clear themselves.

div#container 
{
  height: 1%;
}

div#container:after 
{
content: "."; 
display: block; 
height: 0; 
clear: both;
visibility: hidden;
}

Brilliant. This works in Safari, Firefox and IE6+ as far as I know.

Tagged with

More Usable Forms

I just thought I’d post about a few things that you should be doing with your forms and also a few things I just like to do.

Use Labels

I still don’t understand why there are a load of people who don’t use labels within their forms. They’re more semantic that using strong tags like alot of people seem to do. They’re also more user friendly. Also they’re useful for styling your forms.

The LABEL element may be used to attach information to controls. Each LABEL element is associated with exactly one form control.

And here’s how you’d use it in your code:

<label for="username">Username</label>
<input type="text" name="username" id="username" />

Which gives you:

Basic label

Now, when a user clicks on the label it will focus on the form item specified by the for attribute. Hooray.

User the Pointer Cursor

Here’s the CSS:

label, button, input.button
{
    cursor: pointer;
}

Easy. It does require you to add a class to submit and reset buttons, but hey it’s a small sacrifice.

Focus on the First Field

Having to click on the first form field I want to fill in is a pain in the ass. Don’t make me do it. Here’s a quick jQuery function to do it for you:

$(document).ready(function() {
    $('input[type=text]:first').focus();
});

No Confusing Buttons

If you have a submit button and a reset button, or anything similar, make sure people can tell the difference. I don’t want to fill in your huge form and then find I’ve accidentally clicked the reset button instead of the submit button.

An example is shown below:

Buttons

Submit buttons on the left and sub actions on the right, see:

Always put the Submit Form button on the left and on the Clear Form button on the right. Never, ever put the Submit Form button on the right and the Clear form button on the left.

See?

I’ll post more when as they come to me, in my bizarre usability dreams. Feel free to post your own tips. Or to tell me that I know nothing at all about anything.

More Reading

Tagged with

I am available for freelance work! Click here to email me.

Jim Neath is a Freelance Ruby on Rails & Facebook app developer from Manchester, UK, currently working for Engine Yard.