Marp のマイナー機能いろいろ
ここでは、 "Marp の作者自ら" 、Marp の『あんまり使われてなさそうなマイナー機能』や『Tips・テクニック』を随時紹介します。
Marp のメジャーな機能はいろいろな方が紹介してくださっているので、ここでは割愛。
# <!--fit--> (Fitting header)
<h1>〜<h6> に相当する各見出しの中に <!-- fit --> コメントが含まれていると、その見出しは画面全体に拡大されます。
# 普通の見出し
# <!--fit--> 画面全体に拡大

Deckset の # [fit] と同等ですが、HTMLコメントを使用している点が異なります。
ドキュメント
暫定ドキュメント もあります。
Marpit フレームワークを直接使用している開発者向けの注意
Fitting header は Marp Core の機能なので、Marpit フレームワーク を直接使用している場合は使えません。
Marpit フレームワークは、「ブラウザのコンテキストに依存せずに、再現性のある表示を実現する」ことを目的としたフレームワークですので、ブラウザ側の JavaScript に依存する拡大縮小処理が必要な機能は、 Marp Core に実装されています。
相当昔からある機能ですが、私の周知が足りず、わりと埃をかぶっていた機能です。。。
<!--fit--> で高橋メソッド
見出しでページを区切る headingDivider ディレクティブ を組み合わせると、 高橋メソッド のスライドも簡単に書けます。
---
# 中央寄せしてくれるテーマを使う
theme: uncover
headingDivider: 1
---
# <!--fit--> 高橋<br />メソッド
# <!--fit--> 特徴
# <!--fit--> 巨大な<br />文字
# <!--fit--> 簡潔な<br />言葉

<br> は、Marp ツールの HTML 設定を許可しなくても使えるタグなので、気兼ねなく使って大丈夫です。
アニメーション
一般的なシーンでは、プレゼンテーションにおけるアニメーションは悪手になることが多いと考えているので、Marp では積極的にサポートされていません。
ただし、アニメーションの使用が充分に効果的で、いざ必要となった場合は、CSS でアニメーションを定義できます。
animate.css を使用する
スライドの各要素に手っ取り早くアニメーションを適用するなら、ライブラリの力を借りると良いでしょう。
---
theme: uncover
# インラインスタイルで animate.css を読み込む
style: '@import url(https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css)'
---
<div class="animate__animated animate__fadeInDown animate__slow">
# アニメーション
</div>
<div class="animate__animated animate__fadeInDown animate__delay-2s">
animate.css を使うとカンタン
</div>

アニメーションは、 "HTML 形式に出力した際に、ページを切り替えて表示したタイミングで再生" されます。
ライブラリの使用方法や、他のアニメーションのプリセットなどは、 animate.css のドキュメント を参照してください。
@keyframes を定義して使用する
自分で CSS を書く場合、 HTML タグを許可しなくても使えます。
---
theme: uncover
---
# アニメーション
自分で CSS 書いちゃうもんね
<style scoped>
@keyframes slide-down {
from {
opacity: 0;
transform: translateY(-100px);
}
}
h1 {
animation: slide-down 1s ease-in-out 0s 1 both;
}
p {
animation: slide-down 1s ease-in-out 1s 1 both;
}
</style>
---
...
トランジション(ページ切り替え効果)
Marp CLI でデフォルトで使用される HTML テンプレートでは transition ディレクティブが定義されます。これにより、エクスポートした HTML でトランジション(ページ切り替え効果)を使用することができます。
Marp の VS Code 拡張機能も、エクスポートに Marp CLI を使いますので、同じようにトランジションを使用できます。
Marpit フレームワーク、Marp Coreを直接使用している開発者向けの注意
トランジションは Marp CLI で使われる HTML 出力で定義された機能なので、Marpit や Marp Core を直接使用している場合は使用できません。これらのライブラリにおいては、『ページ切り替えなどのUIに関わる機能』はスコープ外です。
使い方
transition ディレクティブを定義します。以下の Markdown は、全ページの切り替えでフェード効果を付与します。
---
transition: fade
---
# First page
---
# Second page

