Separating Theme from Project
Websites, mobile/desktop applications, single-page landers and everything digital all have ONE thing in common: the theme.
Brand consistency is a cornerstone in making sure your client is accurately represented across all mediums. You don’t see a different Nike brand on their mobile app from their website, do you? Keeping track of all these assets (i.e., the fonts, sizes, colors and graphics representative of a client’s digital identity) can be quite challenging, especially across multiple projects and other complexities (read: client rebrand). But it doesn’t have to be.
So how do you do it? Glad you asked. In this post, I’ll review creating a “global theme” (aka, a package containing all your assets that can be imported into any other project).
Prerequisites
- Yarn or NPM — to manage your package dependencies.
- GitHub or Bitbucket — for version control of your projects.
- Sass/SCSS or Less — preprocessor for your styles.
- Webpack or Gulp — bundle your source code into usable browser files.
Throughout this article, I’m going to be referencing Yarn, GitHub, Webpack and SCSS, these are just technologies I prefer to use. If you’re not using any of the listed technologies, then I’m sorry, we cannot be friends.
Ok, let’s begin.
Setup the global theme package
This will be the home base for our clients’ assets (e.g., styles, fonts, images). Folder organization won’t be covered here — look for another article where I’ll go in-depth on structuring a projects’ assets folder — so just try to keep things in a sensical hierarchy, as it will only benefit you and your team later down the road.
As you start defining your styles, take a few things into consideration:
- Limit yourself to
$variables
,%placeholders
,@functions
and@mixins
. - DO NOT create any styles based on class names or DOM structure. These change from project to project and you don’t want to pollute your global theme with project-specific structure.
- There should be very little output from this package, with the exception of
@font-face
styles or@keyframe
animations.
Sample global theme
// Colors
$color-brand: #c0ffee;
$color-accent: $c0ff33;// Fonts
@import url('//fonts.googleapis.com/css?family=Vollkorn:400,400i,700,700i');$font-family-primary: "Vollkorn", serif !global;
$font-weight-regular-primary: 400 !global;
$font-weight-bold-primary: 700 !global;$font-family-secondary: "LocalFont", clean, sans-serif !global;
$font-family-regular-secondary: 400 !global;@font-face {
font-family: "LocalFont";
src: url("path-to-font-file.eot");
src: url("path-to-font-file.woff2") format("woff2"),
url("path-to-font-file.woff") format("woff"),
url("path-to-font-file.ttf") format("truetype");
font-weight: normal;
font-style : normal;
};// Placeholders
%a {
color: $color-brand;
text-decoration: none; &:focus,
&:hover {
color: $color-accent;
text-decoration: underline;
}
}// Mixins
@mixin font-smoothing($aliasing: antialiased) {
@if $aliasing == antialiased {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
} @else {
-webkit-font-smoothing: subpixel-antialiased;
-moz-osx-font-smoothing: auto;
}
}
Create the global theme repository
Commit your global theme code to the Git manager of your choice as the master branch. Make sure the package has a proper package.json
file or you will, perhaps unsurprisingly, get a “Could not install from … as it does not contain a package.json file” error when you attempt to import the global theme into your project.
An added benefit of a version-controlled global theme is the ability to selectively choose specific branches/tags per project. For example, say you’re creating a new feature, you absolutely don’t want to roll that branch out across the board before it’s properly tested. Or, if you are making a breaking change to an existing feature, tag your current branch as a stable version so projects can opt-out of the update, if necessary.
Add the global theme to your project
We can now import that repo into a different project using the following command:
$ yarn add ssh+git://git@github.com:[username]/[my-theme-project].git
or, if you are targeting a branch/tag:
$ yarn add ssh+git://git@github.com:[username]/[my-theme-project].git#my-custom-branch
Once the repository is added, the dependency will show in the projects’ package.json
file. Take note of the name on the left side of the colon. You’ll need that name when importing.
{
...
"dependencies": {
...
"theme-project": "git+ssh://git@github.com:[username]/[my-theme-project].git"
...
}
...
}
Open your projects’ main SCSS file and add the following, near the top:
@import "~my-theme-project/[main-scss-file-in-package.json]";
Tip: When using Webpack, ~ will resolve to the node_modules
folder.
Now everything from the global theme will be imported into your project. Compile your CSS and you’re done. Rinse and repeat for every project from that client.
Conclusion
“Every minute you spend in planning saves 10 minutes in execution; this gives you a 1,000 percent Return on Energy!”
Managing global assets from one place isn’t difficult, it just takes a bit of planning. And, I’ll be the first admit that consistently referencing the node_modules
folder, or remembering what you called a $variable
or @mixin
, can be annoying. Unless, of course, you have an eidetic memory, but then you’re a better person than I. For the rest of us, more and more intelligent IDEs easily make the consequential pros far outweigh the irritating cons.
In an I-want-it-yesterday world, importing a customized, client-specific brand framework can save significant time in developing new projects. Moreover, as brand patterns evolve — either through incremental iterations or through full rebrands — the old paradigm means open countless projects to update. each. set. of. files. one. by. one. and. hope. you. don’t. miss. one. Hoping you maintain consistency versus verifiably updating one set of assets then recompiling that dependency for each project? I know which one I’d choose.