😽

GitHub Flavored MarkdownをTailwindCSSでスタイリング

2023/06/21に公開4

はじめに

TailwindCSSが有効な環境でマークダウンを読み込むとスタイリングが無効化されてしまいます。この記事では、マークダウンに対してスタイリングをあてる方法を紹介します。

以下に作業ソースをおいています。

https://github.com/hayato94087/nextjs-markdown-tailwindcss-styling-sample

使用技術

  • Next.js (App Router)
  • TailwindCSS
  • react-markdown
  • remark-gfm

Next.jsプロジェクトの新規作成

$ pnpm create next-app@latest nextjs-markdown-styling-sample --typescript --eslint --import-alias "@/*" --src-dir --use-pnpm --tailwind --app
$ cd nextjs-markdown-styling-sample

パッケージを追加

react-markdown は、マークダウンを レンダリングする React コンポーネント を提供するパッケージです。

https://github.com/remarkjs/react-markdown

$ pnpm add react-markdown

remark-gfm は、GitHub Flavored Markdown をサポートするためのライブラリです。react-markdownとあわせて使います。

https://github.com/remarkjs/remark-gfm

$ pnpm add remark-gfm

RSCを作成

src/app/page.tsx を上書きします。markdownStringでマークダウンの文字列を定義し、remarkPluginsremark-gfmを指定します。

src/app/page.tsx
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';

const markdownString = `
# GFM

Lorem ipsum dolor sit amet consectetur, adipisicing elit. Magni, nemo!

## Autolink literals

www.example.com, https://example.com, and contact@example.com.

## Footnote

A note[^1]

[^1]: Big note.

## Strikethrough

~one~ or ~~two~~ tildes.

## Table

| a | b  |  c |  d  |
| - | :- | -: | :-: |

## Tasklist

* [ ] to do
* [x] done
`;

const Home = () => {
  return (
    <ReactMarkdown remarkPlugins={[remarkGfm]}>{markdownString}</ReactMarkdown>
  );
};

export default Home;

今回は、remark-gfmの公式で出しているマークダウンのサンプルをそのまま使わせていただきました[1]

# GFM

Lorem ipsum dolor sit amet consectetur, adipisicing elit. Magni, nemo!

## Autolink literals

www.example.com, https://example.com, and contact@example.com.

## Footnote

A note[^1]

[^1]: Big note.

## Strikethrough

~one~ or ~~two~~ tildes.

## Table

| a | b  |  c |  d  |
| - | :- | -: | :-: |

## Tasklist

* [ ] to do
* [x] done

globals.cssを修正

globals.cssから無駄なスタイリングを削除するため、以下で上書きします。

src/app/globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;

ローカルサーバで確認

ローカルサーバを起動させ確認します。

$ pnpm dev

スタイリングは、TailwindCSSによって無効化されています。

いまからスタイリングをあてていきます。

変換後のHTMLを確認

入力されたマークダウンがどのようにHTMLに変換されるか確認します。

以下が、変換結果です。<h1>, <p>, などなどスタイリングするHTMLタグが分かります。

<h1>GFM</h1>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Magni, nemo!</p>
<h2>Autolink literals</h2>
<p>
  <a href="http://www.example.com">www.example.com</a>,
  <a href="https://example.com">https://example.com</a>, and
  <a href="mailto:contact@example.com">contact@example.com</a>.
</p>
<h2>Footnote</h2>
<p>
  A note<sup
    ><a
      href="#user-content-fn-1"
      id="user-content-fnref-1"
      data-footnote-ref="true"
      aria-describedby="footnote-label"
      >1</a
    ></sup
  >
</p>
<h2>Strikethrough</h2>
<p><del>one</del> or <del>two</del> tildes.</p>
<h2>Table</h2>
<table>
  <thead>
    <tr>
      <th>a</th>
      <th style="text-align: left">b</th>
      <th style="text-align: right">c</th>
      <th style="text-align: center">d</th>
    </tr>
  </thead>
</table>
<h2>Tasklist</h2>
<ul class="contains-task-list">
  <li class="task-list-item">
    <input type="checkbox" disabled="" />
    <!-- -->to do
  </li>
  <li class="task-list-item">
    <input type="checkbox" disabled="" checked="" />
    <!-- -->done
  </li>
</ul>
<section data-footnotes="true" class="footnotes">
  <h2 class="sr-only" id="footnote-label">Footnotes</h2>
  <ol>
    <li id="user-content-fn-1">
      <p>
        Big note.
        <a
          href="#user-content-fnref-1"
          data-footnote-backref="true"
          class="data-footnote-backref"
          aria-label="Back to content"
          ></a
        >
      </p>
    </li>
  </ol>
