はじめに (対象読者・この記事でわかること)
この記事は、Webフロントエンドに関心のある開発者や、デザイナー向けに書かれています。特に、HTMLやCSSの基本は理解しているが、ページ上でよく見かける「山型マーク」(▲や△)が画像として埋め込まれているのか、テキストとして表示されているのかを判別したことがない、といった方を対象としています。
本記事を読むことで、
- 山型マークがテキスト(Unicode)で表現されているケースと、画像(SVG/PNG)で埋め込まれているケースの違いがすぐに分かる。
- JavaScript を使って実際に DOM からその種別を判定するコードを書けるようになる。
- テキストで実装すべきか画像で実装すべきかの選択基準と、アクセシビリティ・パフォーマンス面での利点・欠点が理解できる。
このテーマに興味を持った背景は、最近のプロジェクトで UI デザインガイドラインを見直す際に、同じような山型アイコンが何種類もの形式で混在していたことです。統一感と保守性を高めるために、まずは「本当に画像が必要なのか?」を検証したいと考えました。
前提知識
この記事を読み進める上で、以下の知識があるとスムーズです。
- HTML の基本構造(<svg>, <img>, 文字実体参照)
- CSS の基本(display, content)
- JavaScript の基本(DOM 操作, querySelector, getComputedStyle)
山型マークの概要と背景
ウェブ上でよく目にする「山型マーク」—たとえば「▲」「△」「▴」といった上向きの三角形は、デザイン上のアクセントやリストのマーカー、ドロップダウンの開閉指示など多様な用途で使われます。実装方法は大きく分けて次の二つです。
-
テキスト(Unicode 文字)として記述
- 例:▲(U+25B2 BLACK UP-POINTING TRIANGLE)や↑(U+2191 UPWARDS ARROW)
- フォントが対応していれば CSS のfont-sizeやcolorで自由に見た目を調整でき、解像度依存がありません。 -
画像(SVG/PNG)として埋め込む
-<img src="triangle.svg">、あるいは背景画像としてbackground-image: url(triangle.svg);
- デザイン通りの形状やグラデーション、シャドウを簡単に表現でき、フォントに依存しない安定した表示が可能です。
なぜ混在が起きるのか?
- デザイナーの指示:デザインツール(Figma, Sketch)からエクスポートされた SVG がそのまま使われることが多い。
- レガシーコード:昔は画像でしか表現できなかったため、現在でもそのまま残っているケースがある。
- アクセシビリティ:テキストならスクリーンリーダーが文字として認識できるが、画像は
alt属性が必要になる。
このように、どちらが適切かは「見た目の要件」「保守性」「パフォーマンス」「アクセシビリティ」の観点で総合的に判断します。
JavaScriptで山型マークが画像かテキストかを判定する実装方法
ここでは、実際にページ内の山型マーク要素を走査し、画像かテキストかを自動判定するスクリプト例を示します。主に次の三ステップで実装します。
ステップ1 対象要素の取得
Js// 山型マークと思われる要素を取得(例:クラス名 .mountain-mark) const marks = document.querySelectorAll('.mountain-mark');
.mountain-markはデザイナーが付与したクラスです。実際のプロジェクトではdata-mark="mountain"など属性でも構いません。
ステップ2 要素のタイプ判定ロジック
Jsfunction isImageMark(el) { // 1. img 要素か SVG <use> が含まれるか if (el.tagName.toLowerCase() === 'img' || el.querySelector('svg') !== null) { return true; } // 2. CSS 背景画像が設定されているか const style = getComputedStyle(el); if (style.backgroundImage && style.backgroundImage !== 'none') { return true; } // 3. テキストノードを走査し、Unicode の三角形か確認 const text = el.textContent.trim(); const triangleChars = ['▲','△','▴','∧','▵','▼','▽']; // 上向きだけでなく下向きも網羅 return !triangleChars.includes(text); } // 判定結果をコンソールに出力 marks.forEach(el => { console.log(el, isImageMark(el) ? '画像' : 'テキスト'); });
- ポイント
tagNameとquerySelector('svg')で直接的な画像要素を検出。getComputedStyleのbackgroundImageで CSS 背景画像の有無をチェック。- 最後にテキストノードだけが残っているかを確認し、Unicode の三角形文字かどうかを比較します。
ステップ3 判定結果に基づくリプレース処理(必要なら)
Jsmarks.forEach(el => { if (isImageMark(el)) { // 画像の場合はテキストに差し替える例 el.innerHTML = '▲'; // ブラックアップトライアングル el.style.backgroundImage = 'none'; el.removeAttribute('src'); } });
このコードは、画像で実装されていた山型マークをテキストに置き換える簡易的な例です。実際のプロジェクトでは、デザイン要件に合わせて CSS カスタマイズや ARIA 属性の付与を行う必要があります。
ハマった点やエラー解決
| 症状 | 原因 | 解決策 |
|---|---|---|
getComputedStyle が null |
要素がまだ DOM に挿入されていない | スクリプトを DOMContentLoaded 後に実行、または MutationObserver で動的追加を監視 |
| Unicode の三角形がフォントに無い | 使用しているフォントが対象文字をサポートしていない | フォントファミリに Arial Unicode MS など広範囲文字を持つフォントを追加、または font-family: system-ui, "Apple Color Emoji", "Segoe UI Symbol" |
背景画像が url("data:image/svg+xml...") の形で取得できない |
backgroundImage の値が url("...") 形式でラップされている |
正規表現 /^url\(["']?(.*)["']?\)$/ でパスを抽出し、!== 'none' を判定する |
解決策のベストプラクティス
- 早期判定:ページロード直後に判定し、不要な画像リクエストを防ぐ。
- アクセシビリティ:テキストに置き換える際は
aria-hidden="true"を付与し、スクリーンリーダーが不必要に読み上げないようにする。 - パフォーマンス:SVG をインライン化してキャッシュできるようにし、画像サイズの削減と描画速度向上を図る。
まとめ
本記事では、ウェブ上で頻繁に見かける山型マーク(▲/△)が 画像 か テキスト かを JavaScript で判定し、必要に応じてテキストへリプレースする手順を解説しました。
- 判定ロジック:タグ名・SVG 有無・CSS 背景画像・テキスト内容で総合的に判定
- 実装例:
querySelectorAll→isImageMark関数 → コンソール出力・リプレース - 注意点:フォント対応、アクセシビリティ、パフォーマンスを考慮した実装が重要
この記事を通して、山型マークの実装方式を客観的に評価し、最適化できるスキル を身につけてもらえることを期待しています。次回は「SVG アイコンの最適化手法」と「フォントベースアイコン(Font Awesome 等)の活用」について掘り下げる予定です。
参考資料
- MDN Web Docs – Unicode(Unicode character reference)
- CSS Tricks – How to use background‑image correctly
- WebAIM – Images vs. Text for Accessibility
- SVGOMG – SVGO GUI for optimizing SVG files