Styling SparkPost

Styling things in an app that consists of 50,000 lines of code is pretty scary. When you know that anything you touch could break something else, it’s hard to have the confidence to amend or remove existing CSS. This results in our team taking the safer approach most of the time and overriding existing styles with more CSS classes and more specificity (and sometimes !important ). Over time, it’s gotten to a point where it’s just bloated, full of cruft, and unmaintainable.

css gif css modules

As we’re now migrating our app to React, we have the unique opportunity to completely retool and rebuild our styles from the ground up. With so many different ways to style react components in 2017, it was pretty difficult to find the best solution for our new design system, called Matchbox.

We determined that whatever we built should be:

  • Fast to build
  • Component scoped
  • Reusable (even without React or JavaScript)

We decided to go with CSS Modules, and here’s why:


While CSS-in-JS seems to be pretty trendy, especially within the React community, we decided to go with something that allows us to use regular Sass. We weren’t quite ready to throw away CSS and lock ourselves into a full JS solution that seemed to lack the maturity that Sass provides. For example media queries, keyframes, pseudo elements, editor support.

We’re pretty good with Sass. We knew we’d be comfortable working with it and we knew we’d be fast with it. Not having to spend the time retraining ourselves or anyone in the future who joins our team is a bonus.

But Sass by itself does not provide us the modularity that we wanted – that’s where CSS Modules come in.

No Global Scope

While methodologies like BEM, SMACSS, and ITCSS are pretty effective at encapsulating styles and controlling CSS’s global cascading nature, we wanted to take it a step further. We wanted our devs to be able to just write CSS without having to learn or subscribe to strict naming conventions.

At its core, CSS Modules is really just a pretty neat way of automating BEM. The class names it generates are unique and localized to its component for us, so we’ll never need to think about what to name our classes ever again.

For example, the CSS class  .Input {} used in a <TextField />  React component compiles into a class name that looks like this: .TextField__Input___1Vvpx , with a unique hash appended to ensure its styles stay local.


If you’ve read my post on how we designed our onboarding experience, you might remember that we value design consistency. With CSS Modules, we can use our Sass functions, mixins, and component styles elsewhere, even without the React or JS dependency. We wanted to use whatever we built across different projects to help ensure our brand’s design language is consistent.

Without going into too much detail, we do this by passing through a custom generateScopedName function to CSS Module’s config that will auto-BEM our class names when compiled.

Instead of the default template that looks like: [name]___[local]___[hash:base64:5] , our class names compile from:

into something like…

Pretty neat. Without that unique hash, others can use our styles from a normal .css  file.

CSS is Awesome Again

Honestly, we’re having fun styling things again. Building components without worrying if something on the other end of the app will break is something every front end developer greatly appreciates.

If you’re reading this looking for advice on how to style your React app, consider CSS Modules for its flexibility. While we’ve found a set of tools that work for us, other solutions might be worth considering depending on your needs – for example, if you’re working with React native, look into CSS-in-JS tools.


We’re building our React components and styles out in the open, so feel free to check out the code for yourself, and maybe even style your next side project with it. For now, Matchbox is just a component library. In the future, we hope to see Matchbox become a full design system, complete with brand and content guidelines, components, and a UI kit. If you have any questions about this or if there’s anything else you’d like to hear about, let us know!


-Jon Ambas,
Senior Front End Engineer

Dev Survival Guide Blog Footer

White Labeling Email Communications with Template Substitutions

In past discussions, we have talked about how substitution can be used to create dynamic emails. This drastically decreases the number of templates that need to be managed by using conditionals and looping statements. But did you know that you can also use substitution for your CSS within an email?

For companies hosting email services and providing sample templates to their customers, this capability can significantly decrease the number of email templates needed. In order to illustrate the challenges and how template substitutions can solve many of those issues, let’s create a fictional ISP who is bringing on a new customer.

A Practical Application

So, let’s imagine a fictional ISP named SuperComm; they provide corporate phone and webinar services to their customers. Emails from SuperComm to their client’s employees (e.g. sign-ups, feature updates, and personalized notices) are all branded for that specific client using their own color scheme and logos. In this example, SuperComm just acquired Graphite550 as a client and now needs to start the process of helping Graphite550 to get their employees to use the SuperComm platform. In order to do this, SuperComm’s Account Managers obtain the following information from Graphite550:

  • Color scheme: white and orange
  • Copy of Graphite550’s logo
  • Graphite550 phone support numbers
  • Graphite550 support website URL
  • Address
  • Corporate URL