</section>

スタイリングを定義

HTMLタグにあわせてスタイリングをあてていきます。具体的には、globals.cssを修正することで、それぞれのHTMLタグをスタイリングします。

以下のリポジトリで、GitHub Flavored MarkdownをTailwindCSSでスタイリングするためのCSSが公開されているので参考にさせていただきます。

https://github.com/iandinwoodie/github-markdown-tailwindcss/tree/master

https://github.com/iandinwoodie/github-markdown-tailwindcss/blob/master/markdown.css

以下の内容でglobals.cssを上書きします。スタイリングを適応させる対象を、markdownクラスとしておくことで、他の箇所に影響を与えないようにします。

src/app/globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;

.markdown {
  @apply text-gray-900 leading-normal break-words;
}

.markdown > * + * {
  @apply mt-0 mb-4;
}

.markdown li + li {
  @apply mt-1;
}

.markdown li > p + p {
  @apply mt-6;
}

.markdown strong {
  @apply font-semibold;
}

.markdown a {
  @apply text-blue-600 font-semibold;
}

.markdown strong a {
  @apply font-bold;
}

.markdown h1 {
  @apply leading-tight border-b text-4xl font-semibold mb-4 mt-6 pb-2;
}

.markdown h2 {
  @apply leading-tight border-b text-2xl font-semibold mb-4 mt-6 pb-2;
}

.markdown h3 {
  @apply leading-snug text-lg font-semibold mb-4 mt-6;
}

.markdown h4 {
  @apply leading-none text-base font-semibold mb-4 mt-6;
}

.markdown h5 {
  @apply leading-tight text-sm font-semibold mb-4 mt-6;
}

.markdown h6 {
  @apply leading-tight text-sm font-semibold text-gray-600 mb-4 mt-6;
}

.markdown blockquote {
  @apply text-base border-l-4 border-gray-300 pl-4 pr-4 text-gray-600;
}

.markdown code {
  @apply font-mono text-sm inline bg-gray-200 rounded px-1 py-5;
}

.markdown pre {
  @apply bg-gray-100 rounded p-4;
}

.markdown pre code {
  @apply block bg-transparent p-0 overflow-visible rounded-none;
}

.markdown ul {
  @apply text-base pl-8 list-disc;
}

.markdown ol {
  @apply text-base pl-8 list-decimal;
}

.markdown kbd {
  @apply text-xs inline-block rounded border px-1 py-5 align-middle font-normal font-mono shadow;
}

.markdown table {
  @apply text-base border-gray-600;
}

.markdown th {
  @apply border py-1 px-3;
}

.markdown td {
  @apply border py-1 px-3;
}

/* Override pygments style background color. */
.markdown .highlight pre {
  @apply bg-gray-100 !important;
}

src/app/page.tsxを修正します。スタイリングをあてる対象のクラスをmarkdownとしておきます。

src/app/page.tsx
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';

const markdownString = `
# GFM

Lorem ipsum dolor sit amet consectetur, adipisicing elit. Magni, nemo!

## Autolink literals

www.example.com, https://example.com, and contact@example.com.

## Footnote

A note[^1]

[^1]: Big note.

## Strikethrough

~one~ or ~~two~~ tildes.

## Table

| a | b  |  c |  d  |
| - | :- | -: | :-: |

## Tasklist

* [ ] to do
* [x] done
`;

const Home = () => {
  return (
-    <ReactMarkdown remarkPlugins={[remarkGfm]}>{markdownString}</ReactMarkdown>
+    <ReactMarkdown remarkPlugins={[remarkGfm]} className='markdown'>{markdownString}</ReactMarkdown>
  );
};

export default Home;

ローカルサーバで確認

ローカルサーバを起動させ確認します。

$ pnpm dev

無事スタイリングが適応されました。

まとめ

TailwindCSSが有効な環境でマークダウンを読み込むとスタイリングが無効化されてしまいます。この記事では、マークダウンに対してTailwindCSSを利用しスタイリングをあてる方法を紹介しました。

参考

https://github.com/remarkjs/react-markdown
https://github.com/remarkjs/remark-gfm
https://zenn.dev/yoshiishunichi/articles/667120b3d0c9d2
https://github.com/iandinwoodie/github-markdown-tailwindcss/tree/master

脚注
  1. https://github.com/remarkjs/remark-gfm#use ↩︎

Discussion

鈴木拓海鈴木拓海

おかげさまで無事にマークダウンが反映されました。
ありがとうございました!😊