他のディレクティブ (paginate, header など) と同じように、単一ページの画面遷移のみを設定する場合は、アンダースコア付きの _transition ディレクティブを使用できます。
---
transition: fade
---
次スライドへの遷移時はフェード
---
<!-- transition: cover -->
次スライドへの遷移時はカバー
---
<!-- _transition: none -->
次スライドへの遷移時は効果なし
---
次スライドへの遷移時はカバーに戻る
---
...
トランジションの種類
Marp CLI に組み込まれている、合計 33種類 のトランジションを使用できます。 ドキュメント を参照してください。
例
![]() |
![]() |
![]() |
![]() |
|---|---|---|---|
| cube | reveal | swoosh | wipe |
これらはあくまで一部です。
遷移時間
Marp CLI 組み込みのトランジションの持続時間は、いずれも 0.5 秒 です。
変更する場合は、 transition ディレクティブの定義で、スペースの後に持続時間を記入します。(例: 0.5s 2s 500ms など)
<!-- transition: fade 1s -->
カスタムトランジション
満足のいくトランジションが無い場合は、自分で好きな動きのトランジションを作ることができます。Markdown のインラインスタイルや、カスタムテーマで定義することができます。
アニメーションを定義するときと同じように @keyframes を使用し、 Marp で決められたルールに沿った名前のキーフレーム[1]を定義してください。
---
transition: triangle
---
<style>
@keyframes marp-incoming-transition-triangle {
from { clip-path: polygon(0% 0%, 0% 0%, 0% 0%); }
to { clip-path: polygon(0% 0%, 200% 0%, 0% 200%); }
}
@keyframes marp-incoming-transition-backward-triangle {
from { clip-path: polygon(100% 100%, 100% 100%, 100% 100%); }
to { clip-path: polygon(-100% 100%, 100% -100%, 100% 100%); }
}
</style>
# カスタムトランジション
---
<!-- _class: invert -->
# カスタムトランジション

以下のブログ記事で、ステップ・バイ・ステップでその方法を解説しています。
ドキュメントはこちら。
このスクラップで詳しく説明すると長大になりそうなので、いずれ日本語訳するかも。
-
正規表現なら
/^marp(-incoming|-outgoing)?-transition(-backward)?-(.+)$/↩︎
モーフィング
トランジション中に、PowerPoint の変形アニメーション (Morph) や、Keynote の Magic Move のような 『スライド間をまたがる動き』(モーフィング) をつけることができます。

①の画像がモーフィングしている様子
View Transition API で定義されている CSS プロパティ view-transition-name を画像などの要素に付けます。
---
theme: gaia
transition: fade
---
<style>
/* ⬇️ ①の画像を "one" という名前でモーフィング可能に設定 ⬇️ */
img[alt="1"] {
view-transition-name: one;
contain: layout;
}
/* ①②③の画像の共通設定 */
img:is([alt="1"], [alt="2"], [alt="3"]) {
height: 64px;
position: relative;
top: -0.1em;
vertical-align: middle;
width: 64px;
}
</style>
# Today's topics
-  Introduction
-  Features
-  Conclusion
---
<!-- _class: lead -->