Once they have this information, the account manager goes into the SuperComm repository and retrieves a copy of the 15 default emails that are used for each SuperComm customer. They then spend the next several hours branding each of these email templates with Graphite550’s information. As you can imagine, this is a very error prone process which typically needs a few iterations and the eye of a few different employees to get right. Once finished, SuperComm then needs to keep each of these templates in a repository along with all of their other 700 customers. While SuperComm has done everything they can to minimize changes by separating out the main body from headers or footers, maintaining over a thousand templates is very challenging.

So for this example, let’s take a look at the welcome email that will go out to each Graphite550 employee.

Just this one email has over 20 different fields that SuperComm uses in order to brand the email to Graphite550, which turns out to be over 65 individual replacements that have to be done by the account manager. If the other 14 templates are similar to this one, that means there are close to 1000 changes that need to be made for each customer!

So how can this be simplified? SparkPost has the capability to not only support recipient-focused personalization like ‘first_name’ and ‘accountid’ but also CSS entries, enabling per-customer white labeling. In the above example, the title line actually looks like this in the template:

Not only is the company name a substitution field, but so is the background color and the text color which are passed to SparkPost along with the employee personalization. Here is the global substitution data for Graphite550:

Note: In our example, we are using inline CSS but those CSS fields could also be placed in the header, as in this example:

In this new approach all the account manager needs to do is to put this data into a simple web form. This form, created by their IT department, obtains the necessary data, generates a preview for confirmation, and places it into a database. With this new process, the application triggering the welcome emails to each new customer will not only obtain the personalization fields like first name, but also the branding fields. Both types of information are then sent to SparkPost so the email can be branded and personalized during the generation process.

By using branding substitution fields within each template, SuperComm can clean out their repository of 1000+ branded templates down to the original 15 that can be used for every one of their customers. As a result of this, customer acquisition costs decrease significantly and template management becomes simpler.

Now that you know this, the next question is, how can substitution simplify your life?

Happy Sending,
Jeff Goldstein

Please feel free to leave any questions about template substitutions or white labeling in the comments.

We’re adding some great features to help developers looking for a Mandrill alternative. Spoiler: subaccounts are here.

orange we heart developers banner twitter awards

** 3/31/2016 – Update: Subaccounts are now live! Further detail here.

A Feedback Frenzy: How You’re Helping to Make SparkPost Better

Wow. It’s been an amazing month of hard work for the product team here at SparkPost. And I know I’m not the only one keeping my caffeinated drink of choice flowing (through an IV drip, if necessary. Diet Coke girl, here BTW).

We’ve always worked to make SparkPost the most awesome email delivery service, period. And we hear from developers and other customers with product feedback pretty often. But, in the wake of MailChimp’s decision to stop offering their Mandrill product as a stand-alone offering (and endorsing SparkPost as a Mandrill alternative for developers), our Twitter and community Slack channels have been flooded with feedback, feature requests, praise, and yes, even constructive criticism. And we’ve tracked, discussed, and prioritized every single one. In fact, if you’ve given us product feedback, you’re likely to have seen one of our product managers or engineers reach back out for additional insight on the pains, challenges, and use cases you’re trying to solve.

This type and volume of feedback is every product manager’s dream come true, and I want you to know that we’re giving your feedback the care and attention it deserves. That’s just how we work. For over 15 years, our team has lived and breathed the belief that partnering with our customers to drive innovation and excellence in messaging is the right thing to do.

Now, that’s not to say we’re going to implement every feature or make every change that’s asked of us. A big part of my job is to take a hard look at requests to ensure they:

  • Help developers integrate our service easily… and make it possible to really innovate with email;
  • Meet the functional needs of the current and future markets we serve; and
  • Are aligned with our goals and values as a company, as well as the best practices in the email and tech industries.

This perfect storm of feedback could have become really overwhelming, really quickly. Fortunately, we’re big believers in agile development practices. And, as an agile company, leveraging a mix of Scrum and Kanban, we’re pretty darn good at knocking out small wins while also working to implement more complex or comprehensive improvements. We’re also huge fans of iterating on features—allowing our customers to get started using a feature, sooner rather than later. Once a feature or improvement is released, we capture feedback on how it works in the real world, and what could use a little tweaking, and continue to iterate from there.

