The ULTIMATE Service Portal CSS Guide

I work a lot with Service Portal, and luckily my background in web development has meant that I can see through it’s sometimes complex world, so that when something strange is going on I can usually find out why it’s happening, and know what to do to resolve it.

However, often people don’t have the advantage of having done web development from scratch before, and have not had the need, opportunity, or perhaps even desire to learn the fundamentals of web development. If you now want to do advanced widget creation in Service Portal it can be quite overwhelming.

Perhaps you’re a ServiceNow Administrator, and your manager has now tasked you with creating new widgets for your Service Portal. You might be a specialist in desktop enterprise application development and moving into the exciting world of Now Platform wanting to develop a custom interface for your apps in Service Portal. You might even be a web developer already, but new to ServiceNow and having trouble with understanding exactly how the many CSS fields that make up a Service Portal go together into one whole.

Without knowing the fundamentals, or having anyone with the necessary skills to lean on, it could be quite easy to spend hours or even days troubleshooting an issue. Worse even, after that time troubleshooting you may apply what you think is a fix, which will just cause more issues and confusion further down the line.

In this article, I’m going to explain some of the fundamental concepts of CSS, the various ways to create that CSS in Service Portal, and best practices when doing so. So read along, and if you like the article please share it on your social networks of choice! You can also follow me on Twitter at @dylanlindgren to get updates when I post similar articles in the future!

CSS Concepts

Along with HTML and JavaScript, CSS is one of the fundamental technologies of the web. Being a core web technology, knowledge of how it works will benefit you in the short, medium, and long term, as opposed to some technology concepts which can be quite ephemeral.

CSS is an acronym, which stands for Cascading Style Sheets. Knowing that they are related to a website, some key things we can derive from just that name alone is that:

  • They’re used to apply styling to a website
  • “Sheets” is a plural, hence you can have more than one of them.
  • The relevant definition of “cascade” in this context is to “pass (something) on to a succession of others”. So, as the style sheets are “cascading” we know they pass something on from one to the other, in a way similar to a waterfall, cascading downwards.

For some people, CSS is a strange beast. But, spending a little time understanding what I would say are the three key concepts about it, it can also become a very fun beast! It’s what transforms your ugly, brutalist website into a spectacular piece of art that you can be proud to show other people.

Thankfully, the internet has moved on! Back in the age of Internet Explorer 6, even when the design wasn’t that complex one would have to develop CSS which conformed to W3C standards (Firefox, Opera, Safari, etc), and then sometimes a completely different set of styles to allow it to work in Microsoft browsers. There are still sometimes cross-browser issues, but most can be worked out by testing early, and often, and almost never does something fundamental break.

Rule Sets

Without a doubt, if you’ve been exposed to web development (even by simply opening up your browser’s developer tools) you’ll have seen a CSS rule set before. Here’s an example of what one looks like:

A CSS Rule set
A CSS Rule Set

A rule set is made up of two components:

  • The selector: selects what elements the declarations within the rule set will apply to.
  • Declarations: particular properties to set on any elements which match the selector.
The selector and declaration of a CSS rule set

Similarly, the declaration also contains two parts:

  • Property: the name of the property to set the value of.
  • Value: the value to set for that property.
The property and value components of a CSS declaration

A declaration can also have the !important flag appended to the end which, as the name suggests, notes that the declaration is important.

The optional !important flag

We will see how this flag affects things shortly.


As mentioned earlier, you can have multiple style sheets for a single document. There are three different types of stylesheets in a document:

  • User-agent stylesheets: the default styles that come in a web browser, for example, to make a <button> element look like a button.
  • Author stylesheets: the style sheets supplied by the web page itself – i.e., the ones created by the developers of the website. Note that in the case of Service Portal, this means stylesheets you created, that ServiceNow created, and from any external libraries you’ve included.
  • User stylesheets: style sheets that can be defined by the user of the website.

Style declarations can also be made directly in-line with the HTML like so:

An in-line style declaration


With the amount of CSS from multiple sources that goes into making a website, a common scenario is that you might have multiple rule sets with declarations targeting the exact same property on the exact same element – a “competing declaration”. The cascade algorithm determines which of these declarations will win, and thus be used by the element.

Having competing declarations could be something you do intentionally, for example a generic rule set saying that the background-color property of a button is grey, and another “primary button” rule set saying that it is blue. You would target only the primary button on the page with the “primary button” rule set, but all buttons on the page with the generic rule set. This means for the primary button, it would have competing declarations for the background-color property.

