How to add syntax highlighting to Code Snippets on your website, app or blog
Tags: beginners, javascript, css, webdev
Published: 2021-10-13 08:14:32

Have you ever wondered how sites like [Dev.to](https://dev.to/), programming blogs and landing pages (like https://ohmysmtp.com) show little snippets of code with nice syntax highlighting? Read on to find out how to set this up on your site.

*Note that there are code screenshot sites like https://carbon.now.sh/ that will give you great little screenshots of your code. But these are mere .pngs, they're not accessible, searchable or copy & pasteable. That's NOT what we're going to do here, our output will be fully accessible and appear as text on the page.*

Code syntax highlighting looks like magic, but the actual reality is less complex than you might think. Let's get started.

## Dependencies

We're going to use [PrismJS](https://prismjs.com/) to do all the heavy lifting. 

There are a couple of choices to bring it into your project. If you're already using a JS Bundler (e.g. esbuild or Webpack) you can setup the [Babel Plugin for Prism](https://github.com/mAAdhaTTah/babel-plugin-prismjs). For our demonstration we'll do this the old, simple way, writing our HTML tags directly. 

Start by heading over to https://prismjs.com/download.html and:

- Choose languages you want to support (keep this as small as possible to reduce file size)
- Pick a theme
- Download the `prism.js` and `prism.css` files and place them in your project

Finally we include them in the HTML page. CSS goes in the `<head>` section and the JS can go at the end of the `<body>` tag. 

> Tip: Place the JS at the end of the `<body>` section to avoid delaying loading the rest of the page

```html
<head>
    ...
    <link rel="stylesheet" href="prism.css">
</head>
<body>
    ...
    <script src="prism.js"></script>
</body>
```

## Adding the Code snippets

Next we'll add the code snippets we want to highlight plain old `<code>` tags. For example:

```html
<code>
   const variable = "Here's some JavaScript";
</code>
```
Refresh the page, and you'll just see the code unhighlighted, like this:

```
const variable = "Here's some JavaScript";
```

We need to tell Prism to highlight the code block and which language to use. To do this we'll add a HTML class to the `code` block, in this format: `class="language-XXXXX"` where XXXXX is the language, like this:

```html
<code class="language-javascript">
   const variable = "Here's some JavaScript";
</code>
```
Finally we'll wrap everything in a `<pre>` tag. This will "Preserve" the formatting and indentation of our code block so we can display it exactly as it would appear in the editor.

```html
<pre><code class="language-javascript">const variable = "Here's some JavaScript";</code></pre>
```
Note that I've removed the line breaks / whitespace (these are usually ignored by HTML parsers). This is a bit awkward to read in our editor, but it means the JavaScript will appear exactly as we want it when rendered by Prism:

```javascript
const variable = "Here's some JavaScript";
```
## How this works

Our original HTML consists of standard `<code>` blocks, which are generally used for code examples, so the browser kind of knows how to display these without highlighting.

The Prism JavaScript scans the page searching for code blocks with "language-XXXXX" tags, and when it finds them it treats these blocks as code that requires syntax highlighting.

Prism them applies the syntax highlighting by:

- Breaking each known code string into individual language "tokens"
- Wrapping them in `<span>` tags 
- Categorizing them into types of language token (e.g. operator, punctuation, string etc.) and labelling them 

It does most of the work using Regular Expressions, which you can easily read through in the source (e.g. for JavaSript the rules are here: https://github.com/PrismJS/prism/blob/master/components/prism-javascript.js)

The `prism.css` rules then take care of the actual colouring. These RegExes and the implementation can be quite complex, but the concept is relatively simple.

That's it - easy to add, when you know how.