As a product manager, It’s been gratifying to me to see how well the agile development practices really work, even (or perhaps especially!) at the pace that we’ve been working over this past month.

Here’s the New SparkPost Goodness

So: what have we done in the last couple of weeks? A lot! Without further ado, I’ll summarize some of new SparkPost highlights of the past month:

  • We got the pricing right: Check out what we’re doing with SparkPost’s pricing
  • Test Mode: The ability to test your integration before moving it to production, without the fear of sending to real live customers! We’ve also heard requests to support test-only API keys and webhooks—it’s definitely on our radar. Learn more about SparkPost’s new test mode.
  • CSS Inliner: To ensure that your email looks the same across the wide proliferation of inboxes (particularly with the…quirks… of Gmail), it’s a good practice to inline your CSS by removing it from a <style> block and putting it directly into each HTML attribute. That can be extremely painful and honestly, ain’t nobody got time for that. Put some fun back in your day and let us handle this task for you. Learn more about CSS inlining with SparkPost.
  • Mandrill Template Converter: Our template guru Ewan Dennis recently wrote some preliminary tips for manually translating Mandrill templates for SparkPost. Now, he’s working on an automated tool to make it even easier. The tool is still in… let’s call it beta, but if you want early access (and are willing to do some real-world testing), he’d love to have you. Join the SparkPost community Slack and ask for @edennis. He’ll give you the good stuff. **Update: the Mandrill-to-SparkPost template tool is live! Check out Ewan’s latest post about where to get it and how to use the tool to convert and migrate your Mandrill templates.
  • WordPress Plugin: We’re continuing to evolve this plugin by adding support for API over SMTP for people that are blocked for ports 587/2525, template selection, and to allow tracking to be toggled on/off from the plugin. Have more ideas? Please share them! Learn more about SparkPost’s WordPress plugin.
  • C# Client Lib: This one makes our heart swell because it came from a community member! Thank you thank you! Check out the community-developed SparkPost C# library.
  • Run SparkPost in Postman: SparkPost is an API-first service, because we love developers. And because it’s the best way to innovate with email. It’s that simple. What this means in practice is that we build our APIs (you guessed it) first, and then build our UI using those same API calls. Having said that, we also love our UI, and there are plenty of SparkPost users who’d rather not use a cURL command line or dig into the details of HTTP to build their API requests. This is where Postman comes in, turning an API request and response into something much more human-readable. Learn more about running SparkPost in Postman.
  • Slack community: where our teams are available for real time feedback on integration support, best practices, and developer love. Also? We’ve just uploaded all of our favorite emojis. It’s amazing what a little :homerbush: can do for your mood. Join the SparkPost community Slack team.

Oh, and One More Thing: Subaccounts! 

Of all the requests we’ve received over the last several weeks, by far the one raised most frequently is for “Subaccounts.” Fortunately, we were already well underway in terms of R&D for this feature, and we were able to shift some other priorities around in order to focus on bringing this to market ahead of the Mandrill cutover on April 27.

Before getting into any of the details, let me answer the most frequent one: “When?”

** 3/31/2016 – Update: Subaccounts are live! This initial launch will be closely followed with additional feature updates throughout the month of April, with all of the core components in place by the week of April 20. We know that this timing will make it tight for some customers who currently rely on Mandrill’s subaccount features. So, here’s what we’re doing:

  • We’ve already updated the API and SMTP documentation to include the subaccounts components, so you can start preparing immediately. The subaccounts API and SMTP documentation lives in our Developer Hub.
  • A comprehensive knowledge base article will be available within a few days that will outline use cases, implementation specifics, how-to’s,; and a host of future enhancements we’re already focused on.
  • Our awesome team is available on Slack to help answer any integration questions you may have.

What all of this means is that you don’t need to wait for the Mandrill cut-off date to get started with your migration. You can open a SparkPost account now, begin your integration, and familiarize yourself with the features and resources that are already available. By following these steps you can be up and running with subaccounts prior to the April 27 Mandrill cut-off date.

