[Tutorial] How to import custom fonts into Perspective

Hi everyone! :wave:

There have been many questions and answers on this topic in the Forums, but I wanted to create a quick write-up on how to generally import custom fonts into Ignition to be used within Perspective - hopefully people besides future me also find this helpful!

Disclaimer: this may not work for all fonts (especially custom, licensed font packages). I will be using the popular Poppins font as an example, but I believe the process will be similar if not the same for other font families.

Step 1: Find a font

This is an obvious preliminary step - you can't import a font you haven't found yet. What I usually use is an open-source repository like Google Fonts. This is where I will download the Poppins font resource from - here is a link if you want to follow along.

Step 2: Download the font

Once you find one or more fonts that you like, click on the font you desire to import and click on the Get font button in the upper-right corner. This will add the font resource to a "cart", since you can presumably download many fonts all at once.

Picture

Then, click the Download all button.

Picture

Click on your browser's Downloads location to open the font archive.
Browser download

This is what the archive looks like, if you open it.

Step 3: Read and understand the font license

If you download a font from fonts.google.com, you will likely have an OFL.txt file in the archive. This file will contain any license agreements that may come with the particular font resource you downloaded and it should not be removed from the font directory (in my opinion - also that is explicitly what the license calls for).

Step 4: Create a top-level font folder in Ignition's installation directory

I'll create a Poppins folder in the default Ignition installation location, in the fonts folder. Obviously, if you downloaded the Fira Sans font instead of Poppins, for example, create a FiraSans directory (the Noto Sans font also has a space in its name and IA removed it, so we will follow that guideline for a font that has one or more spaces in its name, like Fira Sans or even IBM Plex Sans).

Default Windows installation location C:\Program Files\Inductive Automation\Ignition\data\modules\com.inductiveautomation.perspective\fonts

After you create a new folder inside of fonts (as seen in the snip above), you'll want to extract, copy and paste the contents of downloaded folder - if you downloaded the Poppins font, it should look like this:

Contents of /fonts/Poppins

Step 5: Create a new folder and a fonts.css file

If you read the README.md file in the \themes directory, you'll notice an important comment - any changes made to the light and dark folders (not the light.css or the dark.css files) will be overwritten on upgrade, so we don't want to place any new css files into those directories. Ideally, if you want to use a custom font, you'll also have a custom theme, but this is not a requirement. Another way you can do this is to just modify the light.css file directly and add your @font-face declarations there, but that seems like a bad practice to me.

