<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>ブラウザ</title><link>https://blog.ast.moe/tags/%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6/</link><description>Recent posts from 五里霧中</description><generator>Hugo</generator><item><title>自作ブラウザOmoikaneのHTML・CSS実装をまとめて進めた</title><link>https://blog.ast.moe/blog/2026-09-12/</link><pubDate>Sat, 12 Sep 2026 19:51:40 +0900</pubDate><guid>https://blog.ast.moe/blog/2026-09-12/</guid><description>&lt;p&gt;ここ数日、自作ブラウザの&lt;a href="https://github.com/ieee0824/omoikane"&gt;Omoikane&lt;/a&gt;でHTMLとCSS周りの実装をまとめて進めていました。&lt;/p&gt;
&lt;p&gt;最初はFirefoxと同じHTMLを表示して、どこに描画差が残っているかを調べていました。&lt;/p&gt;
&lt;p&gt;比較を始めると、単純な色の違いだけではなく、inline要素の矩形が取れていない、WebフォントをJavaScriptから扱えない、HTML fragmentをcontextに合わせてparseできない、といった基盤側の不足も出てきます。&lt;/p&gt;
&lt;p&gt;見つかったものを順番に直していたら、描画、レイアウト、CSSOM、DOM、HTML parserまで広がりました。&lt;/p&gt;
&lt;p&gt;今回は、その中で閉じた15件のIssueをまとめておきます。&lt;/p&gt;
&lt;h2 id="最初はfirefoxとの描画比較"&gt;最初はFirefoxとの描画比較&lt;/h2&gt;
&lt;p&gt;きっかけは、同じfixtureをOmoikaneとFirefoxで開き、DOMの矩形とスクリーンショットを比較したことでした。&lt;/p&gt;
&lt;p&gt;この比較で最初に見つかったのが、次の問題です。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;textareaの複数行表示と改行位置が合わない&lt;/li&gt;
&lt;li&gt;inline spanの背景が描かれず、&lt;code&gt;getClientRects()&lt;/code&gt;も空になる&lt;/li&gt;
&lt;li&gt;Arabicテキストが連結字形ではなく欠落グリフになる&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://github.com/ieee0824/omoikane/pull/680"&gt;PR #680&lt;/a&gt;で、&lt;a href="https://github.com/ieee0824/omoikane/issues/673"&gt;#673&lt;/a&gt;、&lt;a href="https://github.com/ieee0824/omoikane/issues/674"&gt;#674&lt;/a&gt;、&lt;a href="https://github.com/ieee0824/omoikane/issues/675"&gt;#675&lt;/a&gt;をまとめて修正しました。&lt;/p&gt;
&lt;p&gt;inline要素については、行ごとの要素境界を保持し、背景描画と&lt;code&gt;getClientRects()&lt;/code&gt;、&lt;code&gt;getBoundingClientRect()&lt;/code&gt;で同じ矩形を使うようにしました。&lt;/p&gt;
&lt;p&gt;textareaは改行コードをLFへ正規化し、単語とgrapheme単位の折り返し、行高、padding端でのclip、UTF-16位置でのcaretとselectionを処理します。&lt;/p&gt;
&lt;p&gt;Arabicについてはfont fallbackを増やしただけではなく、data URLの読み込み漏れや、URL内の数字を変換してBase64を壊していた処理、font shorthandからfamilyが消える問題も直しています。&lt;/p&gt;
&lt;p&gt;修正前後とFirefoxで25条件を撮影し、同じブラウザ内では再撮影した画像が一致することも確認しました。&lt;/p&gt;
&lt;p&gt;このPRでは、macOSでテスト用HTTPサーバーが&lt;code&gt;WouldBlock&lt;/code&gt;になり、CSPテストの後片付け中に二重panicする&lt;a href="https://github.com/ieee0824/omoikane/issues/703"&gt;#703&lt;/a&gt;も一緒に直しました。&lt;/p&gt;
&lt;p&gt;描画比較をする前にテスト基盤が不安定だと、結果が実装差なのかテストの失敗なのか分からなくなるので、このあたりも必要でした。&lt;/p&gt;
&lt;h2 id="inline-blockを一つの箱として扱う"&gt;inline-blockを一つの箱として扱う&lt;/h2&gt;
&lt;p&gt;Webフォントのfixtureを比較していると、文字列の横幅は合っているのに、&lt;code&gt;inline-block&lt;/code&gt;の高さだけが10pxずれていました。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-css" data-lang="css"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;#measure {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;display&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;inline-block&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;font&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;40&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt;&lt;span style="color:#f92672"&gt;/&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;50&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; DynamicFace, &lt;span style="color:#66d9ef"&gt;monospace&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;border&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;solid&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;padding&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;8&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;px&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Firefoxでは、border boxの高さが70pxになります。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;line-height 50px
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;+ padding 8px × 2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;+ border 2px × 2
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;= 70px
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Omoikaneでは60pxになっていました。&lt;/p&gt;
&lt;p&gt;原因は、&lt;code&gt;inline-block&lt;/code&gt;を通常のinline要素と同じように断片へ展開し、内部に独立した整形文脈を作っていなかったことです。そのため、明示した50pxのline boxではなく、40px相当のglyph metricsが高さに使われていました。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ieee0824/omoikane/issues/709"&gt;Issue #709&lt;/a&gt;では、&lt;code&gt;inline-block&lt;/code&gt;を親の行に置かれるatomic inline-level boxとして扱い、子要素は独立した&lt;code&gt;LayoutBox&lt;/code&gt;でlayoutするように変更しました。&lt;/p&gt;
&lt;p&gt;これによって、内部line box、block child、shrink-to-fit、baseline、&lt;code&gt;vertical-align&lt;/code&gt;、overflow、transform、hit testを要素単位で処理できます。&lt;/p&gt;
&lt;p&gt;修正後は、FirefoxとOmoikaneのDOMRectがどちらも&lt;code&gt;(24, 24, 300, 70)&lt;/code&gt;になりました。&lt;/p&gt;
&lt;h2 id="webフォントをjavascriptから扱えるようにする"&gt;WebフォントをJavaScriptから扱えるようにする&lt;/h2&gt;
&lt;p&gt;Omoikaneは以前からCSSの&lt;code&gt;@font-face&lt;/code&gt;を描画に使えましたが、JavaScriptからフォントを読み込むAPIがありませんでした。&lt;/p&gt;
&lt;p&gt;ページ側から見ると、次のような処理ができません。&lt;/p&gt;</description></item></channel></rss>