# Introduction
---
#  Introduction
Marp is an open-sourced Markdown presentation ecosystem.
It provides a writing experience of presentation slides by Markdown.
トランジション効果のついたページ遷移の前後で、同じ view-transition-name がついた要素 (今回の場合は "①" の画像) は、自動的にモーフィングアニメーションになります。
View Transition API について説明している拙作の記事はこちら。
カスタムテーマのサイズプリセット
Marp Core のテーマシステム (Marpit フレームワークから拡張) は、カスタムテーマ上で サイズプリセット を定義することができます。
/**
* @theme custom-theme
* @size 16:9 1280px 720px
* @size 4:3 960px 720px
* @size 16:10 1280px 800px
* @size uwide 1680px 720px
*/
section {
/* デフォルトのサイズは section 要素で設定 */
width: 1280px
height: 720px;
}
CSS のメタデータコメントとして、 @size [名前] [横幅] [縦幅] を定義してください。定義したサイズは、 Markdown 側で size グローバルディレクティブで設定できます。
---
theme: custom-theme
size: uwide
---
# ウルトラワイドモニター用の比率
Marpit フレームワークを直接使用している開発者向けの注意(+小話)
サイズプリセットや、 size グローバルディレクティブは Marp Core の機能なので、Marpit フレームワーク を直接使用している場合は使えません。
Marpit フレームワークのテーマシステムは、テーマ定義の複雑化を避けるため、 "1テーマ1サイズ" を基本として設計されました。
当初、Marp Core でもこのルールを維持するつもりでしたが、主に 旧 Marp ユーザーからの根強い機能要望に折れ、サイズプリセット機能と共に size ディレクティブを復活させたという経緯があります。
サイズプリセット別のデザイン調整
サイズプリセットが選択されると、スライドを示す各 section 要素に data-size 属性 が付与されます。
特定のサイズに合わせたデザインにするために CSS を微調整する際は、 属性セレクター section[data-size="xxx"] を使用します。
/**
* @theme custom-theme
* @size 4:3 960px 720px
*/
section {
width: 1280px;
height: 720px;
/* 16:9 の余白 */
padding: 36px 64px;
}
section[data-size="4:3"] {
/* 4:3 の時は、周囲の余白も 4:3 に合わせる */
padding: 36px 48px;
}
h1 {
font-size: 40px;
}
section[data-size="4:3"] h1 {
/* 4:3 の時は、h1 見出しも少し小さめに */
font-size: 30px;
}
CSS コンテナークエリー (@container)
最近のバージョンの Marp であれば、各スライドの section 要素は CSS コンテナーになっているため、 @container で特定の横幅・縦幅を条件にスタイルをあてることもできます。
h1 {
font-size: 40px
}
/* 4:3 で設定された横幅以下の時だけ適用 */
@container (width <= 960px) {
h1 {
font-size: 30px
}
}
コンテナークエリーの長さ単位
スライド要素 section がコンテナーなので、子孫要素に対しては、以下の長さの単位を使用することもできます。
-
1cqw: スライド幅(パディングを除く)の 1% -
1cqh: スライド高さ(パディングを除く)の 1% -
1cqmin: cqw または cqh のどちらか小さい方 -
1cqmax: cqw または cqh のどちらか大きい方
h1 {
/* スライド幅(パディングを除く)の 4% に設定 */
font-size: 4cqw;
}
これらの単位は @container の中でなくても使用できます。
透かし(ウォーターマーク)
section::before に対して content で要素を生成することで、透かし(ウォーターマーク)を実現することができます。
テキスト透かし
<style>
section::before {
content: '社外秘';
position: absolute;
left: 50%;
top: 50%;
font-size: 40cqmin;
font-weight: bold;
color: red;
white-space: nowrap;
transform: translate(-50%, -50%) rotate(-45deg);
opacity: 0.25;
}
</style>
# 人事について


画像透かし
section::before {
content: url('https://marp.app/assets/marp.svg');
position: absolute;
left: 50px;
bottom: 30px;
width: 200px;
opacity: 0.5;
}

