スキップしてメイン コンテンツに移動
PB-100の宇宙の中の人
PBロッキーの日記

hamura.cssのマルチブラウザ技術、pbLCD.cssとpbChr.css, pbList.cssのフォールバックの画像置換と強制カラーモード

hamura.css > issue 22, hamura.css > issue 23 での解決事項を記事に追記しています。(2022/04/27)

本記事の内容を一般化して述べると、フォント画像やフラットデザインのアイコン等の単色画像への画像置換を大々的に行っているウェブページの強制カラーモード対応の実際について、です。ソースコードと併せて読み進めてみてください。


Firefox 3.1b3(Gecko 1.9.1), Windows の強制カラーモードでの表示

hamura.css は、各ブラウザエンジンとバージョンの実装状況に合せて異なるプロパティと技術を駆使して、同等の表現を実現します。

このプロパティと技術の取捨選択が複雑多岐になる為、この機会にガッツリと文書にまとめておきます。

特に画像置換に強制カラーモード(ハイコントラストモード)が絡むと、使用プロパティと技術の選択がシビアでした。なんとかモノになって本当に良かったです。という hamura.css 開発者用の記録です。

  1. はじめに
    1. コンピュータの入出力内容のマークアップ
    2. CSS によるテキストの画像置換
    3. テキストだけの情報提供
  2. 使用する技術とプロパティ
    1. 強制カラーモード(ハイコントラストモード)
      1. Edge 72~, Chrome 89~, Firefox 89~ の強制カラーモード
      2. IE10~, Edge ~18 の強制カラーモード
      3. IE9, Gecko 1.9.1~88, Goanna の強制カラーモード
      4. IE8 の強制カラーモード
    2. Gecko の奇妙な挙動への対処
  3. pbLCD.css の絶対配置の図
    1. Gecko ~1.3のペイントの問題
    2. 多くのブラウザの座標系
    3. バグを回避する為の座標系
    4. Gecko 1.3.1以下のフォーカスとレンジの問題
  4. border-colortransparent を使えないIE6以下用の変更
  5. IE5 の CSS-P とインタラクションの制限

1. はじめに

hamura.css を読み込むことで、PB-100 の LCD を模した画像状のコンテンツ(pbLCD.css)と LCD セグメントを模した画像状のコンテンツ(pbChr.css)を HTML で表現出来ます。

HTML5スタンダード・デザインガイド > コンピュータの入出力内容をマークアップする

また pbList.css では Web フォントに非対応なブラウザに対して pbChr.css と同じ方法で画像フォントでフォールバック表示します。但し、この時に使用するフォント画像は白抜きのマスク画像です。

これらのマークアップは注意深く設計されている為、ツールチップなどの豊かな表現力を備える pbLCD.css でも多重の <div> の入れ子のようなマークアップではありません。一般的なセマンティックなマークアップにだいたいなっています。

1.1. コンピュータの入出力内容のマークアップ

先に挙げた『HTML5スタンダード・デザインガイド』にある通り、hamura.css でも PB-100 の画面のマークアップには <pre><samp> を使っています。

次に示すのは、ターミナル操作と出力のマークアップの例です。

<pre><samp>PS &gt; <kbd>npm start</kbd>
&gt; node local-web-server.js

Listening on port 8022</samp></pre>

1.2. CSS によるテキストの画像置換

CSS を使ったテキストの画像置換はロゴ(ロゴタイプ)などに使われる古くからあるテクニックです。hamura.css では pbLCD.css と pbChr.css のキャラクター表示と、pbList.css のフォント画像によるフォールバックで大々的に使っています。

画像置換とは

画像置換とは HTML 内のテキストを非表示にし、その範囲を背景画像へと置き換える CSS の手法です。最近はあまり使われなくなりましたが、以前は SEO 対策として利用されたテクニックです。

CSS による画像置換では主に、content:urlbackground-image を使います。(この他には特定の状況で mask を使いました。)

なかでも content:url には、ハイコントラストモード時や、印刷時に背景画像を印刷しない設定でもコンテンツが欠落しない利点があります。しかしサポートするのは比較的新しめのブラウザになってしまいます。

画像置換のクロスブラウザに関する情報は『【画像スプライト編】Web文書のグレースフルデグラデーションをムキになってやってみる』にあります。この機会に覚えておきましょう。

1.3. テキストだけの情報提供

多くの機能が実装途中の NetSurf 3.10では CSS を切った方が、むしろコンテンツは欠落しない。

ブラウザが CSS と画像に非対応の場合、テキストでコンテンツが提供されます。これは hamura.css の定義する HTML が、検索ボットやスクリーンリーダーにテキストと適切な HTML タグでコンテンツを伝えることが出来ることでもあります。

多くのブラウザは画像を無効に出来ます。更に Firefox は 表示 > スタイルシート から スタイルシートを使用しない を選択できる為、これらの状況への対応も頭の隅に入れておきます。

2. 使用する技術とプロパティ

