Making a VSCode theme is relatively simple - all you really need is a single .json
file.
However, this comes with a whole bunch of problems, the biggest one being the fact that you can't use variables in a .json
file. What if you want to change a color that was used in multiple places? You'd have to manually replace every single instance of that color.
Now you might think, well, with find & replace, that doesn't sound so bad. But what if you want to make multiple themes? You'd have to copy the entire .json
file, and then change every hex value manually!
When I made my own theme for VSCode, I already knew that I wanted to make many variants, so I wanted to find a way to use variables to make themes instead of writing every hex value literally.
So now that I've figured out how to do it, I'd like to share that method so that anyone else who wants to make their own theme knows how.
Setting up the project
The first thing you'll need to do is to create the project itself. Detailed instructions can be found on the VSCode documentation, but basically all you have to do is type the following in your terminal and VSCode's yeoman cli will help you generate the rest.
npm install -g yo generator-code
yo code
However, instead of creating a .json
file, create a new TypeScript (or Javascript) file in your src/
folder, and name it whatever you want.
Making the theme
In this file, you can define all your color variables. Then, make a function called getTheme()
which returns a JSON object. This JSON object should be in the format of a theme JSON, meaning it should specify the name, whether it's a dark, light, or high contrast, and the colors that the theme consists of. Then, export the function you just made, like so:
// src/mytheme.js
const blue = "#2D3079"
const blue2 = "#2C2E58"
const white = "#FFFFFF"
const black = "#000000"
// define as many colors as you want...
function getTheme() {
return {
"name": "My theme",
"type": "dark",
"colors": {
"editor.background": blue,
"editor.foreground": white,
"editorIndentGuide.background": blue2,
"editorRuler.foreground": white,
"activityBarBadge.background": black,
"sideBarTitle.foreground": white,
// ... add as many changes as you want
},
}
module.exports = getTheme
If you want to use translucent colors, you can either hardcode the alpha value at the end of the existing hex values, or you can use a helper function. For mine, I used the colors-convert
package.
npm install colors-convert
// src/mytheme.js
const { hexToHexWithAlpha } = require("colors-convert");
function hex(color, alpha = 1) {
return hexToHexWithAlpha(color, alpha);
}
// example usage:
"list.dropBackground": hex(blue2, 0.3),
Once you've customized all the color values (a detailed description of which can be found here), there's still more work to be done. First, we need to go into index.js
to actually create the .json
file from the function we just made.
// src/index.js
const getTheme = require("./mytheme")
// ... import any other themes you made
const fs = requre("fs").promises
// generate the json and store it in a const
const myTheme = getTheme()
// ... do the same for any other themes you've made
// write the .json file
fs.mkdir("./themes", { recursive: true })
.then(() =>
Promise.all([
fs.writeFile(
"./themes/my-theme.json",
JSON.stringify(myTheme, null)
),
// call fs.writeFile() again on all your themes
])
)
.catch(() => process.exit(1))
Now, if you run the extension in debug mode by pressing F5, you should see a new themes/
directory with a brand new .json
file in it!
All you have to do now is register your theme in your package.json
file:
// package.json
{
// ...
"contributes": {
"themes": [
{
"label": "My theme",
"uiTheme": "vs-dark", // or "vs" if it's a light theme
"path": "./themes/my-theme.json"
}
// ...repeat for the rest of your themes
]
}
}
And congratulations! You've just created a whole bunch of themes. Just remember that if you make any changes, you must run F5 again to write the changes to the actual .json files or none of the changes you made will actually change the theme.
To see a full example, check out my theme, lightning, on github. Or, you know, just install it and give me a rating if you like how it looks!
Happy coding!
Zev
Top comments (1)
This is an interesting approach! In my theme, I'm using a script to generate a combined theme — light with dark terminal — but both source themes are JSON.