Conflicting CSS declarations

In the case of a competing declaration, which gets used is determined using the order shown below. Note that the lower the number, the more important it is.

  1. Whether the declaration is included in-line with the HTML.
  2. Whether the declaration includes the !important flag.
  3. What type of style sheet the declaration is made in.
  4. What the specificity of the declaration is (more on this later).
  5. Which rule appears last in the stylesheet.

You can read more about the CSS Cascade on the MDN Web Docs.


If a competing declaration makes it all the way to step 4, the one with the most specific selector will be used for the targeted element.

A rule set’s selector is made up of one or more individual selectors. The number of individual selectors, along with the types of selectors, combine together to form the weight (specificity) of the rule set that will be applied to the declarations inside.

The number of type A selectors will be considered first. The more of this type of selector, the higher the weight. If there’s a tie, type B selectors will be considered next. Lastly, type C selectors are considered.

Specificity calculation

Going back to the previous example of a primary <button> element with two competing background-color declarations made on it, let’s see how this would play out.

Specificity calculation example

Here are some other example selectors, along with their specificity, and what order the elements would appear in given this.

SelectorElementsSpecificity WeightsSpecificity Order
.myClass1 class selectorA: 0
B: 1
C: 0
#myItem1 ID selectorA: 1
B: 0
C: 0
body div .myClass1 class selector
2 type selectors
A: 0
B: 1
C: 2
body #myItem div1 ID selector
2 type selectors
A: 1
B: 0
C: 2
body #myItem .myClass1 ID selector
1 class selector
1 type selector
A: 1
B: 1
C: 1

You can read more about specificity on the MDN Web Docs.


If there are no declarations made for a particular property (whether it be in-line, or in a style sheet), some properties will inherit their value from their parent element. A common example of an inheritable property is color. Often, this is set on the <body> element of a page, and it is inherited down throughout its children on the rest of the page.

There are also non-inheritable properties – border is an example of this.

This is quite useful behaviour, as it would be beyond annoying to have to define for every element in the page that the font color is black. It would also be similarly annoying to have to un-set the border on child elements of an element which has the border set on it.

You can read more about inheritance on the MDN Web Docs.

CSS Problems

As time has gone on, and CSS and web applications have become more feature rich and complex, developers started struggling with some very familiar problems. A lot of the problems related to the limited ability of CSS to adhere one of the key principles of software development: Don’t Repeat Yourself (DRY).

For example, if you wanted to use the same colour as a background color for a box, and as a text color elsewhere on the page, you would have to hard-code that color in separate declarations:

Duplicated values

For more complex sites, sometimes you’ll want to use a very specific selector. For example, the one below to define the border of a box:

If you now wanted to style some items inside that box, you’d need to repeat that selector all over again. For example, this is the selector you’d need to use to add some styling to an image in the box above:

Repeated selectors

Lastly, if there was a group of declarations which you wanted to apply to many rule sets, you’d be repeating the same code again and again:

Repeated blocks of the same declarations

All the above are not great when you’re trying to keep your code as “DRY” as possible. They increase complexity, which lowers maintainability, and increases the potential for bugs to exist, or be introduced in future versions.

The problem is that introducing features that solve the above problems are not really a good idea to do in the browser, as it requires changing the way that CSS fundamentally works. As of yet, no solutions to address the above problems have been introduced into the CSS specification.

Enter: SASS (and compilation)

SASS is language which extends CSS, and adds extra features to it to make it easier to use for developers. It stands for “Syntactically Awesome Style Sheets” (presumably they cared about the acronym rather than the name).

SASS works not by changing CSS language itself (which would require changing the browser), but instead by adding extra syntax and then compiling the code (converting it) into CSS once the developer is finished.

Features of SASS

All the problems mentioned in the previous section are addressed by three key features of SASS:


Nesting allows you to enclose CSS rule sets inside other CSS rule sets, and in the compiled CSS the selector on the inner rule set will be prefixed with the selector of the outer rule set. This eliminates the need to have repeated CSS selectors when targeting elements inside other elements that already have a rule set.

More on this at the Style Rules page on the the official SASS website.


Similar to variables in programming languages like JavaScript, variables in SASS allow you to define a value in a single place, and make use of it in other places in the file. This means you can group values together to reuse the same variable, and to change that value you only have to do it in one place, rather than have duplicated values.

More on this at the Variables page on the official SASS website.


