🧸

HTMLメールエディタのアクセシビリティ向上のために取り組んでみたこと

2024/04/19に公開

はじめに

こんにちは!株式会社 CastingONEの岡本です。
最近keyballのキースイッチをHyacinth V2に変更したのですが、打鍵音が最高でした!おすすめです!

さて、今回はCastingONEで使われている HTML メールエディタのアクセシビリティをどのように向上したかについて書いていきます。自分自身、アクセシビリティの知識に関してはまだまだ学ぶことが多い段階ですが、これからアクセシビリティを向上させていこうと思っている方の一助になれば幸いです。

背景

弊社のフロントメンバーは、以下の記事のようにアクセシビリティ向上に対する取り組みを行っていました。その中のアクセシビリティチェックを行なったところ、HTML メールエディタのアクセシビリティの配慮が不足していることを実感しました。現在 Nuxt から React(Next.js) にリプレイスを行っている最中なので、リプレイスをしていく中でアクセシビリティを向上できればと思い、取り組んでみました!

https://zenn.dev/castingone_dev/articles/1bca86b5eb2131

HTML メールエディタについて

改善話に入る前に、弊社の HTML メールエディタについて簡単に説明します。
HTMLメールエディタの概略図

本文や件名の入力・作成を行うコンテンツフィールドとコンテンツフィールドを編集するためのツールキットで構成されています。ツールキットにある、コンテンツブロックをドラッグし、本文のエリアにドロップすることで HTML になるブロックを挿入でき、挿入されたブロックは並び替えもすることができます。また、挿入した要素を選択することで、その要素の編集ができます。

改善した内容

ここからは上記の HTML エディタをどう改善していったかを説明していきます。

tab キー移動対応

Nuxt の時の HTML メールエディタだと、そもそも tab 移動で特定のブロックにフォーカスが当たらないことや、フォーカスが当たっているにも関わらずスタイルを当てていないせいで、フォーカスが当たってていることに気づきにくい箇所が散見していました。これらの問題解決をするために取り組んだことについて書いていきます!

tab 移動で特定のブロックにフォーカスが当たらない問題の解決策

tab 移動で特定のブロックのフォーカスが当てるために、以下の 2 点を実施しました。

  • 適切なマークアップ
  • tabindex の使用(非推奨)

大前提として、HTML エレメントのabuttoninputのようなインタラクティブな要素は、デフォルトで tab 移動の対象になるのですが、divul, liのようなインタラクティブではない要素は tab 移動の対象になってくれません。 見た目がボタンのようなものに対して、divタグなどの非インタラクティブ要素を使用してマークアップしてしまうと、tab 移動の対象になってくれません。なんでもかんでもdivタグを使うのではなく、ボタンっぽい見た目なら、ちゃんとbuttonタグを使うなど、適切なマークアップを使用するようにしました。実際に tab 移動してみて、「あれ、こいつにフォーカス当たってくれないんだ、、」と思った要素はマークアップが適切でない可能性が高いので、そう思った箇所を徹底的に修正していきました。

上記の対応で大部分の tab 移動はできるようになりましたが、本文にドロップした後のコンテンツブロックはdiv要素でラップしているのですが、並び替えをするためのつまみ部分やコピー/削除ボタンにアクセス出来るようにするために tab 移動の対象にしたかったので、スタイルやエレメントの作り替えを実施して試してみたのですが、うまくいかなかったため、暫定対応でtabindex属性を使用しました。tabindex0を指定することで、tab 移動の対象にすることができます。以下にサンプルを用意したので、tab 移動してみてください。

フォーカスが当たっていることに気づきにくい箇所問題の解決策

フォーカスが当たっていることをユーザーに気づかせるために、focus-visibleという CSS セレクタを使用しました。focus-visibleとは、キーボードでフォーカスを当てた時だけフォーカスリングを表示するための CSS セレクタです。

.btn:focus-visible {
  outline: 2px solid green;
}

似たような CSS セレクタで、focusがあると思いますが、focusはマウスクリックでフォーカスを当てた場合でも、キーボードでフォーカスを当てた場合でも、フォーカスリングが表示されてしまうためfocus-visibleを使用しました。以下にサンプルを用意してみたので、実際に tab 移動やマウスクリックをしてみて、違いを確認してみてください!


これらの対応を盛り込み、tab 移動が違和感なくできるようになりました!
HTMLメールエディタのタブ移動

ドラッグアンドドロップがキーボード操作で出来るようになった

弊社の HTML メールエディタでは、テキストやボタンなどの要素をブロックとして扱い、ユーザーは使いたいブロックを本文作成部分にドラッグアンドドロップで挿入/並び替えを行い、HTML メールを作成していきます。Nuxt の時はドラッグアンドドロップがマウス操作でしか行うことができませんでした。

React では、ドラッグアンドドロップ周りの実装をdnd-kitを入れて対応しました。dnd-kit はアクセシビリティをものすごく配慮してくれているライブラリであり、こちら側で特に何か設定せずともキーボード操作に対応しています! ドラッグ対象の要素を指定すると、その要素にrole="button"tabindex="0"を付与してくれて、上述の tab 移動の対象にもしてくれます。

