Hi everyone!
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.
Then, click the Download all
button.
Click on your browser's Downloads
location to open the font archive.
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\fontsAfter 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:
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).
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:
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');
}
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.
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.
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
There are many things that can go wrong. Here are a few things you can use to troubleshoot what doesn't work.
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).
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.
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.
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.