2024年10月7日の月曜日 26時20分ぐらい

Twitter(新X)アイコン対応とCSS MaskingによるSVGアイコンについて

2024/10/08 02:21 2024/10/08 12:53
#CDMP
#SSG
#CSS

本日放送のはなかっぱ2本目「恋する小鳥とはなかっぱ」が名作だったなぁと思ったこととは全く関係なく、先日思い立って左メニュー内のプロフィール用アイコンと記事フッタ内のシェアリンク用Twitterアイコンを新Xアイコンに変えたのでそれぞれ以下のようになりました。

compare twitter x

また1匹の青い鳥(白い鳥)が飛び立ってしまった・・・。

せっかくなので本ブログで使うアイコンについて書いてみます。

CDMPで利用しているCSSベースのSVGアイコンについて

CDMPの設計思想(というほど大したものではないんですが)は10年〜20年の利用スパンをターゲットにしているため、基本的に外部のライブラリなどは極力使わないようにしていますが、各アイコンに Bootstrap Icons を利用させて頂いています。ちなみに記事エディタにはAsciidoctor.jsも利用していますがSSG側からは見えていません。

v4.0→v4.9でのデザインリニューアル時にアイコンを求め、Font Awesome を使う予定だったのですが、構築途中でBootstrapのアイコンセットが発表され、使いたいアイコンデザインがあったためこちらを採用としました。

Bootstrap Iconsはいくつかの利用方法がありますが以下の要件を満たす方法として、本来画像の切り抜きやエフェクト用に定義されたCSS MaskingをSVGと組み合わせることでフレキシブルなアイコン表示を実現しています。

  • フォントファイル(約130KB)のロードによる肥大化を避けるためIconFontは使わない

  • できる限りHTMLコードは短く、できればIconFontと同じシンプルなコードとしたい

  • アイコンの色やサイズをCSSで設定したい(ダークモード対応など)

  • bi-以下はBootstrapIconsのitem名と合わせたい

実装方法 前述の通りCSS Masking を利用して、CSSの指定とdataURLの組み合わせで実装しています。またサイトレイアウト用のCSSとアイコン用のリソース定義ファイルを分離するためCSSを2つに分けています。実パス含めた実例はこのブログのheaderあたりをご覧ください。

style.css

サイトレイアウト用のstyle.cssにBootstrap IconsのSVGアイコン用のクラス.bi内でmask-*を指定し、mask-imageのurlを変数(--url)としてテンプレートを定義しておきます。

.bi {
  display: inline-block;
  vertical-align: -0.2em;
  width: 0.8rem;
  height: 0.8rem;
  margin: 0.1rem 0.3rem;
  background-color: #030;
  mask-repeat: no-repeat;
  mask-size: 0.8rem 0.8rem;
  mask-image: var(--url);
}

style-bi.css

実際のアイコンデータはアイコンリソース用の定義ファイルstyle-bi.css内で、各アイコン名のクラスを作成します。クラス内で色はbacground-colorで指定し、アイコンSVGデータは—​url変数でdataURL化(後述)し記述します。

例えば左メニュー内RSSアイコンは以下となります。

.bi-rss-fill {
  background-color: #F96;
  --url: url('data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2216%22%20height%3D%2216%22%20fill%3D%22currentColor%22%20class%3D%22bi%20bi-rss-fill%22%20viewBox%3D%220%200%2016%2016%22%3E%0A%20%20%3Cpath%20d%3D%22M2%200a2%202%200%200%200-2%202v12a2%202%200%200%200%202%202h12a2%202%200%200%200%202-2V2a2%202%200%200%200-2-2H2zm1.5%202.5c5.523%200%2010%204.477%2010%2010a1%201%200%201%201-2%200%208%208%200%200%200-8-8%201%201%200%200%201%200-2zm0%204a6%206%200%200%201%206%206%201%201%200%201%201-2%200%204%204%200%200%200-4-4%201%201%200%200%201%200-2zm.5%207a1.5%201.5%200%201%201%200-3%201.5%201.5%200%200%201%200%203z%22%2F%3E%0A%3C%2Fsvg%3E');
}

HTML

FontIconsの指定と同様にクラス名にテンプレートとアイコン名を指定します。

<i class="bi bi-rss-fill"></i>

もちろんタグ内で個別のstyle指定もできるため

<i class="bi bi-rss-fill"></i>
<i class="bi bi-rss-fill" style="width:1.5rem;height:1.5rem;mask-size:1.5rem;"></i>
<i class="bi bi-rss-fill" style="width:2rem;height:2rem;mask-size:2rem;background-color:#999;"></i>

のように書くと

とサイズ変更や色指定でグレーアイコンも簡単に書けるため便利です。なお、表示サイズ変更に.bi-x150といった拡大率設定クラスも併用しています。

アイコンリソースの追加方法

style-bi.cssへのアイコンの追加は、以下のadd_bi_to_css.phpスクリプトを利用し、利用したいアイコンのSVGをdataURL形式に変換してstyle-bi.cssに追加しています。

<?php

function add_icon_by_biname($icon_name){

  $icon_css_path = "./assets/css/style-bi.css";
  $file = file("https://github.com/twbs/icons/raw/main/icons/$icon_name.svg");

  foreach($file as $line){
    $svg .= $line;
  }

  $base64 = preg_replace('/\+/','%20',urlencode($svg));
  $iconurl_encoded =<<< EOL
  .bi-${icon_name} {
    --url: url('data:image/svg+xml;charset=utf8,${base64}');
  }

  EOL;

  file_put_contents($icon_css_path, $iconurl_encoded,FILE_APPEND);
}

$icon_name = $argv[1];

add_icon_by_biname($icon_name);

?>

これをCLIから実行しCSSファイルの末尾に追加します。例として新Xアイコンはbi-twitter-xなので以下となります。

$ php add_bi_to_css.php bi-twitter-x

SafariのVendor Prefix対応とBootstrap Iconsの変更履歴について

CDMPがv5.0になった当時はSafariのみ-webkit-mask-*が必要でしたが、2022年1月のv15.3にて標準化されたため現在はコメントアウトしています。

またBootstrap Iconsもv1.11.0(2023/09)から新Xアイコンが追加されたため、1年経ちようやくアイコンの更新となりました。

まとめ

これでCDMPの場合、

  • IconFontと同一コードでフォントファイルbootstrap-icons.woff2利用時の130KB → CSS&SVG利用で4KBまで圧縮

    • 同一コードなのでヘッダの変更のみでCSS→フォントファイル利用に戻せる *HTMLとstyle指定でCSSで色・サイズがカスタマイズ可能に

と、要件を満たすことができました。

実際のアイコン更新作業としては、新Xアイコンデータの追加とHTMLテンプレート内のクラス名bi-twitterをbi-twitter-xに変えてサクッと完了となりました。

  • めずらしく有用な記事だったのでリツイートしてね!

ちなみにiPhoneにはまだTwitterの鳥さんがいるのでリポストとかの用語はよく分からないままです。

「モクレン 鳥 そっくり」で画像検索してみて下さい