Mix-ins allow you to define blocks of declarations, and then reuse them throughout multiple rulesets. This is useful when you want to apply the same group of declarations (for example, border styling) to multiple elements on the page, and stops you from needing to have repeated blocks of the same declarations on the page.

Note that you should always be mindful that comma-separating selectors in a rule set can accomplish similar results, of sharing a block of declarations across multiple elements. Even though in your SASS you won’t be repeating the block, by using mix-ins the resulting compiled CSS will have the block repeated, which can cause the CSS to be bloated and take longer to load.

You can read more one the Mix-ins page of the official SASS website.

More Features

There are many more features of SASS. You can find the full list of features on the official SASS website.


There are two different syntaxes supported by SASS:

  • Indented: The original syntax released with SASS. I’m really not sure why this exists. The start and end of a rule set is controlled by indentation, rather than the curly braces {} in standard CSS.
  • SCSS: A syntax very similar to CSS, with rule sets opened and closed using curly braces.

You can see a comparison of these syntaxes at the Syntax page on the official SASS website.

Implementation in Service Portal

So the first thing is that EVERY field that you can enter CSS into in Service Portal you can also enter SASS into. Before making its way to the user’s browser, the ServiceNow instance runs an in-built SASS processor over your fields to compile them into pure CSS, and sends that compiled CSS to the browser. Yay!

In total there are 6 different places that CSS can make its way from a Service Portal record into the user’s browser window. Below you can see each field, and what its purpose is:

1Service PortalCSS VariablesDeclare reusable variables that can be used in other fields
2Service Portal ThemeCSS VariablesDeclare reusable variables that can be used in other fields, across multiple portals
3Style SheetCSSCSS that should apply throughout the entire Service Portal
4PagePage Specific CSSCSS that should only apply to a specific page
5WidgetCSSCSS that should only apply to all instances of a particular widget
6Widget InstanceCSSCSS that should only apply to a specific instance of a widget

Even though it’s possible to enter any SASS/CSS into fields 1 and 2, to use Service Portal the way it is designed only SASS variables should be placed into these fields. Before we go into why this is the case, first I should explain scoping.


As widgets can be thought of as reusable, self-contained components, if you define a CSS rule set inside field 5 (widget), it should only apply to elements inside that widget, and not to other widgets. The same can be said for the field 4 (page) – rule sets defined in there should only apply to the page it’s contained in. This shows that for a number of the fields above, some type of scoping is needed – to scope it off from other elements on the page.

FieldRequires scoping?Reason
1NoDoesn’t ever make its way to the client directly – more on this later.
2NoDoesn’t ever make its way to the client directly – more on this later.
3NoThis file will only exist on the page for the portal which is included in.
4YesStyles in this field should only apply to the page.
5YesStyles in this field should only apply to any uses of the widget.
6YesStyles in this field should only apply to the individual widget instance.

Service Portal automatically attaches an identifying class or ID to each of the elements that contain a widget, a widget instance, or the whole page itself. When the database retrieves the contents of the fields that require scoping, they’re wrapped in a containing rule set (using SASS nesting) that selects the right element using the identifying class or ID.

FieldField contentsIdentifying class/ID formatExample output on client
4.myClass {}.page-[page_sys_id].page-273170321bbcc8106206b95bdc4bcb89 .myClass {}
5.myClass {}.v[widget_sys_id].v45e270b21bbcc8106206b95bdc4bcbb8 .myClass {}
6.myClass {}#x[instance_sys_id]#x73a145721bfcc8106206b95bdc4bcb07 .myClass {}

One absolutely key thing to understand here is that because all your CSS in these fields are prefixed by a scoping class, it will affect the specificity of your definitions inside the fields:

  • For CSS inside the fields on your page and widget records, it will add a type B selector, as it gets prefixed with a class.
  • For CSS in the fields on widget instance records, it will add a type A selector, as it gets prefixed with an ID.

Because of the importance of specificity in CSS this is very crucial to remember, especially when dealing with competing declarations across the various fields.

So now we know how Service Portal restricts fields so they only apply in the right places, let’s look into how the styles get to the browser.


A file called sp_bootstrap.scss is automatically included as a style sheet in the <head> tag of Service Portal. When Service Portal loads, this triggers the browser to make a request for it, and passes into it the portal_id parameter. This parameter identifies which portal we are accessing so it knows which record to look at for fields 1 – 3. Fields 1 and 2 are read from the database, combined in that order, and then the content from any style sheets (field 3) attached to the Service Portal Theme are added below them. The resulting SASS is compiled into CSS and sent back as a response.