Create a new folder in the \themes directory that will correspond to your future custom theme (if you don't have one already) or a directory that can store separate or disjoint css files. Again, this is an organizational step, only applicable to those who want a custom font without also creating a custom theme (again - this is just one of the many ways to do this).

A custom theme for a stealth corporation

Next, we will create a css file inside your custom theme directory - because we will use one css file for all of the custom fonts we may add, I'll call it something generic, like fonts.css. Here is what that looks like:

Generic file for custom fonts

:information_source: If you have trouble creating a file in this directory because of permission issues, create the file or folder in a different directory, such as on the Desktop, then cut it into the \themes location.

Step 6: Add @font-face declarations

Copy the following code into the fonts.css file you created above (in my case, \themes\brawndo\fonts.css):

Sample file contents
@font-face {
    font-family: "Poppins";
    font-weight: 100;
    font-style: normal;
    src: url('/data/perspective/fonts/Poppins-Thin.ttf') format('truetype');
}

@font-face {
    font-family: "Poppins";
    font-weight: 200;
    font-style: normal;
    src: url('/data/perspective/fonts/Poppins-ExtraLight.ttf') format('truetype');
}

@font-face {
    font-family: "Poppins";
    font-weight: 300;
    font-style: normal;
    src: url('/data/perspective/fonts/Poppins-Light.ttf') format('truetype');
}

@font-face {
    font-family: "Poppins";
    font-weight: 400;
    font-style: normal;
    src: url('/data/perspective/fonts/Poppins-Regular.ttf') format('truetype');
}

@font-face {
    font-family: "Poppins";
    font-weight: 500;
    font-style: normal;
    src: url('/data/perspective/fonts/Poppins-Medium.ttf') format('truetype');
}

@font-face {
    font-family: "Poppins";
    font-weight: 600;
    font-style: normal;
    src: url('/data/perspective/fonts/Poppins-SemiBold.ttf') format('truetype');
}

@font-face {
    font-family: "Poppins";
    font-weight: 700;
    font-style: normal;
    src: url('/data/perspective/fonts/Poppins-Bold.ttf') format('truetype');
}

@font-face {
    font-family: "Poppins";
    font-weight: 800;
    font-style: normal;
    src: url('/data/perspective/fonts/Poppins-ExtraBold.ttf') format('truetype');
}

@font-face {
    font-family: "Poppins";
    font-weight: 900;
    font-style: normal;
    src: url('/data/perspective/fonts/Poppins-Black.ttf') format('truetype');
}

@font-face {
    font-family: "Poppins";
    font-weight: 100;
    font-style: italic;
    src: url('/data/perspective/fonts/Poppins-ThinItalic.ttf') format('truetype');
}

@font-face {
    font-family: "Poppins";
    font-weight: 200;
    font-style: italic;
    src: url('/data/perspective/fonts/Poppins-ExtraLightItalic.ttf') format('truetype');
}

@font-face {
    font-family: "Poppins";
    font-weight: 300;
    font-style: italic;
    src: url('/data/perspective/fonts/Poppins-LightItalic.ttf') format('truetype');
}

@font-face {
    font-family: "Poppins";
    font-weight: 400;
    font-style: italic;
    src: url('/data/perspective/fonts/Poppins-Italic.ttf') format('truetype');
}

@font-face {
    font-family: "Poppins";
    font-weight: 500;
    font-style: italic;
    src: url('/data/perspective/fonts/Poppins-MediumItalic.ttf') format('truetype');
}

@font-face {
    font-family: "Poppins";
    font-weight: 600;
    font-style: italic;
    src: url('/data/perspective/fonts/Poppins-SemiBoldItalic.ttf') format('truetype');
}

@font-face {
    font-family: "Poppins";
    font-weight: 700;
    font-style: italic;
    src: url('/data/perspective/fonts/Poppins-BoldItalic.ttf') format('truetype');
}

@font-face {
    font-family: "Poppins";
    font-weight: 800;
    font-style: italic;
    src: url('/data/perspective/fonts/Poppins-ExtraBoldItalic.ttf') format('truetype');
}

@font-face {
    font-family: "Poppins";
    font-weight: 900;
    font-style: italic;
    src: url('/data/perspective/fonts/Poppins-BlackItalic.ttf') format('truetype');
}

:information_source: This is specifically for the Poppins font family and for the TrueType font standard (i.e. .ttf extention)! Adjust the contents of that file accordingly - for a reference, check the \themes\light\fonts.css file; there are both .woff and .ttf examples in that file.

How to generate above code for any font!

If you want to generate these file contents based on the font you selected, Google Fonts has an amazing tool called Get embed code that will get you 95% of the way there.

The section you'll want to copy into fonts.css is what you find under Poppins CSS classes (in my case):

Paste that code into fonts.css. We will need to make some manual changes: instead of using css classes, we'll use the @font-face at-rule for each font weight, and we will also need to add a src property to each font weight (Poppins comes with 18 different font weights by default and there is a .ttf file for each font weight inside of \fonts\Poppins). Implementing these two changes will get you exactly what I have in the "Sample file contents" code snippet above.

Step 7: Import the fonts.css file into \themes\light.css

The penultimate step is an easy one: update the \themes\light.css file and add an @import statement for our new fonts.css file.

Contents of lights.css:

@import "./light/index.css";
@import "./brawndo/fonts.css";

Step 8: Merge changes from the gateway and test!

You'll want to be sure that the changes you make on the gateway filesystem actually saved to disk - VSCode warns me that any change I make requires admin privileges and Auto-save won't work unless you explicitly allow the changes to be saved.

The other thing to be aware of is that the default scan rate by the gateway of the filesystem is 5 minutes. In other words, the gateway can be unaware of the changes you made within the fonts and themes directories for a time - this is normal.

:information_source: If you're on 8.1.28+, you can manually trigger a read using the new system.project.requestScan function.

If you have a Designer open, be sure to click the Merge button to get all the newest gateway changes.
Merge Simpson

If you have a View open, close it and reopen it after merging changes from the gateway. You should see the new font in the Designer after that!

Troubleshooting :wrench:

There are many things that can go wrong. Here are a few things you can use to troubleshoot what doesn't work.

:bell: Always check gateway logs!

Check the logs to see if there are any log messages from the perspective.ThemeManager logger. For some reason, when I created the brawndo folder, that change didn't register (probably because of the dumb name), so then I kept getting messages like you see below (even though my filesystem showed the correct folder name).

:bell: Check if browser can see your new resources

Navigate to your gateway webpage and check if your browser can download the font file. For instance, if your gateway is at localhost, you can use the following test URL:

http://localhost:8088/data/perspective/fonts/Poppins-Thin.ttf

This should trigger a download that will show up in your host machine's Downloads folder. If that doesn't happen immediately, that means your filesystem changes either weren't saved or the gateway can't see the new folders and files.

:bell: Check the browser DevTools

The last tip I'll mention when troubleshooting custom fonts is to double-check to make sure the @import statement in light.css is doing its job. Go to your browser DevTools -> Sources -> themes -> light.css and make sure the @font-face statements for your custom font appear in that file.

Another way to check this same thing would be to use the DevTools -> Network -> light.css file to check for the same thing.

:information_source: Our @font-face at-rules appear at the end of the light.css file because in our light.css file in the gateway filesystem, we import it after importing the \themes\light\index.css file.


If we switched the position of those to @import statements, our @font-face declarations would appear at the very top of light.css in the browser's DevTools. Hopefully that makes sense...

Conclusion

Let me know if this is helpful - I will try to edit it when new information comes to light. I tested this process on 8.1.36, but it's been very similar if not the same for a very long time.

19 Likes

Excellent tutorial! Just what I've been looking for.

Thank you for creating such a helpful tutorial.

1 Like