Custom fonts can add flair to your site, or help you comply with corporate branding guidelines. Regardless, there are some best practices to follow for adding a new font to your NetSuite Commerce web store.

Considerations

Broadly speaking, there are five things we need to think about:

  1. The license attached to the font you want to use
  2. How the font will be applied to the site’s look-and-feel
  3. Where the font will be served from (locally or remotely to the rest of the site’s resources)
  4. What file types to use to ensure browser compatibility
  5. How using a custom font will impact a web store’s performance

Font Licensing

Prior to beginning, it is important to understand the ramifications of using a custom font on your web store.

First, you must make sure you are allowed to. You will either need to own the font, or have a license from the person who does to use it on a commercial site. The specifics will vary from site-to-site and font-to-font, so make sure you are compliant.

Second, if you plan to use a ‘corporate’ font or some other proprietary font then know that using it on a web site like this will likely distribute a copy to all those who visit. While you may not be granting a license to those people to use the font, you will be giving them a copy regardless. If you need to add a layer of protection to your font files, then you’ll need to find a third-party service that is designed to deliver fonts remotely via JavaScript.

Also note that ‘free’ fonts may come with restrictions on how it can be used, so you’ll need to make sure you are compliant.

Once you have your font, you will then need to understand the mechanisms for applying the font to your site’s styles.

The easiest and best way to apply a font to a site is with the CSS3 @font-face rule. It essentially lets you define new font families and lets you build in provisions for different font file types, font weights, and font styles.

@font-face declarations go in CSS/Sass files. At their simplest, they declare a new font family name and where that font file should be sourced from — you can and should also declare what font weight (eg normal, bold, light, or numeric values) and font style (eg regular, bold, italic, etc) each declaration applies to.

Once defined, you can use your newly created font family name in your styling declarations. Here is a simplified example:

@font-face {
    font-family: "My New Cool Font";
    src: url("path/to/My-New-Cool-Font.woff");
}

body {
    font-family: "My New Cool Font";
}

This would tell the application that there’s a new font family, what it’s called, where to find it, and then to apply it to all text within the page’s body tag.

There are more detailed explanations available online; for example, see the MDN docs for more detail.

Non-Standard Application Mechanisms

I don’t know whether to class this as an application mechanism or delivery mechanism, but there are services that offer the ability to ‘protect’ fonts from being downloaded/copied onto a user’s device. This may be because the service designs and licenses those fonts (and wants to protect them) or if you have a font of your own that you want to protect.

These services do not use @font-face. Instead, they will require you to load a JavaScript file from their server, which then loads and applies the font dynamically without saving a copy to the user’s computer.

Some people also set a base font style and then use JavaScript to asynchronously load their custom font file after the page has loaded. This can improve the performance (both visual and actual) of a site as, by default, any text that requires a font to load first will not paint until it the font has been loaded; doing it asynchronously with JavaScript makes the text load and then progressively improves it. Generally speaking, this approach is fine but it’s a bit of a rigmarole and most people won’t need to go this route.

Delivery Mechanisms

So the next question becomes: what is the best way to populate that src parameter with a path to the font? Is it best to host it remotely on some cool font CDN, or to mux it among the rest of your code and serve it ‘locally’ (ie from the same server as the rest of the web store). Generally, speaking the best answer is the latter: we would say keep it with the rest of your source code.

The simple explanation is that it is more reliable and that you have more control over it. A call to a URL via @font-face will still result in additional HTTP requests, so you’re not cutting down on requests either way, but you know that as long your site is up then your font should also be available (and you know that it’s going to load at roughly the same time as the rest of your site’s assets).

Furthermore, when you have a copy of the font and make it available yourself, then you can control what is being sent. It is possible that a font may get updated, and you may not want that; some sites require that you, instead, load a full CSS file instead of just a font — what if they include additional styles you don’t want? What if they stop serving your font? It’s all unlikely, but you get more peace of mind from keeping a copy of the font along with your code.

If you decide to keep a copy of the font with your code, then the next question is where, specifically, you should store the font in your code.

If you are using SuiteCommerce, or a version of SuiteCommerce Advanced that is Aconcagua (2018.1) or newer, then the best way is as an asset to your theme or extension. For older versions of SuiteCommerce Advanced, you should create a custom module folder for your font which contains a fonts folder, and a Sass folder for your @font-face declaration. This method is also available for newer versions of SuiteCommerce Advanced, but we don’t recommend it for them.