The <link> element that requests sp-bootstrap.scss

Separately, the content of page you’re accessing is requested through the Service Portal API. This gets the structure of the page, such as containers, rows, columns, widgets, widget instances, and any widget dependencies. When each of the fields associated with these items is read from the database (potentially fields 3 – 6), the fields are scanned to see if any SASS variables are used, and if so once again the content from fields 1 and 2 are prepended to each of them which uses a SASS variable. Each item’s combined SASS is compiled into CSS and sent back with the response.

When the client receives the above from the Service Portal API, the compiled CSS for the page, each widget, and widget instance gets its own <style> element created by Service Portal’s JavaScript inside the <head> tag of the page. As new pages are loaded, and widgets are added and removed, these elements also get added and removed as necessary.

A <style> element created by Service Portal to host a widget’s CSS

Because of the behaviour of prepending fields 1 and 2 before the other fields, it is strongly advised to never put anything other than SASS variables into these fields. If you do, you will end up with duplicate declarations in each field which you have used a SASS variable in. SASS variables get removed as part of the process of compiling to CSS, and so there is no duplication in this case.

Best Practices

A lot of the information above I had to research for this article, and even though I’ve been working with Service Portal since it came out I’ve been able to get by without fully knowing the specifics of exactly how it works. It’s a lot to get your head around, especially if you’re new to web development, however hopefully you can use this article as a reference whenever something happens in Service Portal CSS which you don’t fully understand, and it can help you to get to the bottom of the issue, and apply the correct fix. I’ll be using it as a reference too!

Even though some of these details are new to me, the below best practices have served me well over the years to avoid pitfalls.

Prefix Class Names

Even though Service Portal widgets can be thought of as self-contained components, and there is some scoping applied to its CSS to stop it from affecting other things on the page, that doesn’t mean that other things can’t affect it.

An example of this is you could have a class called .alert defined in your widget. You can also have the same class defined on your page’s CSS, or in your theme. Of course, this may be intentional, however with a common selector like .alert it’s quite likely other things on your page could be selected by that too.

Furthermore, embedded widgets can still be affected by the widgets that they are embedded into. So a .alert class defined in a containing widget would apply to the embedded widget.

External CSS could also have an .alert class in it, and as external CSS doesn’t get scoped it would apply to your widget too.

My best practice I try to keep to is to come up with a short name or acronym for each page, widget, and portal, and prefix all my classes/ID’s etc inside it with that short name. For example, if I’m building a portal called “Marketing Event Manager” and the widget is called “Gantt Chart”, then for CSS classes in the widget I will call them something like .mem-gc-alert. There is a very low likelihood that a competing declaration could exist for that classes name unless it’s something I’m doing intentionally.

SASS Variable Naming

SASS variables are great as they allow you to modify the styling of your widgets, without needing to change/copy the widget itself. You can use the same widget on different portals, or different pages, and have things like font color, background color, and header size change to accommodate.

To give as much flexibility as possible. For example, you might be creating an alert widget. In the default color scheme of the widget your border color and text color may be the same. However, you should offer flexibility to allow these to be different. So, instead of using a variable name like $my-main-color you should separate that out to be $mem-gc-alert-text-color and $mem-gc-alert-border-color.

Default SASS Variables

Don’t forget, when a widget’s SASS is compiled, fields 1 and 2 are prepended to it. So, make sure you use the !default flag on all SASS variables in your widget. This flag basically means that this value will be used for this variable only if it doesn’t already exist.This will ensure that the values of the variables defined in your theme/portal get used, rather than the ones in your widget.

CSS Variables in the Theme

If you plan on using the branding editor on your Service Portal, be careful as modifications to it will saves the values in the CSS Variables field of your Portal record, overwriting any value already stored in there.

Put CSS Variable declarations into the CSS Variables field of the Theme record where possible.

Style Sheets for Portal-wide CSS

Lastly, I’ll repeat you shouldn’t be putting anything other than SASS variables into fields 1 and 2. If you have CSS that you want to apply to the entire portal, this should go in a Style Sheet record and should be included through the CSS Includes related list on the Theme record.


Once again, I hope this article has been valuable to you. Please share this article on social media, and let me know in the comments any feedback you have, questions, comments. Please do follow me on Twitter as well to keep up to date on new posts!