Enhancing Astro With a Markdown Component

There are two ways to enhance Markdown in an Astro project:

  1. Through MDX
  2. Through a Markdown Component

This article focuses on the Markdown Component.

Why Use a Markdown Component

I use a Markdown Component for two main reasons:

  1. It reduces the amount of markup I need to write.
  2. It converts typographic symbols like ' to opening or closing quotes (' or ').

So, I can skip several HTML tags — like <p>, <strong>, <em>, <ul>, <ol>, <li>, and <a>. I can also skip heading tags if I don’t need to add classes to them.

<div class="card">
  <!-- prettier-ignore -->
  <Markdown>
    ## Card Title
    This is a paragraph with **strong** and *italic* text.
    This is the second paragraph with a [link](https://link-somewhere.com)

    - List
    - Of
    - Items
  </Markdown>
</div>

Notice the prettier-ignore comment? It tells prettier not to format the contents within the <Markdown> block so Prettier won’t mess up my Markdown content.

The HTML output will be as follows:

<div class="card">
  <h2> Card Title </h2>
  <p>This is a paragraph with <strong>strong</strong> and <em>italic</em> text.</p>
  <p>This is the second paragraph with a <a href="https://link-somewhere.com">link</a></p>

  <ul>
    <li> List </li>
    <li> Of </li>
    <li> Items </li>
  </ul>
</div>

Installing the Markdown Component

Fun Fact: Astro came with a <Markdown> component in its early release, but this <Markdown> component was migrated to a separate plugin in Version 1, and completely removed in version 3.

I was upset about it. But I decided to build a Markdown component for myself since I liked using one. You can the documentation here.

Using the Markdown component is simple: Just import and use it in the way I showed you above.

---
import { Markdown } from '@splendidlabz/astro'
---

<Markdown>
  ...
</Markdown>

Respects Indentation Automatically

You can write your Markdown naturally, as if you’re writing content normally. This Markdown component detects the indentation and outputs the correct values (without wrapping them in <pre> and <code> tags).

<div>
  <div>
    <!-- prettier-ignore -->
    <Markdown>
      This is a paragraph

      This is a second paragraph
    </Markdown>
  </div>
</div>

Here’s the output:

<div>
  <div>
    <p>This is a paragraph</p>
    <p>This is a second paragraph</p>
  </div>
</div>

Inline Option

There’s an inline option that tells the <Markdown> component not to generate paragraph tags.

<h2 class="max-w-[12em]">
  <Markdown inline> Ain't this cool? </Markdown>
</h2>

Here’s the output:

<h2 class="max-w-[12em]">
  Ain't this cool?
</h2>

Gotchas and Caveats

Prettier messes up the <!-- prettier-ignore --> block if you have unicode characters like emojis and em dashes anywhere before the block.

Here’s the original code:

<!-- prettier-ignore -->
<Markdown>
  Markdown block that contains Unicode characters 🤗
</Markdown>

<!-- prettier-ignore -->
<Markdown>
  Second Markdown block.
</Markdown>

Here’s what it looks like after saving:

<!-- prettier-ignore -->
<Markdown>
  Markdown block that contains unicode characters 🤗
</Markdown>

<!-- prettier-ignore -->
<Markdown>
  Second Markdown block.
</Markdown>

Unfortunately, we can’t do much about emojis because the issue stems from Prettier’s formatter.

But, we can use en and em dashes by writing -- and ---, respectively.

Content Workaround

You can prevent Prettier from breaking all those <!-- prettier-ignore --> comments by not using them!

To do this, you just put your content inside a content property. No need to worry about whitespace as well — that’s taken care of for you.

<Markdown content=`
  This is a paragraph

  This is another paragraph
`/>

Personally, I think it doesn’t look at nice as slot version above…

But it lets you use markdown directly with any JS or json content you load!

---
const content = `
  This is a paragraph

  This is another paragraph
`
---

<Markdown {content} />

Taking it Further

I’ve been building with Astro for 3+ years, and I kept running into the same friction points on content-heavy sites: blog pages, tag pages, pagination, and folder structures that get messy over time.

So I built Practical Astro: Content Systems — 7 ready-to-use solutions for Astro content workflows (MDX is just one of them). You get both the code and the thinking behind it.

If you want a cleaner, calmer content workflow, check it out.

I also write about Astro Patterns and Using Tailwind + CSS together on my blog. Come by and say hi!


Enhancing Astro With a Markdown Component originally handwritten and published with love on CSS-Tricks. You should really get the newsletter as well.

This post first appeared on Read More