We will discuss these methods now.

Serving it ‘Remotely’

A common way of serving font files is from a third-party CDN that specializes in serving font files. There are some services that offer this for free (where ‘free’ usually means ‘free at the point of delivery’ and can sometimes have strings attached). We’re not in a position to to make recommendations or provide analysis on these services: if this is something you want to pursue then you’ll need to find the one that works for you.

If you do go down this route (or, for example, your organization has a central server which serves font files) then you’ll just need to use the above @font-face rule in your Sass file, specifying the URL for the font file to this remote server. Eg:

@font-face {
    font-family: "My New Cool Font";
    src: url("https://www.mycoolwebserver.com/My-New-Cool-Font.woff");
}

Alternative Delivery with the @import At-Rule

Depending on the type of third-party server/service you are using, you may not be allowed to hotlink directly to your desired fonts. Instead, you will be required to use the @import at-rule instead.

This is a standard component of stylesheets (both CSS and Sass) and we use them throughout our Sass. They help you split up your styles into multiple stylesheets and then let you import them into other ones. Thus you can have the logical separation (eg across modules or different parts of your site) but then have them combined into one stylesheet.

Thus, it’s entirely possible to declare your font styles in another stylesheet and then just import them into your own. You can also use @import to fetch stylesheets from remote servers.

Therefore, if you’re going to use a third-party service your font, they may just specify that (rather than using @font-face) you just import their CSS into your stylesheets. It’ll look something like this:

@import url("//fonts.thirdpartyserver.com/css?family=My+New+Cool+Font");

This CSS file will then contain @font-face to declare their fonts.

Furthermore, as mentioned above, it is possible to deliver font files via JavaScript but this is non-standard and should only to be used in specific circumstances.

Serving it ‘Locally’

OK, technically serving a file locally would mean doing something like using a font file already on the user’s device. However, I am using this term to distinguish it from font files being served from a server other than the one used by the web store. Therefore, ‘local’ means stored and served with the rest of your site’s code, and ‘remote’ means a server third-party to the one your web store runs on.

Generally speaking, there are two ways available to you of doing this, depending on the product your web store uses and its code version.

  1. If your site runs SuiteCommerce or SuiteCommerce Advanced running Aconcagua (2018.1) or newer, then it is recommended you add your font file as an asset to a theme or extension
  2. If your site runs SuiteCommerce Advanced Kilimanjaro or older, then you should create a fonts folder in a module’s folder and put it in there (newer versions of SCA can also do this)

When dealing with either of these methods, there is also the question of the best way to generate URL path for your font file.

Themes and Extensions

The best place for your font is in the assets folder of an extension or theme. Choosing between the two is best decided by how you best conceptually tie the font to a customization. If you prefer a ‘clean’ theme, and you deliver a lot of ‘look-and-feel’ customizations via an extension, then you can keep it with your extension. Furthermore, if you have a customization that is being delivered via an extension and that extension requires, the font, then it definitely makes sense to keep the font with the rest of the code.

Generally speaking, however, it is best to keep fonts with the rest of the look-and-feel of your site, and that usually means the theme.

In your theme or extension’s workspace, there is (or can be) a folder on the same level as Modules which is/can be called assets. This is where we would recommend putting your font. Note that you can organize your assets directory with sub-directories, if you wish. For example, you may wish to have a fonts folder within it — if you do decide to do this, just make sure you update the paths in your code!

So, you’ve added your font file, now how do you reference that path? This path will vary depending on things like: the vendor name, the name of the extension or theme, and its version. Therefore, this path should never be hardcoded because it will break if one of those things changes.

The best option is tell the developer tools to generate the URL path for you. To dynamically generate a URL, use the helpers that we have built in. Depending on whether you referencing the assets folder of an extension or theme, you need to use getExtensionAssetPath() or getThemeAssetPath().

However, assuming that you are putting your font directly into a theme’s assets folder, your code would look something like this:

@font-face {
    font-family: "My New Cool Font";
    src: url(getThemeAssetsPath("My-New-Cool-Font.woff"));
}

Remember to use getExtensionAssetPath() if you’re using an extension instead of a theme.

