そんな気配はあったけど、何でこんな仕様になってるのかと
- Blinkって書いてもピンとこない人もいると思うんで、Chromeとまとめています。
brって知ってます?改行なんですよ(すっとぼけ
こういうやつです。
_skipCopy_
<p>
brって知ってます?改行なんですよ(すっとぼけ
<br>
こういうやつです。
</p>
ブラウザのdevツールのインスペクターを見るとこんな感じに入ると思います。<br>ってものは制御するためのもので、Chromeでは改行のみの機能があって、単に文章を折り返すだけなんですよ。
江戸川乱歩 黒蜥蜴を題材に
_skipCopy_
この国でも一夜に数千羽の七面鳥がしめられるという、あるクリスマス・イヴの出来事だ。
帝都最大の殷賑地帯、ネオン・ライトの闇夜の虹が、幾万の通行者を五色にそめるG街、その表通りを一歩裏へ入ると、そこにこの都の暗黒街が横たわっている。
G街の方は、午後十一時ともなれば、夜の人種にとってはまことにあっけなく、しかし帝都の代表街にふさわしい行儀よさで、ほとんど人通りがとだえてしまうのだが、それと引き違いに、背中合わせの暗黒街がにぎわい始め、午前二時三時頃までも、男女のあくなき享楽児どもが、窓をとざした建物の薄くらがりの中に、ウヨウヨとうごめきつづける。
スクロールバーが表示されない場合はカーソルを当てて、Shift + マウスホイールでスクロールできます
上記のような文章があって、Chromeでは以下赤枠のように折り返しはしているが、改行してもそこに高さは「ない」となります。これはChromeだけでFirefoxでは改行に高さを持たせられます。Chromeでは設定をしても無視されるわけです。
ここではChromeと同等にするために敢えて
<br>で改行をし、その<br>にはスタイルしていません。つまりChromeと同等のただの折り返しになっています。<br>にmarginを設定してしまうと、Firefoxでスタイルが反映されるので、Firefox利用者の方にもわかってもらえるように<br>にはスタイルをしないようにしています。
この国でも一夜に数千羽の七面鳥がしめられるという、あるクリスマス・イヴの出来事だ。
帝都最大の殷賑地帯、ネオン・ライトの闇夜の虹が、幾万の通行者を五色にそめるG街、その表通りを一歩裏へ入ると、そこにこの都の暗黒街が横たわっている。
G街の方は、午後十一時ともなれば、夜の人種にとってはまことにあっけなく、しかし帝都の代表街にふさわしい行儀よさで、ほとんど人通りがとだえてしまうのだが、それと引き違いに、背中合わせの暗黒街がにぎわい始め、午前二時三時頃までも、男女のあくなき享楽児どもが、窓をとざした建物の薄くらがりの中に、ウヨウヨとうごめきつづける。
これはこう書いています。
<!-- skipCopy -->
<p class="border-2 border-solid border-rose-500 p-4 my-[1rem]">
この国でも一夜に数千羽の七面鳥がしめられるという、あるクリスマス・イヴの出来事だ。<br>
帝都最大の殷賑地帯、ネオン・ライトの闇夜の虹が、幾万の通行者を五色にそめるG街、その表通りを一歩裏へ入ると、そこにこの都の暗黒街が横たわっている。</br>
G街の方は、午後十一時ともなれば、夜の人種にとってはまことにあっけなく、しかし帝都の代表街にふさわしい行儀よさで、ほとんど人通りがとだえてしまうのだが、それと引き違いに、背中合わせの暗黒街がにぎわい始め、午前二時三時頃までも、男女のあくなき享楽児どもが、窓をとざした建物の薄くらがりの中に、ウヨウヨとうごめきつづける。
</p>
しかし見た目的には、
この国でも一夜に数千羽の七面鳥がしめられるという、あるクリスマス・イヴの出来事だ。
G街の方は、午後十一時ともなれば、夜の人種にとってはまことにあっけなく、しかし帝都の代表街にふさわしい行儀よさで、ほとんど人通りがとだえてしまうのだが、それと引き違いに、背中合わせの暗黒街がにぎわい始め、午前二時三時頃までも、男女のあくなき享楽児どもが、窓をとざした建物の薄くらがりの中に、ウヨウヨとうごめきつづける。
こう書きたいことってありますよね?行間やmarginは当サイトのデフォルトのスタイルなのでアレですが、もっと見栄え良くもできるんでしょう。つまり改行間もスペースを開け、段落間もスペースを開けると言う事を言いたいわけです。
青枠のは、
_skipCopy_
<div class="border-2 border-solid border-sky-500 p-4 my-[1rem]">
この国でも一夜に数千羽の七面鳥がしめられるという、あるクリスマス・イヴの出来事だ。
帝都最大の殷賑地帯、ネオン・ライトの闇夜の虹が、幾万の通行者を五色にそめるG街、その表通りを一歩裏へ入ると、そこにこの都の暗黒街が横たわっている。
G街の方は、午後十一時ともなれば、夜の人種にとってはまことにあっけなく、しかし帝都の代表街にふさわしい行儀よさで、ほとんど人通りがとだえてしまうのだが、それと引き違いに、背中合わせの暗黒街がにぎわい始め、午前二時三時頃までも、男女のあくなき享楽児どもが、窓をとざした建物の薄くらがりの中に、ウヨウヨとうごめきつづける。
</div>
こうです。<div>タグは青線を付けるため、同様に赤枠のは<p>に色だけ変えて同じようにしています。<div>の中の文章はMarkdownとして解釈され、後は何もしなくてもMarkdown → htmlと変換され、テキストは段落になり<p>で囲まれます。改行される部分には<br>が自動挿入されます。
状況説明
どういう状況かと言うと、Chrome系は<br>が ただの折り返し でスタイルできない仕様になっているのです。
私はChromiumの誠実なフォーク((誠実なフォーク:無駄なものを取り除きオリジナルに忠実にフォークすると言うことで、Chrome等のようにテレメトリーなどの余計なデータの通信を行わずプライバシーに配慮しているという事です))(分岐・派生)の1つであるHelium最新版を使用しています((余計なことがされていないと言う意味です))。最新版で実際に試してから質問しているので、過去にはできたことでも 今はできない と言うのが事実なのです。
しかし、仕様として色々と世界中のwebを策定してる人らが集まって<br>は、
- 「折り返しだけで良いんじゃね?」
- 「スタイルなんかしなくても、divにクラスつけとけばいいやん」
- 「divでなくても要素にclassつければそれで何とかなるよな、
<br>は折り返しだけで」
と決めたわけです。
いやちょっと待てと、何のための<br>やねんと。それなら全部短い<p>で書いてしまえばいいやんと思うわけですが、実際そうさせようとしているフシがあり、(webのルールを作ってる)ヤツらの言語は英語だから(単語の前後にはスペースがあるんで)気に留めない所なのかも知れません。
つまり、
- 要素同士が近い → 同じグループに見える
- 離れている → 別のまとまりに見える
こういう効果が行間と言う間では作れるのです。むしろFirefoxではできるのにChromeではできないとは何事だと。
実はこの時、もう一つの方法も思い浮かべていましたが、すぐに無理だとなりました。
<!-- skipCopy -->
<p>
この国でも一夜に数千羽の七面鳥がしめられるという、あるクリスマス・イヴの出来事だ。<br/>
帝都最大の殷賑地帯、ネオン・ライトの闇夜の虹が、幾万の通行者を五色にそめるG街、その表通りを一歩裏へ入ると、そこにこの都の暗黒街が横たわっている。<br/>
G街の方は、午後十一時ともなれば、夜の人種にとってはまことにあっけなく、しかし帝都の代表街にふさわしい行儀よさで、ほとんど人通りがとだえてしまうのだが、それと引き違いに、背中合わせの暗黒街がにぎわい始め、午前二時三時頃までも、男女のあくなき享楽児どもが、窓をとざした建物の薄くらがりの中に、ウヨウヨとうごめきつづける。 </p>
この構造で、
- もし
<p>がネストできるならまだ道はある- → すぐ後に来る
<p>で閉じてしまうのでネストは無理
- → すぐ後に来る
- 一番外が
<div>で<p></p>の後に<br>がきても、それは段落間のマージンで済ませられるから無意味
つまり、
/* skipCopy */
p {
margin: xxxx;
br {
& + p {
margin-top: 1rem;
}
}
}
とかは無理だろうかと考えましたが、<p>(段落)はテキスト塊の一番外で文章を囲む要素であり、その中の<br>で分断されるとテキストが前後に分かれるだけで、スタイルできる要素はないと言うことが問題なのです。
<!-- skipCopy -->
<p>
テキスト
<br>
テキスト
</p>
こういうことです。もしテキストが<span>ででも囲まれていれば、それはスタイル可能になります。
<!-- skipCopy -->
<p>
<span>テキスト</span>
<br>
<span>テキスト</span>
</p>
たとえ<br>が折り返しだけであろうと、<span>にclassをつけたりして制御することはできますが、そういう要素はなにもないテキストであるから<br>にスタイルできないことが問題となり得るわけです。<br>だけであり、前後にあるのはテキストの塊でそれらを<p>で囲む段落内では改行間を制御することは無理ということなのです。
<br>が欲しいということはそこそこの文章量があり、当然他の行間より広い行間が欲しいわけですが、かと言って段落(<p>)間ほど離すべきでもないとしたら、cssで制御するためにそこにあるものとしては<br>しかないじゃないかと。
誰しもが考えることとしては<br>のある所に空の何かしらの要素を入れてblock要素にしたら良いじゃないと言うことでしょう。思い付きはするわけですが、改行毎にそれすんのと?そんな大変なことをしてんの?となるでしょう。<br>はもう入っているんですよ。だったらスタイルできた方が簡単・便利でしょう?というわけなのです。
Firefoxは<br>そのものの折り返しと言う機能を持ちながらも、スタイルすることを寛容しています。私はこれが正しいと思うのです。
他にもあるぞ、Chromeよ
例えばcssで、
/* skipCopy */
pre {
overflow-x: auto;
code {
...
}
}
こういうふうに、もし<code>がオーバーフローしたらスクロールしてでも全部を見せたいってことありますよね?
しかしChromeではそのスクロールバーが表示されるのが 一瞬 で、マージンやパディングにもよりますが、その表示される僅かの間でカーソルをその位置まで移動できるかっ!と。
ChromeでMDNのOverflow-xの解説ページで試してみたらわかります。操作できるのは最初の一回だけで、その後マウスオーバーしてもスクロールバーは出ないでしょう?
デフォルトで何でこんなおかしな仕様になっているんだとGrokに聞くと、それはMacOSに寄せた見た目重視の仕様ですと言います。いやそうじゃなくて仕様に忠実なのはわかるが、デフォルトでマウス操作できないってすべての人はタッチ操作だけで、マウス使ってないと思ってるんかと。
Firefoxではスクロールバーが出ない構造の時はありますが出たら操作できるはずという事と、Chromeでは表示を維持できないので「必ずマウスオーバーでスクロールバーが表示されるにはどうすればいいか」と合わせてGrokに尋ねると、別途cssで手を加える必要があると言います。
待て待て待てと。手を加えないとできないってそれバグと同等じゃないかと言うと、「いえこれはバグではなく仕様に忠実に作られています」と言います。誰だよそんなクソ仕様にしたのは、と思ったわけです。
なるほどそれで昔からOverlayScrollbars や SimpleBarなどがあるんだなと妙な納得感もあったわけです。
これは今回の内容と別なんでここまでにしますけども、掘り起こせばもっとあるんじゃないの?と疑ってます。
ChatGPTに回避策はないかを聞いてみた
という事で、ChatGPTにさんざん小言も言いました。が、ChatGPTが言うには、タイポグラフィの世界では改行で行間を作るのは正しいが、Webでは違うと言うんですよ。<br>は仕様的にできないと言うばかり。
ほう、例えばどんな?と聞くと、
br {
display: block;
margin-bottom: 20px;
content: "";
}
とかと言うんですよ。それでも無理なら::afterを使い……と、おい、ちょっと待てGPTよと、お前さっきまで、<br>はインラインを操作するものでスタイルを当てられないようになっていると言ってたじゃないか、インライン要素の中に突然ブロック要素が来たらレイアウトが崩れるでしょ(<span>てすと<br>テスト</span>で<br>がブロックになるとレイアウト崩壊)と言うてたやないかと。
待て待て待てと、何のためのinline-blockやねんと。
上記は、
_skipCopy_
待て待て待てと、何のための`inline-block`やねんと。<div class="text-4xl align-middle">これがレイアウト崩れ</div>になるかと。
と書いています。つまり、
div {
font-size: var(--text-4xl); /* 2.25rem (36px) */
line-height: var(--text-4xl--line-height); /* calc(2.5 / 2.25) */
vertical-align: middle;
}
と、同義です。
で、<br>は<br>のままでいいが、Webをリードしてる奴らは
- 何でスタイルできる別の要素を用意したり、
- 制限ありでスタイルをできるようにしなかったのか
を聞くと、元々<br>は箱(box)ではないからスタイルできないとの一点張り、そういうことを聞いてるんじゃなくて、<br>としての改行の機能はこれまで通りで良いが、Chromeでスタイルできないのはおかしいだろう?Firefoxではできるんだからと何度も尋ね、display:inline-blockで<span>もインラインだがブロック要素同様にスタイルできるやん?と聞くと、<span>は箱なのでとかなんとか。<br>だけがそうなんだと聞いてるわけで。
<br>だってそれ自体が改行させているわけではなく、<br>がある所をブラウザが改行するようにしているんじゃないのかと。blockというのはインラインの中で使うと、ある意味、前者の<br>のように改行の機能も持たせられるというのも知っていたので((上記の大きな字でやった「これがレイアウト崩れになるんか」という部分))、それはレイアウト崩れではないだろうと終始思っていたわけです。
レイアウトが崩れるのは、親にposition: relativeを設置せず子にposition: absoluteを使ってすっ飛んでいくとか、float: left|rightで高さの持たない要素を何とかしようとしたりと言うことだろうと。改行だけやで?と段々イライラしてくるわけです。<br>を連打して入れられているページがあったとして、それのどこが問題なんだと。見にくいだけだろ?とも思うわけです。
<br>は<br>のままにして、例えば別で、
- その要素はサイズを持たないboxとしてデフォルトではあり、
- 何か(
display:blockとか)で宣言したらスタイルできる代替要素を作る
とかなんとかとはできなかったのかと詰めたわけです。
すると、GPT「CSSでスタイルできるんで、逃げ道も用意してあるんですよ」という、おい、さっきそれは できん と言うたばかりじゃないか!となったわけです。
最初の質問に、「Markdownで改行を書けば<br>が自動で入るがこれをスタイルできない理由と、回避方法があれば教えて」と聞いた自分がバカでした。<br>をChromeでスタイルできないから聞いたわけですが、もうChatGPTの言うてるようなことはほとんど済ましているわけです。
解決編
タブをそっ閉じしまして、こいつはだめだ時間の無駄だと思ったわけです。
<br>の何がだめで、- こういう経緯があり
- それは〇〇と言う問題を生むので
<br>の本来の役目を果たすために- そういう仕様になった
と、ちゃんと問題と経緯を説明し、そして一番聞きたかった事が「代替案の有無」で、代替がないなら他のアプローチでそれを解決する方法です。
結果Webを作ってる彼らがやったのは、ブラウザ側で<br>にスタイルできないようにしたという、臭いものには蓋をするって考え方なんだろう?と。それって一番簡単で考えることを放棄した結果じゃないかと。
そういった会話の合間で、並行して色々考えてると、さっき、
- 「代替の要素があれば
display:block(あるいはinline-block)で行けそうだな」 - Firefoxでは普通に
<br>のマージンは効く
とすれば、これはChromeが独自に無効にしているだけだと。ChatGPTが言うChromeの仕様に不備があるだけだと。不備がある仕様をそのまんま忠実に実装した結果、動作は仕様通りだが日本語などでは不便になっていて、それは英語では感じにくい問題であると言うことかと。
よしClaudeに聞いてみよう
そこで、今度は質問を変えてClaudeに「markdown-it((11tyで使われているMarkdownパーサーでhtmlに変換するライブラリです))って改行すると<br>を挿入するのがデフォルトだけど、改行の役目はそのままで、別でスタイルできるように何かしらの要素あるいはオリジナルの要素が当たるようにしたらどうだろうか?」と質問しました。html5では独自タグも作れるはずですし。
するとClaude「面白いアプローチですね!それならcssでスタイルしたら改行するのも無理ではないかと」なんて回答。
「では、<br>を<cr>というのに変えるにはどうしたらいいだろうか?」と聞くと、「 特に難しくはなく2行追加するだけですよ 」と。
どうやって実現するか?
mdLib.renderer.rules.softbreak = () => '<cr></cr>';
mdLib.renderer.rules.hardbreak = () => '<cr></cr>';
この2行を、
eleventyConfig.setLibrary("md", mdLib);
でライブラリに設定をセットする前に書くだけ。
const mdLib = markdownIt({
html: true,
xhtmlOut: true,
breaks: true,
linkify: true,
typographer: true,
})
.use(rubyPlugin, { rp: ["(", ")"] })
.use(markdownItYoutube, { defaultClass: "ytp", separator: "::" })
.use(attrs, { selectorExceptions: ["table", "table tbody", "tbody"] })
.use(markdownItMultimdTable, {
multiline: true,
rowspan: true,
headerless: false,
Multibody: true,
});
mdLib.renderer.rules.softbreak = () => '<cr></cr>';
mdLib.renderer.rules.hardbreak = () => '<cr></cr>';
eleventyConfig.setLibrary("md", mdLib);
そうすると、<br>が書き出されていた所が<cr></cr>になるため、
/* skipCopy */
cr {
display: block;
margin-top: xxxxxx;
}
としてcssを書けるわけです。どこにも問題はありません。むしろ賢い人らが考えた<br>のない世界がここにあります(<cr>で代わりにしたけどな笑)と言う感じです。
これらは他の開発環境でもMarkdownのようにどこかでhtmlに変換する機構があればできると思います。何かが変換してブラウザで表示しているわけですから。
ちなみに<cr></cr>としているのは、Void要素(<br/>、<img/>、<hr/>等)はブラウザ側でハードコーディングされているのでJavScriptなどで後からvoid要素として追加できません。後から追加したものは必ずコンテナ扱いです。<cr></cr>と空要素として導入しています。
簡潔に、そうしたらどうなるのか
この国でも一夜に数千羽の七面鳥がしめられるという、あるクリスマス・イヴの出来事だ。
G街の方は、午後十一時ともなれば、夜の人種にとってはまことにあっけなく、しかし帝都の代表街にふさわしい行儀よさで、ほとんど人通りがとだえてしまうのだが、それと引き違いに、背中合わせの暗黒街がにぎわい始め、午前二時三時頃までも、男女のあくなき享楽児どもが、窓をとざした建物の薄くらがりの中に、ウヨウヨとうごめきつづける。
_skipCopy_
<div class="my-[1rem]">
この国でも一夜に数千羽の七面鳥がしめられるという、あるクリスマス・イヴの出来事だ。
帝都最大の殷賑地帯、ネオン・ライトの闇夜の虹が、幾万の通行者を五色にそめるG街、その表通りを一歩裏へ入ると、そこにこの都の暗黒街が横たわっている。
G街の方は、午後十一時ともなれば、夜の人種にとってはまことにあっけなく、しかし帝都の代表街にふさわしい行儀よさで、ほとんど人通りがとだえてしまうのだが、それと引き違いに、背中合わせの暗黒街がにぎわい始め、午前二時三時頃までも、男女のあくなき享楽児どもが、窓をとざした建物の薄くらがりの中に、ウヨウヨとうごめきつづける。
G街の方は、午後十一時ともなれば、夜の人種にとってはまことにあっけなく、しかし帝都の代表街にふさわしい行儀よさで、ほとんど人通りがとだえてしまうのだが、それと引き違いに、背中合わせの暗黒街がにぎわい始め、午前二時三時頃までも、男女のあくなき享楽児どもが、窓をとざした建物の薄くらがりの中に、ウヨウヨとうごめきつづける。
</div>
スクロールバーが表示されない場合はカーソルを当てて、Shift + マウスホイールでスクロールできます。矢印キーでも同様に。ブラウザのデフォルトの動作です。
Chromeではフォーカスが当たってshiftを押すと白枠が出ます。それがフォーカスが当たってる状態です
こうなります。段落<p>の間隔も見て欲しいので、繰り返し「G街の方は、午後十一時ともなれば~」を入れてあります。
既にこのサイトには<br>を<cr>に変換されるようにしてあるので、このサイト全体、上記の黒蜥蜴冒頭の表示と同じになります。
やることは、
- 設定ファイルに2行足して保存
- cssで
<cr>にスタイルを付けるdisplay: block;は必須。これで改行します。高さはmarginでもなんなりとで設定できます
- (当サイトなら)Githubにpush
これだけです。
まとめ
解決方法としてはごく簡単なことですが、<p>の中に今回の<cr>要素が入った所で何も問題はありません。これ単体では改行も何も無い要素に変わるだけです。
クロスブラウザ対応です笑<br>がスタイルできるようになれば、こんな手間さえ無くて済みます。最初にこの記事を書いていた時はFirefoxで確認していたので<br>にマージンを設置していましたが、Chromeで確認したらやたら文字が詰まってるなぁと思い、devツールで確認して気がついたわけです。
なんでも自由にする事を許容するのは確かに、それをブラウザが吸収しないといけなくなるので、シンプルに安全に保ちたい気持ちはわかります。
<br>は改行なのでサイズを持たないからスタイルができないのもわかりますが、その高さ(縦書きなら幅)ぐらい調整できても良いんじゃないかと。それが問題になるならダメですが、問題にもならないだろうと思うんです。
Firefoxでできることを、業界を牽引しているChromeができないとは何事なんだと。
できなくするではなく、しても問題が起きないようにするにはどうすればよいかを考えるのが大事なんじゃないかと思うわけです。