ブラウザ CSS Generated Content フォント画像ファイル pbChr pbLCD pbList
キャラクタ表示 カーソルの点滅 キャラクタ表示 透過 ゴースト マスク画像ファイル
モダンブラウザ(*1) x3.gif, x3.svg, x3.anime.svg(*6) :after + content:url animation gif, CSS Animation(*5, *6) :after + content:url opacity :before + content:url x3mask.png, x3.anime.svg(*6)
IE 9 x3.gif, x3.svg(*6) :after + content:url animation gif, DHTML(*6) :after + content:url opacity :before + content:url x3mask.png, x3.svg(*6)
IE 8 〇(*2) x3_x10.png, x3_csr.gif :after + content:url animation gif :after + content:url 透過 png :before + content:url x3mask.png
Opera 9~9.2x △(*3) x3.gif background-image animation gif :after + content:url opacity :before + content:url x3mask.png
Opera 7.2~8 △(*3) x3_x10.png, x3_csr.gif background-image animation gif :after + content:url 透過 png :before + content:url x3mask.png
Opera 7~7.1 ×(*4) x3_x10.png background-image DHTML(*7) background-image 透過 png(*11) DHTML x3mask.png
Gecko 0.9~1.9.0 ×(*4) x3.gif background-image animation gif background-image -moz-opacity DHTML x3mask.png, x3mask.gecko0.9.1.png(*8)
Gecko ~0.8.1 ×(*4) x3_x10.png, x3_csr.gif background-image animation gif background-image 透過 png(*9, *11) DHTML x3mask.png
IE 7 - x3_x10.png, x3_csr.gif background-image animation gif background-image 透過 png DHTML x3mask.png
IE 5~6 - x3_x10_8.png, x3_csr.gif background-image animation gif background-image 疑似透過 png(*10), -ms-filter DHTML x3mask.png
MacIE 5 - 未実装
  1. モダンブラウザは IE10 以上、Firefox 3.5(3.1 beta)以上、Opera 9.5以上、Safari, Chrome
  2. IE8 には CSS Generated Content に -ms-filter を使えない制限がある。IE8 の -ms-filter はハイコントラストモード時のツールチップの尻尾に使っています。
  3. CSS Generated Content を CSS-P する場合、ブロック要素でないと意図した動作をしない。この為に pbChr.css では画像置換に background-image を使う。
  4. CSS Generated Content をサポートするが CSS-P することが出来ない。この為に全ての画像置換に background-image を使う。
  5. EdgeHTML は、高圧縮されたアニメーション GIF でリピートしない為、カーソルの点滅に CSS アニメーションを使う
  6. モダンブラウザと IE9 の強制カラーモード(ハイコントラストモード)」にて詳しく。
  7. Opera 7~7.1x は背景画像のモーション gif に非対応の為、カーソルの点滅は javascript で行う。
  8. Gecko 0.9.1, このバージョンだけ透過 png の透明色が黒くなる為、透過 gif に切り替えている。この手法でも pbLCD.css のコンディション部分の問題が解決していない。
  9. Gecko 0.6~0.8.1, -moz-opacity を指定する要素が Viewport に入るとブラウザがクラッシュする。

  10. IE6以下は、透過 png に非対応の為、疑似的な透過 png を使う。キャラクターの組み合わせによっては背面にあるキャラクターが隠れてしまう。javascript で -ms-filter の可否を判定して正しい透過表示に切り替える。この機能は以前のバージョン(pbDisplay)から備えている。
  11. Opera 7~7.1x, Gecko ~0.8.1, 透過キャラクタの画像スプライトの background-position の指定は javascript で行っている。これらのブラウザが background-position-y を非サポートの為、各キャラクタの透過度ごとに background-position を指定すると CSS が巨大になってしまうためです。

2.1. 強制カラーモード(ハイコントラストモード)

強制カラーモードと画像置換は大変に相性が悪いですが、様々な手法を駆使して相性問題を解消しています。

2.1.1. Edge 72~, Chrome 89~, Firefox 89~ の強制カラーモード

forced-colors メディア特性をサポートするこれらのブラウザの pbChr.css と、pbList.css の画像フォールバックでは mask を使ってボーダーをフォントの形で切り抜いています。CSS の上書きはやや複雑になりますが、通常のカラーモードの x3.gif をそのまま mask-image に使える為、別の画像のダウンロードが不要な利点があります。

2.1.2. IE10~, Edge ~18 の強制カラーモード

-ms-high-contrast メディア特性をサポートするこれらのブラウザの pbChr.css と、pbList.css の画像フォールバックでは x3.animate.svg でキャラクタを表示します。カーソルの点滅は SVG ファイル内に記述した CSS Animation で行います。

2.1.3. IE9, Gecko 1.9.1~88, Goanna の強制カラーモード

先のメディア特性をサポートしないブラウザの pbChr.css と、pbList.css の画像フォールバックでは x3.svg でキャラクタを表示します。SVG には <path style="fill:WindowText" /> のスタイルが設定されていて、閲覧者の選択したテキストカラーが塗り(fill)に反映されます。カーソルの点滅は javascript で行っています。

2.1.4. IE8 の強制カラーモード