Note that these helpers are also available for use within your template files, and that getExtensionAssetsPath is also available in your extension’s JavaScript files. You can, therefore, use them to reference other non-font asset files like services, images, and library JavaScript files.

SCA Source Modules

When working with SCA source code, you don’t need a helper like you do with themes and extensions; instead, you can just use standard syntax for referring to a path relatively.

Assuming that the font you are referencing is in a sibling Fonts directory to the Sass file you are currently editing, then you can reference your file by doing this:

@font-face {
    font-family: "My New Cool Font";
    src: url("../Fonts/My-New-Cool-Font.woff");
}

If you need to reference a font file in another module then you will need more instances of ../ to go further up in the directory structure before going back down, eg:

@font-face {
    font-family: "My New Cool Font";
    src: url("../../MyOtherModule/Fonts/My-New-Cool-Font.woff");
}

As is normal for SCA source module changes, you will need to update the module’s ns.package.json file to include the Fonts folder, eg:

{
    "gulp": {
        "fonts": [
            "Fonts/*"
        ],
        "sass": [
            "Sass/*.scss"
        ]
    }
}

Depending on how you organize your code, you may want to have a module just to load your custom font. If you are doing this then you will also need to update the distro.json file to include a reference to the module in the modules object, and a reference to it in the relevant applications’ CSS dependencies array.

Browser Coverage

In the examples above, we have only included woff formats of font files. All major modern browsers support this format, but it is not supported by older browsers like Internet Explorer 8.

In order to support IE8, you’ll need to also serve an Embedded OpenType (EOT) version of the font. To guarantee support for multiple browsers, you can also serve other versions of your desired font.

For example, in order to provide full coverage you could write your @font-face declaration like this:

@font-face {
    font-family: "My New Cool Font";
    src: url(getThemeAssetsPath("My-New-Cool-Font.eot"));
    src: url(getThemeAssetsPath("My-New-Cool-Font.eot?#iefix")) format("embedded-opentype"),
         url(getThemeAssetsPath("My-New-Cool-Font.woff")) format("woff"),
         url(getThemeAssetsPath("My-New-Cool-Font.ttf")) format("truetype"),
         url(getThemeAssetsPath("My-New-Cool-Font.svg#My-New-Cool-Font")) format("svg");
    font-weight: normal;
    font-style: normal;
}

body {
    font-family: "My New Cool Font", Helvetica, Arial, sans-serif;
}

Note that the first declaration sets a src parameter on its own — older versions of Internet Explorer don’t handle multiple values for a single src parameter very well, so we give it its own one first; other browsers work progressively through the different values until it finds one it supports. Generally speaking, this is a bit ‘overkill’ and is probably unnecessary, but if you absolutely want to cover all your bases then you’ll need to prepare and serve multiple versions of your code. (You may decide, for example, that it’s not important that users of older browsers see your custom font.)

Also note that in this example, I have set a font-weight and font-style. If you plan to use different font weights or styles, then you will need multiple versions of your font and multiple @font-face declarations for each style or weight. Luckily, many online font repositories provide multiple types of font files and will generate @font-face declarations for you!

Finally, make sure you always set backup font families just in case your new font file doesn’t load.

Performance

Generally speaking, using a custom web font will always decrease the performance of a site: it is an extra resource that must be loaded, it will add at least one extra HTTP request, and it will add additional CSS that must be processed and painted. You will need to balance the aesthetic needs of the site with the impact it will have to the performance.

How much will it affect performance? In most cases, generally not very much. Font files can be served from a CDN, and the painting of a site’s content will generally not take that long. Furthermore, font files can be cached on a user’s device the first time they are requested, so future attempts to load/paint the font will be much quicker. But just remember that loads of little performance hits can quickly add up!

Furthermore, @font-face loads synchronously, which means that it blocks the page’s loading/rendering from completing until it has finished doing its thing. If the requested font file takes an unusual amount of time to load, this can block the text from rendering and ultimately block the user from using the site. Some people suggest loading a font asynchronously and applying it after the initial render; this is a more complicated process (requiring JavaScript) but could be an option for the more performance-conscious organization.

Ultimately, there are no major concerns associated with custom fonts as long as best practices are followed, but the answer always depends on how lean you want to be.