section::before の利点は、分割背景画像 ![bg right]() にも干渉できることです。
分割背景は隔離された専用の領域が作られるため、通常は干渉できませんが、section::before と section::after (ページ番号) で生成された要素は唯一干渉できます。
Marp で特定のページのみスタイルを変える
これはマイナーというよりメジャーな要望ですので、ドキュメントにも載っていますが、落とし穴がある方法を使っている例もちらほら見受けられるので、ちゃんと説明しておきます。
✅ 【推奨】特定ページで特定のクラスを適用するように設定する
class ディレクティブの先頭にアンダースコア _ をつけて、_class で定義すれば、そのスライドのみのクラスを定義できます。 (Scoped local directive、別名 Spot directive)
- 利点: 環境によって使えなくなるケースが存在せず、安心して使える
- 欠点: Markdown 側にも定義が必要
---
theme: example
---
<!-- _class: first-page -->
# 1ページ目
---
# 2ページ目
/* @theme example */
section {
background: red;
}
section.first-page {
background: blue;
}
⚠️ 【要注意】特定のページを id 属性セレクタで指定する
Marp の公式ツールなどでは id 属性にページの通し番号が採番されていることが多いので、これを利用した方法です。
- 利点: Markdown 側に定義する必要がない
-
欠点: Marp/Marpit の
anchorコンストラクターオプションがカスタマイズされていると 動作しない場合がある
---
theme: example
---
# 1ページ目
---
# 2ページ目
/* @theme example */
section {
background: red;
}
/* ⚠️ 動作しないケースがあるため要注意 */
section[id="1"] {
background: blue;
}
❌ 【NG】特定のページを nth-of-type セレクタで指定する
スライドは必ずしも HTML 上で順番に並んでいるとは限らないので、 nth-of-type セレクタは動作しないケースがほとんど でです。
/* @theme example */
section {
background: red;
}
/* ❌ 動作しないケースがほとんどなのでNG */
section:nth-of-type(1) {
background: blue;
}
nth-of-type セレクタは、以下のように、 HTML 上でスライド section が順番に並んでいる時だけ動作します。
<!-- nth-of-type が意図通り動作する例 (簡易版) -->
<div>
<section><h1>1ページ目</h1></section> <!--`nth-of-type(1)` にマッチ -->
<section><h1>2ページ目</h1></section> <!--`nth-of-type(2)` にマッチ -->
</div>
実際にこうなってることもあるでしょうが、通常は Web やアプリ側で独自に機能がついてたりして、こんな単純な構造ではない事が多いです。そのため、 nth-of-type セレクタが意図した通りに動作しないことのほうがほとんどでしょう。
例えば、以下のように各スライドが <div> で囲まれている場合などが考えられます。これは常に nth-of-type(1) (first-of-type) にマッチするので、意図した通りにレンダリングされません。
<!-- nth-of-type が意図通り動作しない例 (簡易版) -->
<div>
<div><!-- section はここから数えて1要素目なので `nth-of-type(1)` にマッチ -->
<section><h1>1ページ目</h1></section>
</div>
<div><!-- section はここから数えて1要素目なので `nth-of-type(1)` にマッチ -->
<section><h1>2ページ目</h1></section>
</div>
</div>
日本語の自動改行処理を改善する
Marp の話というより最近の CSS・Web のお話ですが、日本語の自動改行処理を改善するスタイルを含めることで、Marp でも読みやすさを改善できます。
以下のサンプルでは Markdown 中にスタイルを含めていますが、テーマにスタイルを含めることで、より使いやすくなることでしょう。
文節ごとに自動改行 (word-break: auto-phrase)
word-break: auto-phrase を設定することで、単語の途中で自動的に改行されることを防ぐことができます。
---
# 👇 重要!
lang: ja
style: |
/* 見出し、段落に適用 */
h1, h2, h3, h4, h5, h6, p {
word-break: auto-phrase; /* 文節ごとに自動改行 */
}
---
# 長い文章が読みやすくなる!日本語を適切な位置で改行しよう
| 設定なし | 設定あり |
|---|---|
![]() |
![]() |
設定なしの場合、"改行" という単語が分断されてしまいますが、word-break: auto-phrase を使用すると回避できます。
日本語のスライドであると明示しなければ適切に動作しないため、スライドの lang 属性を設定するための グローバルディレクティブ lang を ja に設定 することが重要です。
💡 デフォルトの lang 属性を ja に設定するには? (Marpit/Marp Coreを直接使用する開発者向け)
Marpit クラス (Marp Core の場合は Marp クラス) のインスタンスを新規作成する際、コンストラクターオプションとして lang が使用できます。
const marpit = new Marpit({ lang: 'ja' })
const marp = new Marp({ lang: 'ja' })
ここで定義した言語は、Markdown 側で lang グローバルディレクティブを設定しない場合のデフォルトとして使用されます。Markdown 側で設定した場合は、その言語設定が優先されます。
技術的には BudouX が使用されています。BudouX を JavaScript ライブラリとして使用する記事例が多いですが、現在の Chrome は BudouX がブラウザに内蔵されているため、その必要はなく、手軽に使用できます。
改行位置の最適化 (text-wrap)
word-break: auto-phrase と text-wrap プロパティによる改行位置の最適化を組み合わせると、より読みやすさを改善できることでしょう。
-
text-wrap: balance: 各行がなるべく同じ文字数になるように自動改行する -
text-wrap: pretty: 最後の行が極端に短くならないように自動改行する
---
lang: ja
style: |
h1, h2, h3, h4, h5, h6, p {
word-break: auto-phrase;
text-wrap: balance; /* または pretty */
}
---
# 長い文章が読みやすくなる!日本語を適切な位置で改行しよう
word-break: auto-phrase のみ |
text-wrap: balance を併用 |
text-wrap: pretty を併用 |
|---|---|---|
![]() |
![]() |
![]() |
個人的には、以下のように 『見出しは text-wrap: balance』『段落(本文)は text-wrap: pretty』 が妥当かなと思います。
h1, h2, h3, h4, h5, h6, p {
word-break: auto-phrase;
}
h1, h2, h3, h4, h5, h6 {
text-wrap: balance;
}
p {
text-wrap: pretty;
}







