はじめに
急いでいる方は解決方法を考えるまで飛ばしてください。
この記事は、pre
タグの余分なインデントを削除する方法について、数種類の方法を紹介しています。
また、最初の方は問題発生までの手順や、余分なインデントの正体なども書いています。
作者自身が初心者のため、間違いがある可能性があります。
もしあったらすみません。
環境
- OS: Mac
- エディタ: VSCode
- インデント: スペース×2(
- インデント: スペース×2(
- HTMLの表示: Chrome
ついさっき知ったんですが、インデントにもタブとスペースの2種類あるんですね...
ずっとTabキーを押したらインデントできるくらいにしか思ってなかったので、まさかTabキーを押して入力されていたのがスペースだとは思いませんでした...
VSCodeのインデントの設定については、以下の記事をご覧ください。
問題
茶番です。
急いでいる方は余白の正体まで飛ばしてください。
さて、今日も今日とてHTMLを書いていきます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTMLファイル</title>
</head>
<body>
<main>
<article>
<h1>Hello World!</h1>
</article>
</main>
</body>
</html>
よく見る普通のHTMLですね。
中身のコンテンツは演出のためmain
とarticle
で囲まれています。
ということで、ここに文章を追記していきたいと思います。
<body>
<main>
<article>
<h1>Hello World!</h1>
<p>
これはpタグ<br>
普通の文章<br>
</p>
<a href="">これはaタグ</a>で<code>これはcodeタグ</code>
<blockquote>
これはblockquoteタグ<br>
引用に使われる
</blockquote>
<pre>
これはpreタグ
用途は正直よくわからん
スペースや改行がそのまま表示されるから、
こんな風にインデントすることができる
</pre>
</article>
</main>
</body>
見ての通りp
タグやa
タグ、pre
タグなどが追加されました。
至って普通のHTMLですね。
CSSで装飾するのもいいかもしれません。
pre
タグの背景色をskyblue
にしたらいい感じになりそうです。
<style>
pre {
background-color: skyblue;
}
</style>
...pre
タグに変な余白がついてしまいました。
見ての通り、pre
タグの内側の左と下に謎の余白があります。
padding
は設定していませんし、この余白は一体なんでしょうか。
余白の正体
もしかしたらpre
タグの中身に問題があるのかもしれません。
コピペして調べてみましょう。
これはpreタグ
用途は正直よくわからん
スペースや改行がそのまま表示されるから、
こんな風にインデントすることができる
コピペしてみたところ、なぜか余白が再現されました。
これはpre
タグのスタイルではなく、pre
タグの中身に原因があると見て間違いなさそうです。
これだと分かりづらいので、余白部分を特殊文字に置き換えてみます。
HTML特殊文字変換というサイトを見つけたので、これを使って変換したものがこちらです。
これはpreタグ
用途は正直よくわからん
スペースや改行がそのまま表示されるから、
こんな風にインデントすることができる
というのは半角スペース(
)を表しています。
ということはつまり、余白の正体は大量の半角スペースだったみたいです。
ではこの半角スペースは一体なんなのでしょうか。
...待てよ、そういえばこの形の余白、どこかで見たような...
</blockquote>
<pre>
これはpreタグ
用途は正直よくわからん
スペースや改行がそのまま表示されるから、
こんな風にインデントすることができる
</pre>
</article>
これはpreタグ
用途は正直よくわからん
スペースや改行がそのまま表示されるから、
こんな風にインデントすることができる
左余白の大きさが一致していますね。
大量の半角スペースの正体は、どうやらインデントだったみたいです。
解決方法を考える
さて、原因が分かったのはいいですが...
この余白は一体どうやって消したらいいのでしょう。
困った時はGoogle先生に聞いてみましょう。
Bing AIでもいいんだけど参考ソース書くのがめんどいから...
ということで、「preタグ インデント 削除」でググった結果、以下の方法が出てきました。
CSSで対処する
こちらの記事を参考にしています。
どうやら、white-space: pre-line;
というCSSを適用させると、余分な余白が消えるそうです。
white-space
プロパティは、要素内のホワイトスペース(改行文字や半角スペースなど)をどのように扱うか決めるCSSプロパティです。
このプロパティにpre-line
を設定すると、ソース内の改行はそのまま残されますが、ホワイトスペースは詰めて表示されます。
以下はMDNにあるwhite-space
の説明です。
このプロパティは 2 つのことを指定します。
- ホワイトスペースを折り畳むかどうか、およびその方法。
- 行を自動折り返しの場面で折り返すことができるかどうか。
pre-line
連続するホワイトスペースは詰められて 1 つになります。行の折り返しは、改行文字や<br>
要素のあるときか、行ボックスを埋めるのに必要なときに行われます。
white-space
プロパティについて詳しく知りたい方は、MDNをご覧ください。
ということで試してみます。
<style>
pre {
background-color: skyblue;
+ white-space: pre-line;
}
</style>
こちらのCSSを追加すると、HTMLの表示が以下のように変わります。
比較用:white-space
を指定する前
見ての通り、行の最初にあったインデントが全て削除されています。
問題点
上の画像だと、余白はしっかり消えているのですが、故意にインデントした部分も一緒に消えてしまいました。
これはpreタグ
用途は正直よくわからん
スペースや改行がそのまま表示されるから、
こんな風にインデントすることができる
故意にインデントすることなんてないという場合は、white-space: pre-line;
で大丈夫だと思います。
CSSと特殊文字を組み合わせる
さて、上で言った通り、white-space: pre-line;
を指定すると行頭のインデントが消え去ります。
では、消える対象として認識されない=ホワイトスペースではない空白文字はないのでしょうか。
あります。空白の特殊文字
です。
ということはつまり、インデントしたい箇所に
を入れればうまく表示されるのではないでしょうか。
<style>
pre {
background-color: skyblue;
+ white-space: pre-line;
}
</style>
</blockquote>
<pre>
これはpreタグ
用途は正直よくわからん
- スペースや改行がそのまま表示されるから、
- こんな風にインデントすることができる
+ スペースや改行がそのまま表示されるから、
+ こんな風にインデントすることができる
</pre>
</article>
これを表示してみます。
うまく表示されましたね。これがやりたかったのです。
問題点
...これでもいいのですが、少しHTMLの視認性が悪くなってしまいました。
気にならないと言われれば気にならないのですが、気になると言われれば気になります。
</blockquote>
<pre>
これはpreタグ
用途は正直よくわからん
スペースや改行がそのまま表示されるから、
こんな風にインデントすることができる
</pre>
</article>
また、他からコピペしてくる場合、いちいちインデントを
に置き換えなければいけません。
置き換える作業自体は自動化できると思いますが、その場合その自動化ツールを通すという手間が生まれます。
こういった問題点はありますが、これでも気にならないという方はこれで大丈夫だと思います。
以外のスペース
先ほども載せたこちらのサイトには、
について以下のような記述があります。
実は
の本来の役割は「半角スペースの代わり」ではありません。本来は「改行の禁止(=当該空白部分での自動的な改行を防ぐ)」という機能を果たすものだそう。英文などの場合、単語と単語の間は半角スペースで区切られますが、例えば会社名など複数単語でひとつながりのものを改行させずに表示したいときなどに使うのが、
なのです。
どうやら
は半角スペースの代わりではないそうです。
ということを考えると、上で挙げた使い方は少し邪道にも思えてきます。
では
以外に使える文字はあるのか?
上のサイトには以下のような特殊文字が紹介されていました。
&ensp;
半角スペースよりやや広いスペース
&emsp;
全角スペース
&thinsp;
半角よりさらに小さいスペース
時と場合によりますが、もしかしたらこちらを使った方がいいのかもしれません。
ちなみに、スペースの代わりにタブ文字(	
)を使うこともできます。
こちらはCSSのtab-size
プロパティでインデントのサイズを調整することができたりもします。
こちらも時と場合によりますが、ぜひ使ってみてください。
preタグのインデントをなくす
よく考えてみれば、余白があるから余白が表示されるのです。
つまり最初から余白がなければうまくいくのではないでしょうか。
ということで、pre
タグを以下のように編集してみます。
</blockquote>
<pre>これはpreタグ
用途は正直よくわからん
スペースや改行がそのまま表示されるから、
こんな風にインデントすることができる
</pre>
</article>
</main>
ポイントはこんな感じです。
-
pre
タグは左端につめる - 最初の行を
<pre>
の直後に持ってくる -
pre
タグ内でのインデントは、故意に字下げしたい箇所以外では入れない
ということで、これを表示してみます。
※画像はイメージです
うまく表示されました。これは嬉しいですね。
問題点
...うまくいったのはいいですが、正直このHTML読みづらくないですか?
pre
タグだけ左端にあるHTML、美しくなくないですか?
</blockquote>
<pre>これはpreタグ
用途は正直よくわからん
スペースや改行がそのまま表示されるから、
こんな風にインデントすることができる
</pre>
</article>
</main>
このHTMLでも気にならない / 問題ないという場合は、この方法で大丈夫だと思います。
JavaScriptで削除する
今まで紹介した方法には、どれも問題点やデメリットがありました。
ですが、このJavaScriptを使った方法ならば、今まで挙げたようなデメリットがありません。
- 特殊文字を使わなくてもインデントして表示できる
- ソース内の
pre
タグをインデントできる - 一度コードを書いてしまえば、あとは何も考えなくていい
それに加え、JavaScriptなので柔軟性が高いです。
挙動の仕様を自分で決めることができます。
ということで私が考えたのがこちらです。
document.querySelectorAll('pre').forEach(pre => {
const space = pre.textContent.match(/^[ |\t]*/gm)[0].length;
const result = pre.textContent.split('\n').map(str => {
return str.slice(space);
}).join('\n');
pre.textContent = result;
});
このコードを書いたscript
タグを</body>
の直前に配置すると、なんと余分な余白を消し去ってくれます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTMLファイル</title>
<style>
pre {
background-color: skyblue;
}
</style>
</head>
<body>
<main>
<article>
<h1>Hello World!</h1>
<p>
これはpタグ<br>
普通の文章<br>
</p>
<a href="">これはaタグ</a>で<code>これはcodeタグ</code>
<blockquote>
これはblockquoteタグ<br>
引用に使われる
</blockquote>
<pre>
これはpreタグ
用途は正直よくわからん
スペースや改行がそのまま表示されるから、
こんな風にインデントすることができる
</pre>
</article>
</main>
<!-- preタグのインデントを削除 -->
<script>
document.querySelectorAll('pre').forEach(pre => {
const space = pre.textContent.match(/^[ |\t]*/gm)[0].length;
const result = pre.textContent.split('\n').map(str => {
return str.slice(space);
}).join('\n');
pre.textContent = result;
});
</script>
</body>
</html>
プレビュー:
※画像はイメージです
ちなみにこのコードの仕様はこんな感じです。
- 最初の行よりインデントが少ない行はバグる(仕様)
- タブ文字(
	
\t
)にも対応しているはず - 仕組み上タブ文字とスペースが混ざったインデントは未対応
上のコードの問題点(仕様)
「最初の行よりインデントが少ない行はバグる」についてですが、例えばこんな感じのHTMLを書くとバグります。
<body>
<pre>
ここは1行目 <!-- この行が基準 -->
ここは2行目
ここは3行目
ここは4行目
ここは5行目
ここは6行目
</pre>
</body>
すると、こんなふうに表示されます。
(画像は面倒だったため、テキストでのお届けになります)
ここは1行目
行目
ここは3行目
ここは5行目
ここは6行目
見ての通り2行目が途中からしか表示されていません。
また、4行目に至っては何もありません。
これは仕様上の問題です。
1行目を基準としてそれ以降の行にインデントがあるかを判断しているため、1行目の最初の文字の位置より左側にあるものは全て消されます。
これに関しては割とどうしようもないです。すみません。
まあでもそんな場面滅多にないでしょ...(お祈り)
この方法の問題点
JavaScriptで余白を消す方法にどんなデメリットがあるかですが、正直に言うと私にはわかりません。
一応懸念している点を挙げておきます。
- エラーが出る可能性がある、予想外の挙動をする可能性がある
- JavaScriptなので表示が遅くなるかも?(未検証)
上のコードを使用する際や自分でコードを書く場合はご注意ください。
まとめ
この記事では以下の方法を紹介しました。
リンク | インデントの表示 | HTMLの綺麗さ |
---|---|---|
CSSで対処する | 不可 | 綺麗 |
特殊文字と組み合わせる | 特殊文字を使う | 微妙 |
preタグを左にする | HTMLのインデントを反映 | うーん |
JavaScriptで削除する | HTMLのインデントを反映 | 綺麗 |
時と場合に応じて使い分けてみてください。
余談ですが、Prism.jsのプラグインにNormalize Whitespaceというものがあります。
Prism.jsというのはHTML上のコードをハイライトするためのライブラリで、Normalize Whitespaceは余分な余白を削除するプラグインです。
もしpre
タグを使う理由がコードを載せるためな場合(過去の自分)、Prism.jsの使用を検討してみてはいかがでしょうか。
余分な余白を消してくれる上、副産物としてコードのハイライトもついてきます。
Prism.jsの導入については過去に記事にしているので、よければ見て見てください。