flutter_markdownでcode spans(コードスパン)を柔軟なスタイルにする方法
はじめに
今回もまたまたflutter_markdownについてのブログです。
今回はflutter_markdownでcode spans(コードスパン)の柔軟なデザインを実現するための方法について紹介します。
code span(コードスパン)とは
コードスパンとは下記のようにバッククウォートで囲んだ時のスタイルのことです。
テキスト `code spans` テキスト
スタイル適用時の課題
flutter_markdownでは通常、スタイルを指定する際に MarkdownStyleSheet を利用します。
コードスパンのスタイルは、その中の code に TextStyle を設定します。
MarkdownStyleSheet.fromTheme(Theme.of(context)).copyWith(
// ...
code: TextStyle(fontSize: 14, color: Colors.orange),
// ...
);
この設定を適用した状態で、以下のMarkdownを表示させた結果を見てみます。
Markdown例
## h2 `code span` h2
テキスト `code span` テキスト
表示結果

通常のテキストに code span を表示させる場合には問題ありませんが、見出し(例: h2)など、通常のテキスト以外でコードスパンを表示すると、TextStyle のフォントサイズが固定で 14 に設定されているため、不自然に見えてしまいます。
この問題を解決するためには、親要素(この例では h2)の TextStyle を考慮し、コードスパンのフォントサイズやスタイルが親要素に応じて柔軟に適用される方法が必要です。
以下では、その具体的な方法を共有します。
MarkdownBodyのinlineSyntaxesとbuildersでスタイルを上書きする
以前、以下のブログ記事でカスタムインラインタグの実装方法について紹介しました。
Flutter Markdownでカスタムのインラインタグを実装する方法
今回のテーマでは、この方法を活用して、コードスパンのスタイルをカスタマイズする方法を解説します。
flutter_markdown では、 MarkdownBody の inlineSyntaxes と builders を使うことで、インライン要素に対してスタイルを柔軟に適用できます。
syntax と builder を実装していきます。
Syntaxの実装
import 'package:markdown/markdown.dart' as md;
class CodeSpanSyntax extends md.InlineSyntax {
CodeSpanSyntax() : super(r'`([^`]+)`');
@override
bool onMatch(md.InlineParser parser, Match match) {
final content = match.group(1) ?? '';
final element = md.Element('code_span', []);
element.attributes['content'] = content;
parser.addNode(element);
return true;
}
}
実装のポイント
- コンストラクタの
superでcode spansを識別するための正規表現を定義する- `
- バッククォートを1つ指定します
- ([^]+)`
- バッククォート以外の文字列をキャプチャします。
- [^]`:バッククォート以外の1文字にマッチ。
- +:1文字以上の連続する部分にマッチ。
- バッククォート以外の文字列をキャプチャします。
- `
- 再びバッククォートで終わる部分を探します。
- `
Elementのtagはcode_spanに設定しておく
その他は下記のブログで説明しているためご覧ください。
flutter_markdownでカスタムのインラインタグを実装する方法
これで、InlineSyntax 側の実装は完了です。
次に、スタイルやビジュアル面でのカスタマイズについて説明します。
builderの実装
import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart' as fmd;
import 'package:markdown/markdown.dart' as md;
class CodeSpanBuilder extends fmd.MarkdownElementBuilder {
@override
bool isBlockElement() => false;
@override
Widget? visitElementAfterWithContext(
BuildContext context,
md.Element element,
TextStyle? preferredStyle,
TextStyle? parentStyle,
) {
return Text.rich(
TextSpan(
text: ' ${element.attributes['content']} ',
style: _textStyle(context, parentStyle),
),
);
}
TextStyle? _textStyle(BuildContext context, TextStyle? parentStyle) {
if (parentStyle != null) {
return parentStyle.copyWith(
color: Colors.orange,
fontSize: parentStyle.fontSize != null
? parentStyle.fontSize! * 3 / 4
decoration: parentStyle.decoration,
);
} else {
return TextStyle(
color: Colors.orange,
fontSize: 14
);
}
}
}
実装のポイント
parentStyle を使用してスタイルを適用するのがポイントです。
parentStyle は親のスタイルになります。つまり下記のMarkdownの場合h2の TestyStyle になります。今回の場合は親TextStyleのフォントサイズの 3/4 になるように設定しています。
## h2 `code span` h2
その他は下記のブログで説明しているためご覧ください。
flutter_markdownでカスタムのインラインタグを実装する方法
これで MarkdownElementBuilder 側の実装は完了です。
MarkdownBodyにCodeSpanSyntaxとCodeSpanBuilderを適用する
最後に、 MarkdownBody に対して CodeSpanSyntax と CodeSpanBuilder を設定します。以下のように記述することで、カスタムのコードスパンスタイルが適用されます。
return MarkdownBody(
inlineSyntaxes: [
CodeSpanSyntax(),
],
builders: {
'code_span': CodeSpanBuilder(),
},
);
これで実装は完了です!
以下の画像のように、code spans のフォントサイズが親の TextStyle によって柔軟に変化していること、また通常の code spans のスタイルが上書きされていることを確認できます。

ちなみに・・・
return MarkdownBody(
builders: {
'code': CodeSpanBuilder(),
},
);
実は InlineSyntax を実装しなくても、 builders に 'code' を指定するだけで code spans のスタイルを上書きすることが可能です。
この方法を採用すると、 code spans のスタイルだけでなく、 コードブロックのスタイル も同時に変更されてしまいます。そのため、 code spans のみをカスタマイズしたい場合には、このアプローチは適していません。
最後に
Markdownの記法でもあるcode spansのスタイルの上書きができることを確認しました。
inline要素で親のスタイルによって変化させたい時は便利だと思います。是非参考にしていただければと思います。