markdown-itでレンダリングした要素にディープセレクタでスタイルを適用してみる

2021.04.19

はじめに

案件で@nuxt.js/markdownit を使うことになったので、同僚のしょいとさんの記事Nuxt.jsで作ったアプリでMarkdownをレンダリングしてみる | Developers.IOを読んでお勉強してました。

ただ、私はレンダリングされたhtmlの部分にスコープ付きスタイル(scoped)を適用したくて、それどうやるんだろう?という疑問が湧いたので調査をしてみました。

結論から言うと、ディープセレクタを利用することで適用することができます。

ということで、この記事では適用してみた例をご紹介します。

やってみたこと

適用前の状態

まずは、何もスタイルを設定しない場合の状態を確認します。 例えばこんなコードを書いてみます。

<template>
  <div class="renderer" v-html="$md.render(markdown)"></div>
</template>

<script>

export default {
  data() {
    return {
      markdown: `
# h1 Heading
## h2 Heading
### h3 Heading
      `,
    };
  },
};
</script>

画像のように、デフォルトのスタイルが適用された状態になります。

適用後の状態

次に、ディープセレクタ( ::v-deepを使用 ※)を使ってh1タグを赤色にするスタイルを設定した場合の状態を確認します。 こんなコードにしてみます。

<template>
  <div class="renderer" v-html="$md.render(markdown)"></div>
</template>

<script>

export default {
  data() {
    return {
      markdown: `
# h1 Heading
## h2 Heading
### h3 Heading
      `,
    };
  },
};
</script>

<style lang="scss" scoped>
::v-deep h1 {
  color: red;
}
</style>

すると、画像のように、h1タグにスタイルが適用されることを確認できました。

画像のように、デフォルトのスタイルが適用された状態になります。

なお、以下のページに記載の通り、セレクタは環境に合わせて選択する必要があります。 Scoped CSS | Vue Loader

Some pre-processors, such as Sass, may not be able to parse >>> properly. In those cases you can use the /deep/ or ::v-deep combinator instead - both are aliases for >>> and work exactly the same.

ちなみに、この時の要素とスタイルがどうなっているかというと、こんな感じになっています。 data-v-xxx属性に対するスタイルが定義されることを確認できました。

<div id="__layout">
    <div>
        <div data-v-1906d359="" class="renderer">
            <h1>h1 Heading</h1>
            <h2>h2 Heading</h2>
            <h3>h3 Heading</h3>
        </div>
    </div>
</div>
[data-v-1906d359] h1 {
    color: red;
}

まとめ

ディープセレクタを使えば @nuxt.js/markdownit でレンダリングした部分にもスタイルが適用されることを確認できました。

私はそれに気づくのにちょっと時間がかかったので、同じ様に悩んでいる人の参考になれば幸いです。

参考