dark-on-light(黒いテキストカラーに白地など、テキストカラーの方が暗い), light-on-dark(白いテキストカラーに黒地など、テキストカラーの方が明るい) を Javascript で検出し、light-on-dark の場合は outline を使って色を反転(invert)させてカラー設定に馴染ませています。

テキストカラーと背景色が黒と白の場合には意図した描画を得られますが、これ以外の色の場合、必ずしも良好な描画ではありません。

light-on-dark, dark-on-light は hamura.css が使用するクロスブラウザライブラリが独自に定義したものです。詳しくは『ユーザー設定の調査』を参照します。

2.2. Gecko の奇妙な挙動への対処

  1. Gecko 1.1 には -moz-opacity が設定されている <b> 要素が <a> 要素の下に居ないと非表示になってしまう問題がありました。解決していますが、発生条件と回避条件を特定できてはいません。

    Gecko 1.1.1 で現象を確認しています。Gecko 1.0(Netscape Navigator 7.0), Gecko 1.2 では問題は発生していません。

  2. Gecko 0.6~1.3 には CSS-P している要素が親要素ボックスをはみ出すと描画されない問題がある。この問題を迂回するためにレイアウトを変更している。(後述)

    この変更によってフォーカスとレンジの描画が他のブラウザに劣ります。(後述)

3. pbLCD.css の絶対配置の図

pbLCD.css は200x70ピクセルの画像状のコンテンツをマークアップで記述することが出来ます。CSS-P と画像置換で HTML を PB-100 の LCD 風に置換しています。

3.1 Gecko ~1.3のペイントの問題

Gecko 1.3.1以下で CSS-P に関連したペイントの問題

さて、Gecko ~1.3 には CSS-P している要素が親要素を上下にはみ出す部分について、onload 時に当該要素が ViewPort 外の場合にペイントされない問題がありました。

マウスで周辺を触ると描画される。さらにスクロールで ViewPort 外に出た後に再び ViewPort に入ると描画されていない場合もあります。

そこで2種類の異なる座標系の CSS を用意しました。

3.2. 多くのブラウザの座標系

Nesting of pbLCD, For most browsers.
Edit on draw.io

<pre> とこの直下の <samp> 要素は、200x70ピクセルのサイズです。液晶画面全体を表示しているのは <samp> です。

LCD セグメントに対応する <b> にツールチップやレンジを関連付ける <a> 要素は、<b> より一回り大きいサイズです。この為、ツールチップは <a> 要素の上下にはみ出す位置に出現します。

マウスホバーやタブフォーカスといった閲覧者のインタラクションで、<a> に背景色が付きます。これは <b> より一回り大きいサイズになります。

3.3. バグを回避する為の座標系

Nesting of pbLCD, For browsers with paint bugs around CSS-P.
Edit on draw.io

<pre>, <samp>, <a> 要素の高さを、上下のマージン30pxづつを加えた130pxとします。液晶画面全体を表示しているのは <small> です。

ツールチップが親要素をはみ出すことが無くなった為、ペイントが欠落する問題は解消されました。

しかしこの変更によって、フォーカス時の塗りとレンジが他のブラウザに劣るものになってしまっています。

3.4. Gecko 1.3.1以下のフォーカスとレンジの問題

レンジの下線が LCD セグメント毎に切れる問題は hamura.css > issue 22 で解決しました。(2022/04/27)

Gecko 1.3でのフォーカスとレンジの様子
Gecko 1.4でのフォーカスとレンジの様子

Gecko 1.3ではフォーカス時に現れる破線は対象の LCD セグメントを囲む形にはなりません。

レンジの下線は、LCD セグメント毎に切れてしまっています。(解決済)

4. border-colortransparent を使えないIE6以下用の変更

hamura.css では、border を駆使して三角形を描画するテクニックをツールチップの尻尾で使っています。このテクニックは広範なブラウザで使えて便利なのですが、IE6 以下では border-colortransparent を指定できない制限があります。

hamura.css はライブラリとして公開されている為、ウェブページの背景色は未定です。この為に transparent を使えないのは具合が悪いのです。

この制限の為、IE6 以下ではツールチップの尻尾は常に LCD の青色のベゼルの上にあるように変更しています。これならばウェブページの背景色は問題になりません。

IE6 の上側のツールチップは青色のベゼルのやや内側に出現する
IE6 の上側のツールチップはマウスホバーで上に向かうも、青色のベゼルをはみ出さない
IE5.5 のツールチップはマウスホバーやタブフォーカスで内側に移動する

5. IE5 の CSS-P とインタラクションの制限

この問題はツールチップのタグ構造を変更して hamura.css > issue 22 で解決しました。(2022/04/26)

IE5 の上側のツールチップはマウスホバーで本体部分だけが移動して、尻尾はその場に残る
IE5 の下側のツールチップはマウスホバーでしっぽ部分だけが移動して、本体はその場に残る

未解決の問題として、IE5 のツールチップのインタラクションでの CSS-P が正しくない問題があります。

この他にも、IE6 ないし IE5.5 以下には、CSS-P の問題に遭遇しています。随分昔に取り組んだことなので失念しています。