
- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on 09-19-2022 07:33 PM
Preface
This article describes methods which are rather hacky in nature. None of this is officially supported, is likely to break on future versions/evolutions of the UI, and only works under limited circumstance. Proceed at your own risk.
How to apply custom themes to ServiceNow script fields
Step 1: Install a userscript browser extension
You will need to install a user script extension which allows custom javascript/css injection. The one I used is available for chrome and opera, your mileage may vary on other extensions. User JavaScript and CSS
Step 2: Find the theme you want
Download a theme css file from this list here: https://codemirror.net/5/theme/
These themes are officially curated by CodeMirror (the editor SN uses) so they should produce a good result
Step 3: Edit the CSS file
You need to do the following things in order to get the CSS file to overwrite ServiceNow's default styling
1. Change all references of ".cm-s-stylename" to ".cm-s-snc" as this is the tag which ServiceNow has applied to in the HTML.
2. Add a "!important;" flag to the end of every CSS selector. Your file should look something like this at the end.
.cm-s-snc.CodeMirror, .cm-s-snc .CodeMirror-gutters {
background-color: #282a36 !important;
color: #f8f8f2 !important;
border: none;
}
.cm-s-snc .CodeMirror-gutters { color: #282a36 !important}
.cm-s-snc .CodeMirror-cursor { border-left: solid thin #f8f8f0 !important }
.cm-s-snc .CodeMirror-linenumber { color: #6D8A88 !important }
.cm-s-snc .CodeMirror-selected { background: rgba(255, 255, 255, 0.10) !important}
.cm-s-snc .CodeMirror-line::selection, .cm-s-snc .CodeMirror-line > span::selection, .cm-s-snc .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10) !important}
.cm-s-snc .CodeMirror-line::-moz-selection, .cm-s-snc .CodeMirror-line > span::-moz-selection, .cm-s-snc .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10) !important}
.cm-s-snc span.cm-comment { color: #6272a4; !important}
.cm-s-snc span.cm-string, .cm-s-snc span.cm-string-2 { color: #f1fa8c !important}
.cm-s-snc span.cm-number { color: #bd93f9 !important }
.cm-s-snc span.cm-variable { color: #50fa7b !important }
.cm-s-snc span.cm-variable-2 { color: white !important}
.cm-s-snc span.cm-def { color: #50fa7b !important}
.cm-s-snc span.cm-operator { color: #ff79c6 !important}
.cm-s-snc span.cm-keyword { color: #ff79c6 !important }
.cm-s-snc span.cm-atom { color: #bd93f9 !important }
.cm-s-snc span.cm-meta { color: #f8f8f2 !important}
.cm-s-snc span.cm-tag { color: #ff79c6 !important}
.cm-s-snc span.cm-attribute { color: #50fa7b !important}
.cm-s-snc span.cm-qualifier { color: #50fa7b !important }
.cm-s-snc span.cm-property { color: #66d9ef !important}
.cm-s-snc span.cm-builtin { color: #50fa7b !important}
.cm-s-snc span.cm-variable-3, .cm-s-snc span.cm-type { color: #ffb86c !important}
.cm-s-snc .CodeMirror-activeline-background { background: rgba(255,255,255,0.1) !important}
.cm-s-snc .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }
Step 4: Add this code to the Javascript section:
const userStyles = `
.CodeMirror-code div { font-size:15px !important; font-family: "Fira Code" !important; }
.cm-s-snc.CodeMirror, .cm-s-snc .CodeMirror-gutters {
background-color: #282a36 !important;
color: #f8f8f2 !important;
border: none;
}
.cm-s-snc .CodeMirror-gutters { color: #282a36 !important}
.cm-s-snc .CodeMirror-cursor { border-left: solid thin #f8f8f0 !important }
.cm-s-snc .CodeMirror-linenumber { color: #6D8A88 !important }
.cm-s-snc .CodeMirror-selected { background: rgba(255, 255, 255, 0.10) !important}
.cm-s-snc .CodeMirror-line::selection, .cm-s-snc .CodeMirror-line > span::selection, .cm-s-snc .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10) !important}
.cm-s-snc .CodeMirror-line::-moz-selection, .cm-s-snc .CodeMirror-line > span::-moz-selection, .cm-s-snc .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10) !important}
.cm-s-snc span.cm-comment { color: #6272a4; !important}
.cm-s-snc span.cm-string, .cm-s-snc span.cm-string-2 { color: #f1fa8c !important}
.cm-s-snc span.cm-number { color: #bd93f9 !important }
.cm-s-snc span.cm-variable { color: #50fa7b !important }
.cm-s-snc span.cm-variable-2 { color: white !important}
.cm-s-snc span.cm-def { color: #50fa7b !important}
.cm-s-snc span.cm-operator { color: #ff79c6 !important}
.cm-s-snc span.cm-keyword { color: #ff79c6 !important }
.cm-s-snc span.cm-atom { color: #bd93f9 !important }
.cm-s-snc span.cm-meta { color: #f8f8f2 !important}
.cm-s-snc span.cm-tag { color: #ff79c6 !important}
.cm-s-snc span.cm-attribute { color: #50fa7b !important}
.cm-s-snc span.cm-qualifier { color: #50fa7b !important }
.cm-s-snc span.cm-property { color: #66d9ef !important}
.cm-s-snc span.cm-builtin { color: #50fa7b !important}
.cm-s-snc span.cm-variable-3, .cm-s-snc span.cm-type { color: #ffb86c !important}
.cm-s-snc .CodeMirror-activeline-background { background: rgba(255,255,255,0.1) !important}
.cm-s-snc .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }`;
// Make UserStyles a copy of your CSS side, the below class simply is used to inject into the content view iframe.
class CSSInject {
styles = "";
href = "";
id = 0;
iframe = undefined;
form_id = "";
contentDocument = undefined;
intervals = [];
constructor(id){
this.id = id;
this.href = window.location.href;
this.styles = userStyles;
var css = document.createElement('style');
css.type = 'text/css';
if (css.styleSheet)
css.styleSheet.cssText = this.styles;
else
css.appendChild(document.createTextNode(this.styles));
this.css = css;
}
log(msg){
console.log("CSSInject", msg);
}
setStylesIframe(){
/* Append style to the tag name */
this.contentDocument.getElementsByTagName("head")[0].appendChild(this.css);
this.log("Styles set")
}
clearIntervals(){
for(var i of this.intervals){
clearInterval(i);
}
}
setIframe(element){
if(element){
this.iframe = element;
this.log("New iframe set");
var doc;
if(element.document)
doc = element.document;
else if (element.contentDocument)
doc = element.contentDocument;
this.log(doc);
if(typeof doc == "undefined"){
throw new Error("contentDocument undefined");
}
if(doc.querySelector("title") == null){
throw new Error("Page not loaded");
}
this.contentDocument = doc;
this.log("contentDocument set");
this.form_id = this.iframe.g_form.getUniqueValue();
this.log("Form id set as " + this.form_id);
return true;
} else {
throw new Error("Element not passed");
}
}
}
var inj = new CSSInject(Date.now());
if(window.location.href.includes("/now/nav/ui/classic")){
loadStyles();
}
function loadStyles(){
var int = setInterval(() => {
inj.intervals.push(int);
let success = false;
try{
inj.log("Trying to fetch iframe");
success = inj.setIframe(window.gsft_main);
} catch(e){
console.error(e);
}
if(success){
clearInterval(int);
inj.log("Setting styles")
inj.setStylesIframe();
monitor();
}
}, 50)
}
function monitor() {
window.gsft_main.addEventListener("unload", () => {
inj.iframe = undefined;
inj.contentDocument = undefined;
inj.form_id = "";
inj.log("Iframe unloaded, loading again");
loadStyles();
})
}
Tested and works in Polaris UI, both when popped in and popped out. Untested pre-polaris UI.
- 2,950 Views

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
This is useful, but the dependency of the navigation breaks it all...
I am using an extension called SN Developer productivity (available only for firefox), which is adding the style to the script fields everywhere.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
You're right, I've figured out how to inject the CSS to the iframe, updated CSS and JS sections in the post above.