Effortless Markdown Styling with Tailwind, Pygments, and Key Plugins

2 weeks ago New!
5 min read

I’ve been running this blog for about five years, and during that time, it’s undergone several transformations. Initially, it was built with plain Markdown, HTML, and CSS. Over time, I experimented with various frameworks before finally settling on Tailwind CSS. The blog has been using Tailwind for a while now, and I’m happy with the results. In addition to Tailwind, I’ve incorporated other tools that enhance the blog’s functionality and aesthetics, such as Pygments for syntax highlighting and Medium Zoom for an interactive image zooming experience. Now that I've settled on a stack that I'm happy with, I thought it would be a good idea to document it. This post will cover the tools I use for my blog, including Tailwind, Pygments, Medium Zoom, and other tips & tricks.

Tailwind

Tailwind is a utility first CSS framework that is very popular. It is the best framework by far for me that uses plain HTML and CSS which I use for my website since I use Django and Wagtail. The framework provides also provides plugins for various things such as typography which we use in the blog for Markdown text.

The Tailwind setup I use is the following:

module.exports = {
  theme: {
    extend: {
      fontFamily: {
        sans: ['Noto Sans', 'Inter var'],
      },
    },
  },
  plugins: [
    require('@tailwindcss/forms'),
    require('@tailwindcss/typography'),
    require('@tailwindcss/line-clamp'),
    require('@tailwindcss/aspect-ratio'),
    require('daisyui'),
  ]
}

The most relevant plugins for Markdown are @tailwindcss/typography and daisyui The typography plugin is used for styling the Markdown text. The daisyui plugin provides a component library for Tailwind and custom styling for Tailwind. The typography plugin is documented here.

The usage of the typography plugin is as follows:

<article class="prose font-['Noto_Sans']">{{ page.body|markdown }}</article>

Note: The font-['Noto_Sans'] class is used to set the font for the Markdown text. The prose class is used to style the Markdown text. The syntax {{ page.body|markdown }} is used to render the Markdown text in the Django template.

The font comes from Google Fonts and is imported in the base.html file:

<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100..900;1,100..900" rel="stylesheet" />

With the above Tailwind/DaisyUI setup any text that has the prose class will be styled according to the Tailwind typography plugin which is great for Markdown text. It provides a nice and clean look for the blog posts and is minimal effort to integrate it.

Pygments

Pygments is a syntax highlighting tool that is used to highlight code snippets in the blog posts. It supports all languages and has several themes. To generate Pygments CSS you'll use the following command:

pygmentize -f html -a .codehilite > <my_directory>/pygments.css>

The generated CSS file can be included in the Django template to style the code snippets. The CSS file is included in the blog.html file:

<link rel="stylesheet" href="{% static 'css/pygments.css' %}" />

The code snippets are styled using the codehilite class:

<pre><code class="codehilite">print("Hello, World!")</code></pre>

However, for a large Markdown file, it is better to use the markdown library in Python to render markdown. The Python library is a Python implementation of John Grueber's markdown which converts markdown to html. The markdown library supports the codehilite extension which can be used to highlight code snippets. The markdown library can be used as follows:

markdown.markdown(
    markdown_text, extensions=["extra", "codehilite", "tables"]
)

The above will transform the markdown_text to html and highlight the code snippets using the codehilite extension. The tables extension is used to render tables in the markdown text. This is what the wagtail-markdown library does under the hood when you use the markdown filter in the Django template, and you can do the same in any of your projects.

Theming

Pygments also supports several themes. I prefer the github-dark theme to align my blog with GitHub's theming. You can generate a CSS file for a specific theme using the following command:

pygmentize -S github-dark -f html -a .codehilite > <my_directory>/pygments.css

As you can see all code snippets in this blog are styled using Pygments' with the GitHub theme.

Medium Zoom

Medium Zoom is a JavaScript library that is used to zoom images on the blog. It works by zooming the image when it is clicked. This allows us to have large images in blog posts and any time we click it, we will see all details. It really works great! Adding it to your blog is simple, you just need to include the library in the HTML file and then initialize it for the images you want to zoom. The following is an example of how to include the library and initialize it:

  <script src="https://cdnjs.cloudflare.com/ajax/libs/medium-zoom/1.0.6/medium-zoom.min.js"
          integrity="sha512-N9IJRoc3LaP3NDoiGkcPa4gG94kapGpaA5Zq9/Dr04uf5TbLFU5q0o8AbRhLKUUlp8QFS2u7S+Yti0U7QtuZvQ=="
          crossorigin="anonymous"
          referrerpolicy="no-referrer"></script>
  <script>
      const images = Array.from(document.querySelectorAll(".prose img"));
      images.forEach(img => {
          mediumZoom(img, {
              margin: 0,
              /* The space outside the zoomed image */
              scrollOffset: 40,
              /* The number of pixels to scroll to close the zoom */
              container: null,
              /* The viewport to render the zoom in */
              template: null /* The template element to display on zoom */
          });
      });

The prose class is used to select the images in the Markdown text. The prose class is used to style the Markdown text. The img tag is used to select the images in the Markdown text. The mediumZoom function is used to initialize the zoom for the images. If you do not use the prose class you need to select the images to zoom using a different way.

You can click on the image below from my Comprehensive Kubernetes Autoscaling Monitoring with Prometheus and Grafana to see the zoom in action:

Karpenter Overview

Conclusion

This post covered the tools I use for my blog, including Tailwind, Pygments, Medium Zoom, and other tips & tricks. This is the stack I use for my blog, and I'm quite happy with it. It is minimal compared to all the custom HTML and CSS I used to write, and it is easy to maintain and implement.


Similar Posts

Recipes when building a headless CMS with Wagtail's API

3 min read

Recently I built a headless CMS using Wagtail's API as a backend with NextJS/React/Redux as a frontend. Building the API I ran into some small issues with Image URL data, the API representation of snippets and creating a fully customized …


Best Practises for A Performant Django Admin

10 min read

The admin interface that comes with Django is one of the great things about Django. It comes with a ton of features out of the box and has many open source packages that extend the base functionality even more. Well …


Custom Django Error Pages

3 min read

Django comes with default views for 400, 403, 404 and 500 pages which is great. However, the default templates for these views are minimal - they just indicate what error it is. This blog post will walk through how to …