Shiki

How to Style Code Blocks in Your Astro Blog Using Shiki and CSS

Tutorial on how to give yourself cool styles in your blog codeblocks.

me

Max Lewis

|

March 20th, 2025

|

5 min read

This blog assumes that you have a blog set up already. You should also understand Astro Content Collections and how to render markdowns in your markup.

What is Shiki?

Shiki is a syntax highlighter. It renders your markdown code blocks into something a lot more pretty.

Something like this.

``` js

console.log(“Hello World!”)

```

It can turn into this!

console.log("Hello World!")

What is a Shiki Transformer?

Shiki transformers allow you to manipulate the view of the code block Shiki renders to have nicely formatted highlights, added lines, deleted lines, lines with warnings, etc.

An example of a code block with a transformer applied looks like this:

console.log("Delete this line!")
console.log("Add this line!")

This block has a delete line and an add line transformer is applied.

This is done by adding a comment at the end of the line that Shiki can read and apply the HTML.

[!code --] comments add red highlighting and a minus.
[!code ++] comments add green highlighting and a plus.

More comments can be seen on Shiki Transformers that can be applied to our lines of code.

How to Add Shiki Transformers to Astro

Astro has built-in support for Shiki, which is super nice. All we have to do is add this to our Astro config.

In astro.config.js we add the following:

export default defineConfig({
  markdown: {
    syntaxHighlight: "shiki",
    shikiConfig: {
      theme: "any-theme-you-want",
      transformers: [
        transformerNotationDiff(),
        transformerNotationHighlight(),
        transformerNotationWordHighlight(),
        transformerNotationFocus(),
        transformerNotationErrorLevel(),
        transformerRenderWhitespace(),
        transformerMetaWordHighlight(),
      ],
    }
  }
})

You can add more or delete any transformer you may want/need, the documentation for these can be found here.

You will also need to npm install @shikijs/transformers.

How Can We See the Cool Highlights?

If you’re like me, you might add these transformers to your code and wonder why none of the cool effects are appearing. This is because we need to style these HTML elements ourselves.

Let’s Examine a Shiki Code Block from the Markdown to HTML

The following code block:

console.log("Hello World!")
console.log("This is so cool!")
console.log("Is this working?")
console.log("I think it is!")
console.log("This is an error")

Gets rendered into the following HTML:

<pre class="astro-code vitesse-dark has-diff has-highlighted relative" style="background-color:#121212;color:#dbd7caee; overflow-x: auto;" tabindex="0" data-language="javascript">
  <code>
  <span class="line"><span style="color:#BD976A">console</span><span style="color:#666666">.</span><span style="color:#80A665">log</span><span style="color:#666666">(</span><span style="color:#C98A7D77">"</span><span style="color:#C98A7D">Hello</span><span class="space"> </span><span style="color:#C98A7D">World!</span><span style="color:#C98A7D77">"</span><span style="color:#666666">)</span></span>
  <span class="line diff add"><span style="color:#BD976A">console</span><span style="color:#666666">.</span><span style="color:#80A665">log</span><span style="color:#666666">(</span><span style="color:#C98A7D77">"</span><span style="color:#C98A7D">This</span><span class="space"> </span><span style="color:#C98A7D">is</span><span class="space"> </span><span style="color:#C98A7D">so</span><span class="space"> </span><span style="color:#C98A7D">cool!</span><span style="color:#C98A7D77">"</span><span style="color:#666666">)</span></span>
<span class="line diff remove"><span style="color:#BD976A">console</span><span style="color:#666666">.</span><span style="color:#80A665">log</span><span style="color:#666666">(</span><span style="color:#C98A7D77">"</span><span style="color:#C98A7D">Is</span><span class="space"> </span><span style="color:#C98A7D">this</span><span class="space"> </span><span style="color:#C98A7D">working?</span><span style="color:#C98A7D77">"</span><span style="color:#666666">)</span></span>
<span class="line highlighted warning"><span style="color:#BD976A">console</span><span style="color:#666666">.</span><span style="color:#80A665">log</span><span style="color:#666666">(</span><span style="color:#C98A7D77">"</span><span style="color:#C98A7D">I</span><span class="space"> </span><span style="color:#C98A7D">think</span><span class="space"> </span><span style="color:#C98A7D">it</span><span class="space"> </span><span style="color:#C98A7D">is!</span><span style="color:#C98A7D77">"</span><span style="color:#666666">)</span></span>
<span class="line highlighted error"><span style="color:#BD976A">console</span><span style="color:#666666">.</span><span style="color:#80A665">log</span><span style="color:#666666">(</span><span style="color:#C98A7D77">"</span><span style="color:#C98A7D">This</span><span class="space"> </span><span style="color:#C98A7D">ia</span><span class="space"> </span><span style="color:#C98A7D">an</span><span class="space"> </span><span style="color:#C98A7D">error</span><span style="color:#C98A7D77">"</span><span style="color:#666666">)</span></span>
  </code>
</pre>

As you can see, Shiki adds nice class names to our lines of code. This enables us to style each line to our desired look. Furthermore, we can also style the code block itself.

Styling the Code Block

We can style the code block by adding some rules to our CSS. Remember we must import the CSS file into our Astro layout or components!

@layer components {
  pre {
    @apply relative max-h-[600px] min-w-[56px] overflow-auto rounded-xl border border-slate-400 py-4 text-sm leading-loose;
  }
  code {
      @apply w-full grid;
    }
}

Next, we can add styles for the highlights.

> code {
      @apply whitespace-pre-wrap mt-6 mb-6;
      counter-reset: line;

      > ::before { 
        counter-increment: line;
        content: counter(line);
        @apply mr-4 inline-block w-4 text-right;
      }

      .add {
        @apply bg-[#16322c];
      }

      .add::before {
        @apply text-emerald-400;
        content: "+";
      }

      .remove {
        @apply bg-[#311c22];
      }

      .remove::before {
        @apply text-rose-400;
        content: "-";
      }

      .line {
        @apply w-full p-1;
      }

      .highlighted {
        @apply bg-[#24272c];
      }

      .error {
        @apply bg-[#3c1e26];
      }

      .warning {
        @apply bg-[#3a3118];
      }

      .highlighted-word {
        @apply rounded bg-[#24272c] p-[2px];
      }
    } 

Now we have green backgrounds on lines for additions, red backgrounds for deletions, warning lines, focused lines, etc. You can add, remove, or change these styles based on what you want your code blocks and transformers to look like.

Now your code blocks should look like mine!