マークダウンをtailwind cssでスタイリングする


はじめに

使用技術

  • Next.js
  • Tailwind css
  • react-markdwon

上記の技術で、マークダウンをスタイリングします

Tailwind cssでデフォルトの要素のスタイリングを消していることが多いと思います。
そのままだとマークダウンが機能しないので、スタイリングします。
マークダウンだけに影響があるようにします。

(react-markdownで目次を作った記事があり、その続きから書いていきます。Tailwind関係ないですし、見なくても問題ありません。)

(Tailwindの設定が不要な人はここから)

ソースコード

Tailwindの設定

ライブラリのインストール

yarn add -D tailwindcss@latest postcss@latest autoprefixer@latest

設定ファイルの作成

npx tailwindcss init -p

以下が作られます

  • postcss.config.js
  • tailwind.config.js

(今回はしませんが普通は)postcss.config.jsで使わないcssを読み込まないようにします。

purge: [],
↓
purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],

その他Tailwind cssの設定

globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;

globals.cssの最初から書かれているものを全て消して↑を記述します。

Unknown at rule @tailwindと表示されると思いますが、vscodeの設定に
"css.validate": falseを設定すると消えます

_app.jsで以下があることを確認します。
なければ追記してください。

import '../styles/globals.css'

これでTailwind cssが使えるようになりました。

マークダウンをスタイリング

globals.cssを編集します

globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;

.markdown ol {
  @apply list-decimal pl-10;
}
.markdown ul {
  @apply list-disc pl-10;
}
.markdown h4 {
  @apply text-lg border-b border-black my-5;
}

.markdown h2 {
  @apply border-red-500 border-l-4 text-2xl;
}
.markdown ul {
  @apply list-disc pl-10;
}

例のスタイルの内容は適当ですが
自分で好きな要素に好きなスタイルをつけてみてください。

.markdown 要素の指定 {
  @apply つけたいスタイル;
}

要素の指定で全部( * )なども指定できます。

.markdownを利用する

マークダウンの親に「markdown」クラスをつけます。

<div className="markdown">
  <ReactMarkdown>
     {body}
  </ReactMarkdown>
</div>

これでマークダウンにスタイリングすることができました。

おまけ

前の記事の続きに、もう少しスタイリングを加えて目次っぽくします。

index.js
import ReactMarkdown from "react-markdown";

const body = `
## タイトル1
* おはよう。
* おはよう。
* おはよう。
* おはよう。
* おはよう。
* おはよう。
* おはよう。
* おはよう。
* おはよう。
## タイトル2
1. こんにちは。
2. こんにちは。
3. こんにちは。
1. こんにちは。
2. こんにちは。
3. こんにちは。
1. こんにちは。
2. こんにちは。
3. こんにちは。
## タイトル3
#### こんばんは
#### こんばんは 
#### こんばんは
#### こんばんは 
#### こんばんは 
#### こんばんは`;

export default function Home() {
  const H2 = ({ node, ...props }) => {
    return (
      <div>
        <h2 id={node.position?.start.line.toString()}>{props.children}</h2>
      </div>
    );
  };

  const ankerLink = ({ node, ...props }) => {
    return (
      <a
        className="list-item hover:bg-gray-200"
        href={"#" + node.position?.start.line.toString()}
      >
        {props.children}
      </a>
    );
  };

  return (
    <div className="m-auto w-full max-w-3xl">
      {/* 目次 */}
      <div className="p-3 m-10 bg-gray-100 border border-black border-dashed">
        目次
        <ol className="p-2 list-decimal list-inside">
          <ReactMarkdown
            allowedElements={["h2"]}
            components={{
              h2: ankerLink,
            }}
          >
            {body}
          </ReactMarkdown>
        </ol>
      </div>

      {/* 本文 */}
      <div className="markdown">
        <ReactMarkdown
          components={{
            h2: H2,
          }}
        >
          {body}
        </ReactMarkdown>
      </div>
    </div>
  );
}

少しだけ目次っぽくなりました

参考記事