ブロック挿入 ブロック並び替え
キーボード操作でのブロック挿入 キーボード操作でのブロック並び替え

この改善に関しては dnd-kit を採用した副産物ですが、ドラッグアンドドロップのような UI/UX に関連するライブラリの選定基準にアクセシビリティの配慮があるかどうかを確認することが大事かもしれません!

https://docs.dndkit.com/

スクリーンリーダーへの配慮

スクリーンリーダーを使用するユーザーに配慮することは、アクセシビリティを向上させる上で非常に重要だと思っています。弊社の HTML メールエディタでは、スクリーンリーダーユーザーにも適切な情報を提供できるように改善に取り組みました!WYSIWYG ツールバーdnd-kitで改善したことを説明していきます!

WYSIWYG ツールバー

適切なマークアップを使用することで、ある程度は違和感なく読み上げられるようにはなるのですが、細かいところは不十分です。例えば、弊社の HTML メールエディタでは以下の画像のようなテキストを装飾するための WYSIWYG ツールバーの中でボールドやイタリック、下線を表すアイコンを使用しているのですが、Nuxt の頃はこれらの装飾ボタンに対して適切なマークアップができておらず、フォーカスが当たらなかったり、当たっとしても適切な読み上げが行われていませんでした。
WYSIWYGツールバーのスクリーンリーダー

React では装飾ボタンをちゃんとbuttonタグで作成し、それだけではなく、スクリーンリーダーのような支援技術にセマンティックな情報を提供するためにARIA 属性を使用して、適切な読み上げが行われるように対応しました。ここの部分では、以下のサンプルコードのように ARIA 属性のaria-pressed属性とaria-label属性を使用しました。

export const BoldMarkButton = ({
  isActive,
}: {
  /** 選択中か */
  isActive: boolean;
}) => {
  return (
    <button aria-pressed={isActive}>
      <BoldIcon aria-label="太字" />
    </button>
  );
};

aria-pressed

aria-pressed属性は、装飾ボタンの状態(押されているかどうか)を示すために使用しています。装飾ボタンが押された状態の時にtrueを指定することで、VoiceOver では「選択中」と読み上げられるようになります。

aria-label

aria-label属性は、装飾ボタンの説明をするために使用しています。装飾ボタンをアイコンのみで表現している UI のため、このアイコンが何の意味なのかを読み上げられるようにしています。


上記の実装を行うことで、以下の改善後のようにスクリーンリーダーで適切に読み上げられるようになりました!🎉

Nuxt(改善前) React(改善後)
NuxtのWYSIWYGツールバー NextのWYSIWYGツールバー

dnd-kit の日本語読み上げ対応

dnd-kit は公式にも書いてある通り、バンドルサイズを抑えるために、言語は英語しか対応していません。そのため、スクリーンリーダーで読み上げると英語で読み上げられてしまいます。

If your application supports multiple languages, make sure you also translate these instructions. The <DndContext> component only ships with instructions in English due to bundle size concerns.
https://docs.dndkit.com/guides/accessibility

ですが、dnd-kit のDndContextaccessibilityプロップに読み上げて欲しい文章を渡すことができます。例えば、ドラッグ操作が開始されたら「ドラッグを開始しました」と読み上げられるように設定することができます。この機能を使用して、日本語で読み上げられるようにしました。以下はサンプルコードです。

<DndContext
  accessibility={{
    announcements: {
      /** ドラッグ開始 */
      onDragStart(id) {
        return `ドラッグ可能なアイテム${id}のドラッグを開始しました`
      }
      /** ドラッグ終了 */
      onDragEnd({ active, over }) => {
        if (over) {
          return `ドラッグ可能なアイテム${active.id}がドロップ可能エリア${over.id}の上にドロップされました。`
        }
        return `ドラッグ可能なアイテム${active.id}がドロップされました。`
      },
    },
    screenReaderInstructions: {
      draggable: 'ドラッグ可能なアイテムを選択するには、スペースバーを押してください。ドラッグ中は、矢印キーを使用してアイテムを移動します。アイテムを新しい位置にドロップするには、再度スペースバーを押してください。'
    }
  }}
>
  {/* .... */}
</DndContext>

上記の実装を行うことで、日本語でスクリーンリーダーが読み上げられるようになりました!(id の読み上げは不必要なので、今後修正するつもりです!)

announcements 未設定 announcements 設定
announcements未設定のドラッグ終了時の読み上げ announcements設定したドラッグ終了時の読み上げ
announcements未設定のドラッグアイテムの読み上げ announcements設定したドラッグアイテムの読み上げ

終わりに

以上が、HTML メールエディタのアクセシビリティをどのように向上させたかについてでした。アクセシビリティ向上に対する取り組みのおかげで、自分自身開発を進めていく中でアクセシビリティを考えるクセがついてきた気がします。これからも常に意識しつづけ、良いユーザー体験を与えることができるサービスを開発していけたらなと思います!

弊社ではいっしょに働いてくれるエンジニアを募集中です。社員でもフリーランスでも、フルタイムでも短時間の副業でも大歓迎なので、気軽にご連絡ください!

https://www.wantedly.com/projects/1130967

https://www.wantedly.com/projects/768663

https://www.wantedly.com/projects/1244229

Discussion