SmartPhoto.jsで快適な画像表示を!フォーカス外れ問題を解消する方法

これは「a-blog cms Advent Calendar 2024」の記事ではありません。

SmartPhoto.jsとは?

SmartPhoto.jsは、ウェブページ上の画像を簡単にスタイリッシュに拡大表示することができるJavaScriptライブラリです。レスポンシブデザインに対応しており、スマートフォンやタブレットなどのモバイルデバイスでも快適に使用できます。また、画像ギャラリーのように複数の画像を切り替えながら表示できる機能も備えており、a-blog cmsのデフォルトの画像表示ライブラリとして組み込まれていますが、それ以外の場所でもたびたび見かけるので、きっと人気があるライブラリです。


SmartPhoto.jsの数少ない弱点

便利なSmartPhoto.jsですが、キーボード操作時に少々気になる問題があります。それは、拡大表示された画像を閉じた際にフォーカスが外れてページの先頭に戻ってしまうという点です。

例えば、キーボードのTabキーでリンクを移動しながら操作している場合、SmartPhoto.jsで画像を拡大して閉じると、フォーカスがページの先頭に戻ってしまい、再び目的のリンクに戻るのが手間になることがあります。これはアクセシビリティにもよろしくありませんし、キーボード操作をすることが多い筆者へのユーザビリティに大変影響を与えています。


フォーカス外れを解消するJavaScriptを作りました!

この問題を解決するために、フォーカスを制御するカスタムJavaScriptを作成しました。このスクリプトでは、画像を閉じる前にフォーカスしていた要素を記憶し、画像を閉じた後にその要素にフォーカスを戻すようにしています。

  document.addEventListener("DOMContentLoaded", function () {
    var clickedLinkId = null;
    // SmartPhotoを初期化
    var photo = new SmartPhoto('[data-rel^="SmartPhoto"],.js-smartphoto');
    // 各リンクにクリックイベントを追加
    document.querySelectorAll('[data-rel^="SmartPhoto"],.js-smartphoto').forEach(function (link) {
      photo.on('open', function () {
        if (!link.id) {
          // 一意のIDを生成してリンクに設定
          var uniqueId = 'link-' + new Date().getTime();
          link.id = uniqueId;
        }
        clickedLinkId = link.id;
      });
    });
    // SmartPhotoのcloseイベント時にフォーカスを戻す
    photo.on('close', function () {
      if (clickedLinkId) {
        var clickedLink = document.getElementById(clickedLinkId);
        if (clickedLink) {
          clickedLink.focus();
          clickedLink.id = ''; // IDをクリア
        }
      }
    });
  });

上記のコードをSmartPhoto.jsを使用するページで読み込めばOKです。もし .js-smartPhoto 以外のクラスで利用している場合は、4行目と6行目を適宜書き換えてください。

上手く動作するとフォーカスが外れなくなります。以下の動画ではわかりやすくするためにフォーカスされた画像の色を変えるCSSを適用しています。


a-blog cmsで実装するには

実はa-blog cmsに実装されているSmartPhoto.jsは組み込みJSということで、少しカスタマイズされており、前述のスクリプトがそのままでは動作しません。

そこでやや「頭が頭痛」みたいなことをしなければならないのですが、あらたにSmartPhoto.jsの本来のスクリプトとCSSを読み込みましょう。

<script src="https://unpkg.com/smartphoto@1.1.0/js/smartphoto.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/smartphoto@1.1.0/css/smartphoto.min.css">

もちろんダウンロードして読み込んでもらっても構いません。その上で、先に紹介したフォーカス外れ解消スクリプトを設置します。

前述のスクリプトと異なるのはSmartPhoto.jsを動作させるクラスを .js-smartphoto2 に変えているところです。.js-smartphoto のままだとa-blog cmsの組み込みJSが動作してしまいますので、多重起動を避けるために変えなければなりません。

  document.addEventListener("DOMContentLoaded", function () {
    var clickedLinkId = null;
    // SmartPhotoを初期化
    var photo = new SmartPhoto(".js-smartphoto2");
    // 各リンクにクリックイベントを追加
    document.querySelectorAll(".js-smartphoto2').forEach(function (link) {
      photo.on('open', function () {
        if (!link.id) {
          // 一意のIDを生成してリンクに設定
          var uniqueId = 'link-' + new Date().getTime();
          link.id = uniqueId;
        }
        clickedLinkId = link.id;
      });
    });
    // SmartPhotoのcloseイベント時にフォーカスを戻す
    photo.on('close', function () {
      if (clickedLinkId) {
        var clickedLink = document.getElementById(clickedLinkId);
        if (clickedLink) {
          clickedLink.focus();
          clickedLink.id = ''; // IDをクリア
        }
      }
    });
  });

そして次にEntry_Bodyモジュールの「イメージビューワー」の設定を、class="js-smartphoto2" に変更します。



組み込みJSを使っている場合には多少手順がややこしくなってしまいます。

必要なJSだけを読み込む方が速いのは間違いないのですが、いろいろ入っている組み込みJSが便利でなかなか手放せないですよね。そういう場合にSmartPhoto.jsがちょっとだけ使いやすくなるスクリプトということでご理解くださいませ。

デモは以下の猫の画像でお試しください。操作はTabキーで遷移、Enterキーで拡大、Escキーで閉じるです。この画像だけですが、わかりやすくなるようにフォーカスが当たった際に画像の色を変えるようにしています。


いずれa-blog cms側で対応されそうな気がするのですが、ちょっとした対応でほんの少しだけ使いやすくできるので、必要な方はぜひご利用ください。


勢いで記事を書いてしまいましたが、ネタを1つ消費してしまったので、登録済みのAdvent Calendarの方に何を書こうかと悩んでおります・・・。


19:08追記 初出時の方法ではa-blog cmsでの実装時にSmartPhoto.jsが二重で動作して、スワイプで閉じる際に2回行わないといけなくなっていたため、別の方法に記事を書き換えました。確認して指摘してくださった皆さまありがとうございます!