Some more details on subaccounts:

  • Subaccounts will be available on all pricing plans, including free. There will be no additional charge associated with subaccounts.
  • Both the UI and our APIs have support for subaccounts features, though some areas of the UI and API will not be supported fully at launch.
  • The first launch in early April will provide subaccount support for the following features:
    • Metrics API (Not available for subaccount API keys)
    • Message Events API
    • Sending Domains API
    • Tracking Domains API
    • Suppression List API
    • SMTP API
  • Following closely behind the initial launch (but before the Mandrill cut-over) will be subaccount support for:
    • Transmission API
    • Custom Tracking Domains
    • And more!

In addition to subaccounts, we’re actively underway with providing customers the ability to have multiple dedicated IPs per account, as well as the ability to manage those IPs for your subaccounts. More to come on those items in the next couple weeks as well.

Thank You, and Please Keep Your Feedback Coming! 

I want to acknowledge personally how valuable the feedback of our growing developer community has been in helping us to prioritize and accelerate many of these new SparkPost features.

To everyone who has taken the time to reach out to us, please accept my genuine thanks and appreciation. It’s people like you, sharing the good and the bad, that are helping us make SparkPost an even more amazing service for everyone. You rock. I’m reminded every day why I love the developer community.

If you haven’t joined in the conversation yet, please do! I’d love to hear from you on Twitter @AmieDurr. And now, you also can find me in our community slack.

-Amie Durr
VP Product Management

** 3/31/2016 – Update: Subaccounts now live! Further detail can be found here.

Biz Eval Guide Blog Footer

css inlining

TL;DR – add "inline_css": true to your Transmission Options object.

If you’re reading this blog, you probably know a thing or two about email. What’s tricky about email is that there are more than a few things that need to be just right in order for your customers to be able to interact with what you send them. One of those things is CSS inlining, and it affects how your HTML email is rendered in many email clients – is that white text on a blue background, or is it invisible?

Why Inline?

The easiest way to understand why CSS inlining matters is to think about how a web-based email client displays HTML messages. In that scenario, the email client itself is built in HTML, and is already using CSS for various things. So how can the email client display HTML messages, without allowing the style rules within each message to affect the display of the email client itself? The simplest and most consistent approach is to remove any CSS rules, which leaves only style attributes on each individual HTML tag, AKA “inline styles.” This is the approach that many email clients take, especially web-based email clients.

So that’s the “why” part of CSS inlining. What about how? SparkPost runs on the Momentum platform, which includes several libraries that make the inlining process easier. CSS inlining has been on our radar for a while, which included building several proof-of-concept implementations, with a variety of approaches. We’ve recently received lots of requests for this feature, which bumped its priority on our roadmap. Voilà!

How to Enable Inlining with SparkPost

Enabling automatic inlining is a simple change – add "inline_css": true  to your Transmission Options object, and send as usual. We didn’t see a significant increase in generation time during our performance testing of this feature, however it is possible that your special CSS may cause generation to take longer than usual.

Inlining and Advanced Templating

SparkPost offers templating features that can change the structure of HTML messages, such as conditional content ( if / then / else ) and dynamic per-recipient content. Our CSS inlining is fully compatible with these templating features, since inlining happens for each individual message, after template processing has been completed.

Selector Support (CSS1, CSS2, CSS3, Oh My!)

There are lots of types of CSS selectors, and they can also be combined so that, for example, the color of an element changes based on the element(s) that contain it. SparkPost’s CSS inlining support covers most common usage for email, with the following exceptions:

From CSS1, we do not support:

  • ::first-letter
  • ::first-line
  • :active
  • :focus
  • :hover
  • :link
  • :visited

From CSS2, we do not support:

  • :first-child
  • :lang

Some of these are excluded because it is impossible to support them correctly ( :active , etc). Others because they are simply shortcuts – p:lang(en)  can also be written p[lang="en"] .

Support was also added for some CSS3 attribute value comparison operators:

  • [attribute^="value"] – “begins with”
  • [attribute$="value"]  – “ends with”
  • [attribute*="value"]  – “contains”/”substring”

Did we miss your favorite CSS selector? Which one, and how have you used it with email?

Have you been inlining for ages? How can we make your workflow easier?

Or did the world just become a little more complicated when you learned that CSS inlining was a thing?

Come chat with us on Slack or Twitter, and let us know what you think.


If you liked this post, check out Advanced Email Templates