Foundation for Emails: How to Use Panini Partials

In this tutorial, we’ll be using ZURB’s Foundation for Emails to create a simple functioning email. We’ll explore various libraries provided by the framework, specifically “Panini”. Panini allows us to do a few things but we’ll be focusing on its partials feature.

Foundation for Emails: How to Use Panini Partials

Foundation for Emails: How to Use Panini Partials
We’ll be using a design put together with Web Wireframe Kit available from ThemeKeeper Elements.

Setting up Our Project

Foundation offers two versions; a standard CSS version or one which uses Sass. For this tutorial we’ll be leaning on the Sass version as it offers a different workflow which includes the “Inky” templating language, as well as more customisation for styling.

I will presume you already have some knowledge of how to setup a project using Foundation, the easiest way being with the Foundation CLI. Instructions for installing via the command line are available in the Foundation docs. Alternatively, if you’re an ThemeKeeper Tuts+ or Elements subscriber you can follow Adi Purdila as he walks through the whole installation process.

Once you’ve done this, we can create a project with the following command. You’ll then be asked for the name of the folder you want to create the project in.

foundation new --framework emails

Before we dive into any code, I like to clean up my build directory first. You should see a src folder with the following structure:

  • assets
  • helpers
  • layouts
  • pages
  • partials

I like to delete all files with the exception of index.html within the pages folder (we won’t be using any of the others). I’ll also delete the index-layout.html in the layouts folder.

Note: As mentioned above, this isn’t compulsory. I just like to keep my build directory nice and clean.

Foundation for Emails: How to Use Panini Partials

_settings.scss file

The sass version of the framework allows us to customise the pre-built components for our own use. I’ve listed below the changes I have made, including each comment section header. Feel free to either change these in your _settings.scss file or create a new file and import it after the the settings file, but before the foundation framework one.

// 1. Global
// ---------

$primary-color: #ACACB7;
$light-gray: #F4F4F6;
$medium-gray: #ACACB7;
$dark-gray: #4E4E56;
$black: #000000;
$white: #ffffff;
$global-width: 540px;
$body-background: $white;
$global-radius: 6px;

// 4. Typography
// -------------

$global-font-color: $dark-gray;
$body-font-family: 'Lato', Helvetica, Arial, sans-serif;
$global-line-height: 1.5;
$header-font-weight: 700;
$h1-font-size: 48px;
$h2-font-size: 32px;
$h3-font-size: 30px;
$h4-font-size: 24px;
$h5-font-size: 18px;
$h6-font-size: 16px;
$header-margin-bottom: 0;
$paragraph-margin-bottom: 0;

// 5. Button
// ---------

$button-padding: (
  tiny: 4px 8px 4px 8px,
  small: 5px 10px 5px 10px,
  default: 16px 80px 16px 80px,
  large: 10px 20px 10px 20px,
);

// 7. Menu
// -------

$menu-item-padding: 10px;
$menu-item-gutter: 10px;
$menu-item-color: $dark-gray;

Foundation for Emails: How to Use Panini Partials

Let’s Begin Coding!

Moving on, it’s time to open up index.html in the pages folder. This is where we will create the email content. We’ll start with the following code which includes a spacer element and the container element. Remember, we’re using the Inky templating language if this looks unfamiliar!

---
subject: Foundation for Emails - Using Panini
---

<spacer size="25"></spacer>

<container>
  
</container>

We’ve already started to use the features of Panini here, specifically Custom Data. This is a default data value used by Foundation. It uses a variable name of subject which is then pulled through into the master template for the title tag with {{ subject }}.

Foundation for Emails: How to Use Panini Partials

The Header

Now we can begin to start using partials with Panini! Go ahead and create a new file called header.html within the src/partials folder.

We’ll be using the following code for the header, and whilst it’s not necessary I do like to wrap my sections within the wrapper tag along with a class for identification:

<wrapper class="header">
    <row>
		<columns small="12" large="6" valign="middle">
			<a href="#" class="logo show-for-large">
				<img src="assets/img/logo.png" alt="Company Name">
			</a>

			<a href="#" class="logo hide-for-large">
				<center>
					<img src="assets/img/logo.png" alt="Company Name">
				</center>
			</a>
		</columns>
		<columns small="12" large="6" valign="middle" class="show-for-large">
			<p class="webversion text-right">
				<a href="#">Not displaying properly?</a>
			</p>
		</columns>
	</row>
</wrapper><!-- END .header -->

You may have noticed I’ve used two anchor tags for the logo. This was due to the logo being centered on mobile (images need a center tag around them) so I used Foundation’s visibility classes to show/hide on mobile. I’ve also hidden the webversion link text on mobile too.

Now you’re wondering, how do we get this to show up? Heading back on over to the index.html file, between the container tags, place the following code inside:

{{> header}}

All partial includes require {{> }} along with the name of the partial file name, in this case, header.html.

I’ll be using the following styles for the header too, feel free to put this anywhere. I created a file named _styles.scss and imported this via app.scss.

// Header
// ===================================
.header {
    .columns {
		padding-bottom:0;
	}

	.logo {
		img {
			max-width:111px;
		}
	}

	.webversion {
		a {
			font-size:14px;
			color:inherit;
		}
	}
}

Note: You may have noticed I didn’t apply a width to the img tag for the logo (which you should normally do!) Foundation’s framework has a bunch of styles which cause the image to expand to its full width. In this case, because I’m supporting retina screens, I create @2x images. We can solve this by targeting the img and applying a max-width (be sure to use max-width, and not just width).

Foundation for Emails: How to Use Panini Partials

Hero Section

For this section, I decided to keep it within the index.html file; I felt it didn’t require a partial, but it’s up to you how you handle it.

<wrapper class="hero">
    	<row>
			<columns small="12" large="12">
				<a href="#" class="play-video">
					<center>
						<img src="assets/img/play-icon.png" alt="Play">
					</center>
				</a>
			</columns>
		</row>

		<row>
			<columns small="12" large="12">
				<h1 class="text-center">De Finibus Bonorum<br class="show-for-large"> &amp; Malorum</h1>

				<spacer size="30"></spacer>

				<p class="text-center">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.</p>

				<spacer size="40"></spacer>

				<center>
					<button href="#" class="radius small-expanded">Sign Up</button>
				</center>
			</columns>
		</row>
	</wrapper><!-- END .hero -->
// Hero
// ===================================
.hero {
    .wrapper-inner {
		padding-bottom:150px;

		@media only screen and (max-width: #{$global-breakpoint}) {
			padding-bottom:75px !important;
		}
	}

	.play-video {
		display:block;
		padding-top:80px;
		padding-bottom:80px;

		img {
			max-width:120px;
		}

		@media only screen and (max-width: #{$global-breakpoint}) {
			padding-top:60px !important;
			padding-bottom:60px !important;

			img {
				max-width:60px !important;
			}
		}
	}

	p {
		font-size:18px;
	}

	@media only screen and (max-width: #{$global-breakpoint}) {
		h1 {
			font-size:40px !important;
		}

		p {
			font-size:16px !important;
		}
	}
}

As far as styling goes, you may see some things in here you haven’t seen before. We’ve started to introduce some styles for mobile size, this is done using a media query but Foundation is very helpful and supplies a Sass variable for the max-width.

@media only screen and (max-width: #{$global-breakpoint})

Whenever creating styles within the media query, you’ll often need to use the !important tag otherwise the small size styles will be overwritten by the large ones.

Foundation for Emails: How to Use Panini Partials

Remaining Partials

So we have three sections left to be completed: Projects, Testimonials and the Footer. Each can be placed in its own file within the src/partials folder.

projects.html

<wrapper class="projects">
    <row>
		<columns snall="12" large="12">
			<h2 class="text-center">Popular Projects</h2>

			<spacer size="20"></spacer>

			<p class="text-center">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>

			<spacer size="20"></spacer>
		</columns>
	</row>

	<row>
		<columns small="12" large="6">
			<a href="#"><img src="assets/img/project-thumb.png" alt="Project Name"></a>
		</columns>
		<columns small="12" large="6">
			<a href="#"><img src="assets/img/project-thumb.png" alt="Project Name"></a>
		</columns>
	</row>

	<row>
		<columns small="12" large="6">
			<a href="#"><img src="assets/img/project-thumb.png" alt="Project Name"></a>
		</columns>
		<columns small="12" large="6">
			<a href="#"><img src="assets/img/project-thumb.png" alt="Project Name"></a>
		</columns>
	</row>

	<row>
		<columns small="12" large="6">
			<a href="#"><img src="assets/img/project-thumb.png" alt="Project Name"></a>
		</columns>
		<columns small="12" large="6">
			<a href="#"><img src="assets/img/project-thumb.png" alt="Project Name"></a>
		</columns>
	</row>
</wrapper><!-- END .projects -->

testimonials.html

<wrapper class="testimonials">
    <row>
		<columns small="12" large="12">
			<h2 class="text-center">Don’t Just Take Our Word For It</h2>

			<spacer size="20"></spacer>

			<p class="text-center">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>

			<spacer size="20"></spacer>
		</columns>
	</row>

	<row>
		<columns small="12" large="4" class="show-for-large">
			<center>
				<img src="assets/img/user-icon.png" alt="User Name" class="user-icon">
			</center>
		</columns>
		<columns small="12" large="4">
			<center>
				<img src="assets/img/user-icon-primary.png" alt="User Name" class="user-icon">
			</center>
		</columns>
		<columns small="12" large="4" class="show-for-large">
			<center>
				<img src="assets/img/user-icon.png" alt="User Name" class="user-icon">
			</center>
		</columns>
	</row>

	<row>
		<columns small="12" large="12">
			<spacer size="40" class="show-for-large"></spacer>

			<spacer size="20" class="hide-for-large"></spacer>

			<p class="quote text-center">“Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex.”</p>

			<spacer size="30"></spacer>

			<center>
				<img src="assets/img/star-rating.png" alt="4 out of 5 Stars" class="star-rating">
			</center>

			<spacer size="20"></spacer>

			<h6 class="user-name text-center">Customer</h6>

			<spacer size="10"></spacer>

			<p class="title text-center">Title</p>
		</columns>
	</row>
</wrapper><!-- END .testimonials -->

footer.html

<wrapper class="footer">
    <container>
		<row>
			<columns small="4" large="5">
				<a href="#" class="facebook social"><img src="assets/img/social-facebook.png" alt="Facebook" class="float-right"></a>
			</columns>
			<columns small="4" large="2">
				<a href="#" class="twitter social"><img src="assets/img/social-twitter.png" alt="Twitter" class="float-center"></a>
			</columns>
			<columns small="4" large="5">
				<a href="#" class="youtube social"><img src="assets/img/social-youtube.png" alt="YouTube" class="float -left"></a>
			</columns>
		</row>

		<row>
			<columns small="12" large="12">
				<center>
				  	<menu>
				    	<item href="#">Link 1</item>
				    	<item href="#">Link 2</item>
				    	<item href="#">Link 3</item>
				    	<item href="#">Link 4</item>
				  	</menu>
				</center>
			</columns>
		</row>
	</container>
</wrapper><!-- END .footer -->

Styles

// Projects
// ===================================
.projects {
    @media only screen and (max-width: #{$global-breakpoint}) {
		h2 {
			font-size:28px !important;
		}

		p {
			font-size:14px !important;
		}
	}
}


// Testimonials
// ===================================
.testimonials {
	.wrapper-inner {
		padding-top:150px;
		padding-bottom:100px;

		@media only screen and (max-width: #{$global-breakpoint}) {
			padding-top:75px !important;
			padding-bottom:50px !important;
		}
	}

	.user-icon {
		max-width:90px;
	}

	.quote {
		font-size:18px;
	}

	.star-rating {
		max-width:94px;
	}

	.title {
		color:$medium-gray;
	}

	@media only screen and (max-width: #{$global-breakpoint}) {
		h2 {
			font-size:28px !important;

		}

		p {
			font-size:14px !important;
		}

		.quote {
			font-size:16px !important;
		}
	}
}


// Footer
// ===================================
.footer {
	background:$light-gray;

	.container {
		background:$light-gray;
	}

	.wrapper-inner {
		padding-top:32px;
		padding-bottom:10px;
	}

	.social {
		img {
			max-width:40px;
		}
	}

	.menu {
		.menu-item {
			a {
				font-weight:700;
			}
		}
	}

Including the Remaining Partials

Now we’ve created the final partials we can get them included within our index.html. Go ahead and add {{> projects}} and {{> testimonials }} immediately after the closing hero wrapper tag.

But what about the footer? The footer does need to be included but it will need to be placed outside the <container> tags. This is because it uses a full width background. Add {{> footer}} straight after the closing container tag.

Foundation for Emails: How to Use Panini Partials

Finishing Up

At this point, our email should be looking pretty good! However, you may have noticed fonts aren’t loading correctly. We defined the $body-font-family variable to use “Lato”, along with fallbacks. This is a Google font so we can import it in the app.scss file. Be sure to import this before anything else.

@import url('https://fonts.googleapis.com/css?family=Lato:400,700');

Now our email is finished, we can finalise it and get it ready for distribution! Using the foundation command helpers we can simply run foundation build which will minify images, inline css and package everything up!

Foundation for Emails: How to Use Panini Partials

Conclusion

We’ve done it! We’ve successfully built an email using ZURB Foundation’s Email framework and the Panini library! If you’d like to look at the other features included within Panini, the full documentation is available.

Foundation for Emails: How to Use Panini Partials