SVG2で検討されているプロパティ

CSS Property Advent Calendar 2013の12日目の記事です。

もともと:futureや:pastなどを考えていたのですが、9日目にTime-dimensional擬似クラスについて調べてみたで書かれています*1ので、今日はSVG 2で検討されているプロパティを2つ見てみます*2

paint-orderプロパティ

SVGの描画モデルでは、図形やテキストは、まずfillが描画され、次にstrokeが描画され、その上にmarkersが描画されます(SVG 1.1ではRendering ModelのPainting shapes and textを参照)。

ですが、時と場合によってはこの順番を変えたい時があります。特にfillとstrokeの順番を変えたいときがあります。strokeは、strokeの中心がオブジェクトの縁(アウトライン)にあうように描画されるので、太くすればするほど内側にも食い込んできます。そのためテキストに太めのstrokeをつけたい場合には、大きなstroke-widthを指定するとfillがstrokeで隠れてしまう、というとても残念な結果になります。


図1:strokeプロパティだけを指定するとstrokeがオブジェクトの内側に食い込んできてしまう。それを回避するためにuse要素を使ってテキストをコピーしたり、フィルターを利用してきた。paint-order:strokeを指定するとstroke、fillの順に描画できる。

これを回避するには、fillだけ指定した要素の後ろに、strokeを指定した要素をもう1つおいたり、フィルターを使ったりしてきました。

<!-- use要素を使ってテキストを重ね書き -->
<use xlink:href="#text" style="fill:none; stroke:#fff; stroke-width:8px; ..." />
<text x="160" y="192" id="text" style="fill:#000">World Wide Web</text>

<!-- filterを使ってstrokeのようなものをつける -->
<defs>
  <filter id="filter">
    <feMorphology in="SourceAlpha" operator="dilate" radius="3" result="morph" />
    <feFlood style="flood-color:#fff" result="flood" />
    <feComposite in="flood" in2="morph" operator="in" result="composite" />
    <feMerge>
      <feMergeNode in="composite" />
      <feMergeNode in="SourceGraphic" />
    </feMerge>
  </filter>
</defs>
<text x="160" y="256" style="fill:#000; filter:url(#filter);">World Wide Web</text>

しかしSVG 2では、paint-orderプロパティによって描画の順番を変えることができるようになる見込みです。現在のところ、このプロパティには描画したい順番にキーワード(fill、 stroke、markers)を記述します。記述しなかったプロパティは、fill、stroke、markersの順に描画されるので、strokeを一番最初に描画して残りは通常どおりで良い、という場合にはpaint-order:stroke;と記述すれば十分です。

<!-- SVG 2ではpaint-orderプロパティを指定するだけ -->
<text x="160" y="320" class="stroke" style="paint-order:stroke; fill:#000 stroke:#fff; stroke-width:8px; ...">World Wide Web</text>

このpainte-orderプロパティはGeckoBug 838805)とBlink(Issue 223766)で実験的にサポートされています。Geckoではsvg.paint-order.enabledをtrueに、Chromeでは「試験運用版のウェブ プラットフォームの機能を有効にする。」必要があります。

vector-effect

SVGではオブジェクトを拡大したり縮小したりといったことが簡単にできます。これまではSVGではオブジェクトの全てが一律に拡大・縮小されてきましたが、SVG 2では拡大縮小してもstrokeを一定に保つことができるようになる見込みです。具体的にはSVG Tiny 1.2にもあるvector-effectプロパティを使います。strokeを一定に保ちたいオブジェクトにvector-effect: non-scaling-stroke;を指定します。

これがどう役に立つのかですが、こういう例はどうでしょうか。strokeだけ指定された星を画面上にたくさん配置します。この時、それぞれの星は大きさが異なりますがstrokeは一定にしたいとしましょう。GUIで例えるならば、画面上にスタンプで星をはりつけていくイメージです。そして、適当にグループ化を行い、その後拡大・縮小を行ったものと考えてください。

ともあれ、大きさが異なるだけであれば星の形は1つだけ定義して、後はクローンを配置しておけば良くなります。

<defs>
  <path id="star" d="..." style="stroke:#fff; strok-width:3px;" />
</defs>
<g>
  <use xlink:href="#star" x="..." y="..." />
  <g transform="scale(0.5)">
    <use xlink:href="#star" x="..." y="..." />
    <g transform="scale(1.25)">
      <use xlink:href="#star" x="..." y="..." />
    </g>
  </g>
  <use xlink:href="#star" x="..." y="..." transform="scale(0.75)" />
</g>

ところが、単純にクローンを配置するだけでは拡大・縮小(transformのscale)の影響を受けてstrokeの太さが変わってします。しかし、vector-effect: non-scaling-stroke; を指定するとstrokeの太さは拡大・縮小の影響を受けません。

<defs>
  <path id="star" d="..." style="vector-effect: non-scaling-stroke; stroke:#fff; strok-width:3px; " />
</defs>

自分で書いていてあまり良いユースケースではないなあと思いますが、ともあれstrokeを一定に保つことができます。

さて、このvector-effectプロパティはGeckoBug 528332)とWebKitBug 31438)およびWebKitから派生したBlinkでサポートされています。

おわりに

SVG 2では、ここで挙げた以外の機能の追加も検討されており、既存のプロパティの拡張も検討されています。例えば、fillやstrokeプロパティに複数の値をカンマ区切りで指定して、fillやstrokeを重ね塗りすることもできる(本稿執筆段階ではSVG2 Editor's Draftの11.2. Specifying paintにあります)ようになる見込みです(SVG 1.1などではfillやstrokeに空白区切りでフォールバックを複数指定することはできます)。

またフィルタやマスク、合成とブレンディングはFXTFの仕様を参照する形になる方向ですので、利用できるプロパティや値も増えるでしょう。

来年も、そしてそれ以降もSVG 2の動向が楽しみですね。

*1:余談ですが、WebVTTと擬似クラスでは、OperaFOMS 2012で行ったWebVTTのデモが好きです。:pastを使ったカラオケもあります(が、当時から仕様が微妙に変わっているためOpera 12くらいでしかカラオケは楽しめません)

*2:余談ですが、pointer-eventsfilterはもともとSVGで定義されています。

Internet Explorer 11におけるtitle属性

お断り:この記事はInternet Explorer Advent Calendar 2013、あるいはYet Another Internet Explorer Advent Calendar 2013のゲリラ投稿、ではありません。

Internet Explorer 9以降といえば、HTML5CSSSVGといったものへの対応が注目されがちですが、他のブラウザーが長い間対応してこなかった基礎的な部分への対応も進んでいます。この記事ではInternet Explorer 11(IE11)におけるtitle属性について書きます*1

title属性

HTMLにはtitle属性という謎の属性があります。多くのブラウザーではtitle属性を設定した要素にマウスを重ねると値をツールチップとして表示します。しかし、ほとんどのブラウザーは、キーボードだけを使ってtitle属性を表示する方法をユーザーに提供していません(ツールチップを表示する方法がありません)。

私が特に問題だと感じるのはinput要素などのフォームコントロールのtitle属性値が表示されない点です。フォームコントロールにはlabel要素を使ってラベルを設定しましょうと言われていますが、様々な理由でlabel要素を使うことが難しい場合には次善の策としてtitle属性を使うことがあります*2dequeが公開しているTechniques for Labeling Standard HTML Form Controlsにはlabe要素やtitle属性を含め、様々な状況におけるラベルづけのテクニックがまとめられています)。

Techniques for WCAG 2.0WCAG 2.0 実装方法集)にもH65: Using the title attribute to identify form controls when the label element cannot be usedH65: label要素を用いることができないとき、title属性を用いてフォーム・コントロールを特定する)があります。WAICが公開しているアクセシビリティ・サポーテッド(AS)情報を見ても、この実装方法が多くのスクリーン・リーダーによってサポートされていることがわかります。

スクリーン・リーダー以外でもブラウザーでマウスを使っている環境であれば、マウスをコントロールに重ねることでtitle属性がツールチップとして表示され、内容を確認することができます。しかし、ブラウザーはキーボードだけを使ってツールチップを表示する方法をユーザーに提供してきませんでした。これではコンテンツが情報を提供しても、キーボードだけを使っている(目の見える)ユーザーに情報を伝えることができません。WAICのAS情報にも次のように書かれています。

キーボード操作時も画面にツールチップが表示されるように、ブラウザの今後の機能向上に期待する。

また、UAAG 2.0のLast Call Working Draftにも2.1.1 Provide Full Keyboard Functionalityという達成基準がありますが、キーボード操作でtitle属性を表示できなければこの達成基準を満たすことはできないでしょう(私見)。

Internet Explorer 11

IE11ではマウス以外にもキーボードとタッチ操作でtitle属性をツールチップとして表示できるようになりました。キーボードを使っている場合には、キーボードフォーカスをあわせるとtitle属性値がツールチップとして表示されます(select要素では表示されません)。また、タッチ操作でも要素をタップしたまましばらく指を動かさないでいると、title属性値がツールチップとして表示されます。


図1:IE11で入力欄にキーボードフォーカスをあてるとtitle属性がツールチップとして表示される(AS情報を作成する際に必要となるテストファイルのH065-2を操作している例)

AS情報を作成する際に必要となるテストファイルに対する結果

WAICが公開しているAS情報を作成する際に必要となるテストファイル(のうち実装方法H65に関連したもの)をIE11で操作した結果は次の通りです。

H065-1: H65: label要素を用いることができないとき、title属性を用いてフォーム・コントロールを特定する(select要素)

  • マウスポインタをセレクトメニュー上に置いたとき、「検索範囲を選択」はツールチップとして表示されない
    • セレクトメニューを展開し、展開されたメニューにマウスポイントを置くとツールチップ表示される
  • キーボードフォーカスでセレクトメニューに移動させるが、ツールチップは表示されない
    • Alt+下向き矢印キーを押下してセレクトメニューを展開し、展開された項目を選択してツールチップは表示されない

H065-2: H65: label要素を用いることができないとき、title属性を用いてフォーム・コントロールを特定する(input要素)

  • マウスポインタを各テキストフィールド上に置いた際に、それぞれのtitle属性値「市外局番」、「市内局番」、「加入者番号」がツールチップとして表示される
  • Tabキーで各テキストフィールドにフォーカスを移動させた際に、それぞれのtitle属性値「市外局番」、「市内局番」、「加入者番号」がツールチップとして表示される

H065-3: H65: label要素を用いることができないとき、title属性を用いてフォーム・コントロールを特定する(input要素)

  • マウスポインタをテキストフィールド上に置いた際に、title属性値「検索キーワードを入力」がツールチップとして表示される
  • Tabキーでテキストフィールドにフォーカスを移動させた際に、title属性値「検索キーワードを入力」がツールチップとして表示される

テスト環境

今回テストした環境はWindows 8.1上のIE11です。別のOS(Windows 7など)ではまた違う結果になるかもしれません。

OS
Windows 8.1 (64bit)
ブラウザー
Internet Explorer 11.0.96000.16438 (32bit、デスクトップ版)

その他、気がついたことなど

AS情報を作成する際に必要となるテストファイル以外にもいくつかのファイルを試して、次のようなことに気がつきました。

  • input[type="text"]以外でもキーボードフォーカスがあたればtitle属性はツールチップとして表示される
    • ただし、select要素にキーボードフォーカスをあててもtitle属性は表示されない
  • abbr要素のようなキーボードフォーカースがあたらない要素のtitle属性を表示する方法は依然としてない
    • キャレットブラウズモード(F7で起動)でもフォーカスがあたっていない要素ではtitle属性は表示されない

おわりに

Internet Explorerツールチップというと過去には暗い時代もありましたが、IE11は現時点でもっとも対応が進んだブラウザーだと感じました。つまり、他のブラウザーベンダーも頑張れということです。

*1:この記事の内容に気が付いたのがIE11だったため「IE11」と記述していますが、それ以前のバージョンでも実はサポートしていたのかもしれません。その場合には気が付いた方が記事にしていただければと思います

*2:私はtitle属性を積極的に使うべきものだとは考えていません。label要素を使うことが難しい状況でまったく情報を提供しないよりは、title属性を提供したほうがまだ良い、と考えています

Mozilla FirefoxとWeb Developer ToolsでEasy Checks (第8回 アクセシビリティキャンプ東京に参加してみて)

第8回 アクセシビリティキャンプ東京は、W3Cが公開しているEasy Checksに沿って、実際にサイトをチェックしてみるという内容でした。Easy Checksはチェックツールではなく、チェックの観点と方法を説明しているドキュメントです。当日、対象となったサイトはクックパッドで、チェック結果の概要はたださんの「アクセシビリティキャンプ東京#8でクックパッドのアクセシビリティチェックをした」にまとまっています。

私がキャンプに参加して感じたことは、キャンプに参加したかたが、また別のかたにチェック方法を教えていったら良いなあということです。そこで、この記事ではMozilla FirefoxWeb Developer Toolsを組み合わせてチェックする方法について、簡単に述べたいと思います。内容はできる限りEasy Checksに合わせた、つもりです。また「メモ」として補足やキャンプ当日に出た話などを載せています。

1. ページタイトル

ページタイトルは次のように使われます。

  • ブラウザーによってはウィンドウのタイトルバーに表示されます
  • 複数のWebページを開いている時にブラウザーのタブに表示されます
  • 検索エンジンに表示されます
  • ブックマークやお気に入りに使われます
  • スクリーン・リーダーが(一般的には最初に)読み上げます

チェック内容

  • ページの内容を十分かつ簡潔に述べているタイトルがあること
  • サイト内の他のページと異なること、そして他のページと十分に区別できるタイトルであること

チェック方法

ブラウザーのタイトルバーを表示してチェックします。

Mozilla Firefoxではブラウザーウィンドウ上部の何もない場所を右クリックして「メニューバー」を選択することでタイトルバーを表示できます。また、Altキーを押してメニューバーを表示し、「表示」の「ツールバー」から「メニューバー」を選択することでタイトルバーを表示できます。

メモ

サイト全体が同じタイトルが同じでは、どの内容のページに移動したのか、ブックマークに登録したのか、などがわかりません。HTML5のtitle要素にも、次のようにあります。

Authors should use titles that identify their documents even when they are used out of context, for example in a user's history or bookmarks, or in search results.

2. 画像の代替テキスト

画像には代替テキストを設定します。代替テキストは画像を見ることができない人が使います。

  • 視覚障害でスクリーン・リーダーを使っている人
  • ネットワークスピードの向上や帯域の節約のために画像を無効にしている人

チェック内容

  • 全ての画像に適切な代替テキストがついているかどうか

チェック方法

Web Developer Toolsを使ってチェックします。

  • 「画像」から「画像を枠で囲う」、「alt属性値がない画像を枠で囲む」を選択
  • 「画像」から「alt属性値を表示」を選択


図:Web Developer Toolsで「画像」から「alt属性値を表示」を選択した画面(f:id:takenspc:20131104165117p

メモ

画像のダウンロードに失敗した場合にも代替テキストは使われます。

適切な代替テキストとは何か、という問題は、ここではいくつかのサイトを挙げてお茶を濁したいと思います。

3. 見出し

見出しは見出しとしてマークアップします。見出しとしてマークアップすることでページ内の移動にも使うことができます。

  • マウスを使えずキーボードだけを使っている人
  • スクリーン・リーダーを使っている人

見出しのレベルは論理的な階層構造を持つべきです。

  • 見出し1
    • 見出し2
      • 見出し3
    • 見出し2

チェック内容

  • 見出しが存在していること
  • 見出しのように見えるテキストが全て見出しとしてマークアップされていること
  • 見出しとしてマークアップされている全てのテキストが、本当にセクションの見出しであること
  • 見出しの構造が意味を持っていること(理想的にはページはh1から始まり、見出しレベルをスキップしないこと。ただしこの項目は絶対に必要というわけではない)

チェック方法

Web Developer Toolsを使ってチェックします。

  • 「情報」から「見出し(h要素)を表示」を選択
  • 「アウトライン」から「枠で囲う時はタグ名を表示」を選択し、再度「アウトライン」から「h要素を枠で囲う」を選択

メモ

  • スクリーン・リーダーには見出しごとにジャンプできるものが多くあります
  • Opera 12はSキーWキーで見出しごとにジャンプできます(シングルショートカット機能が有効な場合)
  • フィードリーダーでは見出し要素に専用のスタイルが設定されていることがあります
  • SafariFirefoxのリーダー・モードでも見出し要素には専用のスタイルが設定されます

4. コントラスト比(カラーコントラスト)

  • テキストと背景に十分なコントラストがないテキストを読めない人がいる
  • 高齢者を含めた弱視者には高いコントラスト(明るい背景に暗いテキストや暗い背景に明るいテキスト)が必要な人がいる
  • ディスレクシアのようなある種の識字障害では明るい色(高輝度)を読めない人がいる

ブラウザーはテキストの色と背景色を変更する機能をユーザーに提供するべきだし、Webページはユーザーが色を変えた時にも使える必要があります。

チェック内容

  • (通常の大きさの文字に対して)Webページは4.5:1のコントラスト比を持っていること

チェック方法

カラー・コントラスト・アナライザーを使ってチェックします。

カラー・コントラスト・アナライザーのスポイトツールでテキスト部分のピクセルと背景部分のピクセルを選択すると、コントラスト比が自動的に計算されます。


図:カラー・コントラスト・アナライザーでコントラスト比を測定している画面(f:id:takenspc:20131104170000p

メモ

基本的には、画像も含めテキストの色と背景色の組み合わせをすべてチェックします。

5. ズーム

  • Webページを拡大して読んでいる人たちがいる
  • フォントや行間などを変更する必要のある人もいる
  • 拡大機能は一般にはブラウザーの機能であり、Webページはズームしても動作するように設計する必要がある
  • メジャーなブラウザーは全て、ページズーム機能(フルズーム機能)を提供している
  • ブラウザーの中にはテキストズームを提供しているものもある(今のところMozilla FirefoxSafari)。可能ならテキストズームをチェックすべき

チェック内容

  • テキストズーム:全てのテキストが大きくなること
  • ページズーム:ページ内の全てが大きくなること
  • テキストが消えたり欠けたりしないこと
  • テキスト、画像や他のコンテンツが重なったりしないこと
  • ボタン、入力欄、他のフォームコントロールが視認できて、使えること

ズームした場合でも、1行が画面の中に納まって水平スクロールが発生しないことがベストプラクティスです。

チェック方法

ブラウザーのズーム機能を使ってチェックします。

Mozilla FirefoxではCtrl++で拡大、Ctrl+-で縮小することができます。Ctrlキーを押しながらマウスホイールを回転させることでも拡大・縮小できます。Ctrl+0でズームをリセットできます。

なお、Mozilla Firefoxではメニューバーを表示していないと、メニューからズーム機能を呼び出すことやテキストズームとページズームの切り替えなどを行うことができません。

6. キーボードアクセスと視覚的なフォーカス

マウスを使えずにキーボードを使っているページを操作している人もいます。

  • 視覚障害者
  • 目の見える運動機能障害者

いわゆるキーボードではなく、OSやブラウザーからはキーボードのように認識される入力デバイスを使うこともあります。ページのすべての機能はキーボードで操作できるべきだし、フォーカスは視覚的に見えて、論理的な順番で移動するように作ります。

チェック内容

全ての要素と順番

  • リンク、入力欄、ボタン、マルチメディアのコントロールを含めた全ての要素にtabキーでフォーカスを移動できること。移動できない場所に(マウスなどで)操作したり選択するものがないこと。
  • tabキーでフォーカスを移動した要素からtabキーでフォーカスを移動できること(よくある問題は、メディアコントロールからフォーカスを移動できなくなる場合)
  • tabキーを移動した順番が論理的な読み上げ順にそっていること(例えば、左から右に書く言語では上から下、左から右)
  • フォーカスがページの末尾で止まらないこと(ページの先頭に移動するか、ブラウザーのUIに当たった後ページに移動すること)

視覚的なフォーカス

  • フォーカスインジケーターが明確に見えていること(アウトラインやハイライトなど)
  • マウスホバーで発生する視覚的な変更(ハイライトなど)が全て、キーボードフォーカスでも発生すること

ドロップダウンリストと画像リンク

  • ドロップダウンリストにフォーカスをあわせた後、矢印キーで全ての項目に移動できること(よくある問題はナビゲーションとしてドロップダウンリストを使っていて、矢印キーを押した瞬間に移動してしまう場合)
  • リンクである画像にフォーカスを合わせた場合、明瞭な視覚的なフォーカスがあり、キーボードを使ってリンクを開けること

チェック方法

  • アドレスバーをクリックする(その後はマウスを使わない)
  • tabキーを押す
  • セレクトボックスやメニューバーでは矢印キーを押す
  • ドロップダウンリストの特定の項目を選択するにはEnterキースペースキーを押す

メモ

キーボードサポートはなぜ重要か

いわゆるキーボードではなく、OSやブラウザーからはキーボードのように認識される入力デバイスを使うこともある。

一時期流行したWiiリモコンを使ったPCで操作では、リモコンのボタンを特定のキー入力にマッピングすることが多く行われていました。キーボード操作をサポートすることは、キーボードと呼ばれているデバイス以外のデバイスにとっても重要です。

ブラウザーのフォーカスリングを見やすく

キャンプではブラウザーのフォーカスリングがそもそも見やすくない、という話がでました。Mozilla Firefoxではabout:configでフォーカスリングの設定を変更できます。

  • browser.display.focus_ring_on_anythingをtrueにして、入力欄やドロップダウンメニューにもフォーカスリングが表示されるようにする
  • browser.display.focus_ring_widthを3などにしてフォーカスリングを太くする

browser.display.focus_ring_widthでフォーカスリングを太くするとbutton要素の見た目が変わるため、私はユーザーCSSでフォーカスリングを見やすくすることの方が多いです。

@namespace url(http://www.w3.org/1999/xhtml);
@-moz-document url-prefix(http://),
               url-prefix(https://),
               url-prefix(file://) {
:focus {
  outline: medium dotted !important;
}
}

マウスで操作できてキーボードで操作できない要素

マウスでは操作できるけれど、キーボードフォーカスがあたらない要素を探すことは、ページの機能を知らないと難しい、という話も出ました。実際、そうだと思います。

完全なソリューションではありませんが、Google Chrome拡張機能Accessibility Developer Toolsにはフォーカスがあたらない要素にclickイベントハンドラーが設定されていると警告する機能があります。この機能は次のようにして使うことができます。

  1. Accessibility Developer Toolsをインストールした状態でデベロッパーツールを立ち上げ「Audits」パネル(監査)を開く

  2. 「Select audits to run」(実行する監査を選択)で「Accessibility」にチェックが入っていることを確認し「Run」(実行)を押す

  3. 監査が終わると結果が表示され、その中に「[Warning] Elements with onclick handlers must be focusable」項目([警告] onclickハンドラ―が設定されている要素はフォーカスがあたらなくてはならない)があれば、マウスでは操作できるがキーボードで操作できないオブジェクトがある可能性が高い
  4. 監査結果の項目はツリー上に開閉でき、イベントハンドラーが設定されている要素の一覧も表示


図:Accessibility Developer Toolsの監査(Audits)結果画面(f:id:takenspc:20131104162024p

7. フォーム

  • フォームコントロールにラベルが設定されていること
  • キーボードで操作できること
  • 明確な指示・説明がついていること
  • エラー処理がわかりやすいこと

チェック内容

キーボード

  • 全てのフォームコントロールがキーボードでアクセスできること

ラベル

  • label要素を使って全てのフォームコントロールにラベルが関連付けられていること(これはベストプラクティスだが必須ではない)
  • ラベルが正しい位置にあること。左から右に書く言語では、ラベルは通常、次の位置にある。
    • 入力欄とドロップダウンメニューでは左
    • ラジオボタンとチェックボックスでは右

必須入力欄とそのほかの説明文

  • 必須項目が明確にわかること
    • 必須かどうかインジケーターが色だけに依存していないこと
    • 必須項目であることがlabel要素(入力欄とドロップダウンメニュー)かlegend要素(ラジオボタンとチェックボックス)の中でマークアップされていること
  • フォームを記入するために使う説明文が、必要となるコントロールの前に書かれていること
    • 一般的な説明文は関連するフォームの前かセクションの前に書かれていること
    • 入力フォーマットはlabel要素に書かれていること

エラー処理

  • エラー処理がありそうなフォームで、必須項目を空にしたり、間違った書式で入力したまま送信する。エラーが表示された場合は、エラーが次を満たしていること
    • ユーザーが理解できエラーを修正できる明確なメッセージが提供されていること(フォーマットが決まっている項目には、正しいフォーマットが説明されていること、など)
    • エラーが容易に発見できること(通常はフォームの前にエラーを置くのがベスト)
    • エラーが起きなかったコントロールが入力済のままになっていること(これはベストプラクティスですが必須ではない)

チェック方法

Easy ChecksではMozilla Firefoxを使った簡単なチェック方法はないと書かれていますが、Web Developer Toolsを使ったチェック方法をいくつかか紹介します。

  • 「フォーム」から「ラベルが指定されていないフィールドを枠で囲う」を選択
  • 「アウトライン」から「任意の要素を枠で囲う」を選択して、表示されたダイアログにlabel入力(label要素が枠で囲まれる)
    • ラベルをクリックしてコントロールにフォーカスが移動するかチェック
  • フォームを空もしくは適当に入力した状態で送信して、表示されるエラーメッセージを確認する


図:Web Developer Toolsで「フォーム」から「ラベルが指定されていないフィールドを枠で囲う」を選択した画面(f:id:takenspc:20131104165306p

メモ

必須かどうかインジケーターが色だけに依存していないこと

必須項目であることが色だけに依存している例としては「赤字の項目は入力必須です」などがあります。色だけに依存している場合、視覚障害のユーザーが判断できなかったり、(カラーでない)電子ペーパーを使っているユーザーにも判断できないかもしれません。

フォームを記入するために使う説明文が、必要になる前に書かれていること

コントロールの後ろに入力を終えてからフォーマットの説明がくると、そのフォーマットで書いていなかったユーザーは入力をやり直さなくてはなりません。例えば、説明文は画面外に出ていて気が付かなかったが、入力欄は画面内にあったので、制作者の意図とは違うフォーマットで入力した場合や、スクリーン・リーダーを使っていて、説明文が読み上げられる前に入力欄が読み上げられたので、制作者の意図とは違うフォーマットで入力した、といった場面を想像してみてください。

8. マルチメディア(ビデオとオーディオ)の代替コンテンツ

(略)

9. プレーンコンテントビュー

  • Webページはマルチカラムや色などを使ってデザインされていることが多いが、全ての人がそのようにページを見ているわけではない
  • スクリーン・リーダーを使って読み上げているかもしれないし、点字ディスプレイで読んでいるかもしれないし、マルチカラムを1カラムにしたり、テキストサイズなどを変更して読んでいるかもしれない
  • ページのプレゼンテーション(表現)を変えた際のアクセシビリティのバリアについて気づくために、プレーンコンテントビューでページを見てみる

画像とスタイルを無効にしてページをリニアライズした状態のことをEasy Checksではプレーンコンテントビューと言っています。

チェック項目

  • プレーンコンテントビューで表示されている順に読んで情報がわかること(見出しが見出しの内容の直前に来ている、など。ただしデータテーブルは除く)
  • 代替テキストが画像と等しい情報を提供していること
  • 情報のまとまりに明確な見出しがついていること

チェック方法

  • 画像を無効にして代替テキストを表示する(「画像」から「画像を無効化する」、「全ての画像」を選択)
  • CSSを無効にする(「CSS」から「CSSの無効化」、「全てのCSSを無効化」を選択)
  • ページもしくは表をリニアライズする(「その他」から「リニアライズ(線形化)する」を選択)

メモ

リニアライズはHTMLに記述された順番に要素を表示することです。テーブルレイアウトでの問題を考えるとわかりやすいです。

<table>
  <tbody>
    <tr>
      <td>ナビゲーション</td>
      <td>メインコンテンツ</td>
    </tr>
    <tr>
      <td>ナビゲーションの続き</td>
      <td>メインコンテンツの続き</td>
    </tr>
  </tbody>
</table>

この場合、「ナビゲーション」の次に「ナビゲーションの続き」が来ること、「メインコンテンツ」の次に「メインコンテンツの続き」が来ることが意味的に正しいとします。しかし、リニアライズをすると「ナビゲーション」、「メインコンテンツ」、「ナビゲーションの続き」、「メインコンテンツの続き」の順になってしまい、意味が通らなくなってしまいます。

ただし、データを表として表現している場所では、リニアライズしたときに意味が通じるようにする必要はありません(スクリーン・リーダーもサポートしています)。

<table>
  <thead>
    <tr>
      <th>日付</th>
      <th>最高気温</th>
    </tr>
  <tbody>
    <tr>
      <td>8月1日</td>
      <td>32℃</td>
    </tr>
    <tr>
      <td>8月2日</td>
      <td>35℃</td>
    </tr>
  </tbody>
</table>

その他

Web Developer Toolsはキーボードショートカットを使って機能の有効・無効を切り替えることができます。

  1. 「設定」から「設定」を選択し、「Web Developerオプション」ダイアログを開く
  2. 「キーボード」タブを開き、「追加」ボタンをクリックして、「オプション」ダイアログを開く
  3. 「オプション」ダイアログで、「機能」プルダウンメニューで切り替えたい機能、「キーボード」でショートカットキーを設定
  4. Mozilla Firefoxを再起動


図:キーボードショットカットを設定する「オプション」ダイアログ(f:id:takenspc:20131104162127p

IE11とPer Monitor DPI

Windows 8.1になって、モニターごとにDPIを設定できるようになりました。といっても、あるモニターにXdpi、別のモニターにはYdpiという指定はできないようです。Windows 8.1では「すべての項目のサイズを変更する」に設けられた「小さくする」から「大きくする」を大雑把に選ぶスライダーで、DPIを設定するようになりました(図1)。この設定を変更するとシステムが自動的にモニターごとにDPIを割り当てます。


図1:Windows 8.1の「すべての項目のサイズを変更する」(DPIの設定)

私は1920×1080のモニターを持ったノートPCに、1980×1080の外部モニターをつないで使っていますが、Windows 8.1にしたところノートPCのモニターは120dpi(125%)、外部モニターは96dpi(100%)という設定になりました。

さて、Windows 8.1のIE11はPer Monitor DPIに対応しており、ウィンドウが存在するモニターのDPI設定が反映されます。具体的にはデフォルトのズーム倍率に表れます。例えば、96dpiのモニターにIE11のウィンドウが表示されている場合では、デフォルトのズーム倍率は100%ですが、120dpiのモニターに移動すると125%になります。試していませんが、144dpiのモニターに移動すると150%に変化するはずです。気になるのは複数のモニターにまたがったウィンドウがどうなるのかということですが、手元で試した限り*1では、ウィンドウの領域がもっとも多く存在しているモニターのDPIが使われるようです。

これにより、DPIが違うモニターを使っている環境では、IE11でRWDなサイトを閲覧しているときにウィンドウを別のモニターに動かすとレイアウトが変わる、ということが起こりえます。

実際に、マウリッツハイス美術館展のサイトIE11で表示したときのスクリーンショットを示します。図2では、IE11のウィンドウ(の領域の半分以上)は96dpiのモニターにいます。この時のデフォルトのズーム倍率は100%で、PCなどでの閲覧を意識したレイアウトになっています。図3では120dpiのモニターに移動しています。単にウインドウを移動させただけですが、120dpiのモニターに移動したIE11のデフォルトのズーム倍率は125%に変化しました。この結果、画面はスマートフォンなどでの閲覧を意識したレイアウトに変わりました。


図2:96dpiのモニター上のIE11マウリッツハイス美術館展のサイトを表示(f:id:takenspc:20131022003546p


図3:120dpiのモニター上のIE11マウリッツハイス美術館展のサイトを表示(f:id:takenspc:20131022003537p)

さすがに最近では、マウリッツハイス美術館展のサイトのようにドラスティックにレイアウトが変わるサイトは多くないでしょうが、注意したいところです。

*1:モニターを左右に並べて、ウィンドウを行ったり来たりしてどうなるかを試しました

リンクかボタンかそれ以外か

あるアクションを引き起こす「モノ」を「リンク」とするか「ボタン」とするかは、何を基準に判断すればよいのでしょうか。ここでは最近の私の解釈を書きます。

最近の私の解釈

最近の私の解釈は「アクションが、ページの遷移かフォーカスの移動を発生させるものはリンク、そうでなければボタン」というものです。この解釈はWAI-ARIA 1.0のある注記がきっかけになっています。

WAI-ARIA 1.0

WAI-ARIA 1.0 (2011年1月18日勧告候補)にはlinkロールbuttonロールがそれぞれ用意されています。中でもlinkロールには私の解釈の直接のきっかけとなった注記があります。

Note: If pressing the link triggers an action but does not change browser focus or page location, authors are advised to consider using the button role instead of the link role.

参考までに訳すと次のようになるでしょうか。

注:もしリンクの押下が、アクションは引き起こすものの、ブラウザーのフォーカスを変えずページのロケーションを変更しないならば、著者はlinkロールの代わりにbuttonロールの使用を検討されたし。

clickイベントのキャンセル

もう1つ考えたことはリンクのclickイベントです。

a要素でマークアップしたリンクをクリックなどするとページ遷移もしくはページ内遷移が発生します(リソースがダウンロードされる場合を考慮しない場合)。これをHTML5風にいうと、a要素のactivation behaviorが実行された、ということになります。

この時、a要素のclickイベントをキャンセルすると、activation behaviorは実行されません。ここで考えたのは、リンクの通常のactivation behaviorを実行すると機能的に破たんするものは、リンクといえるだろうか、ということです*1

ということで、リンクのactivation behaviorを実行しても(clickイベントをキャンセルしなくても)機能的に破たんしないものをリンク、そうでないものはボタンと解釈しています。

解釈の例

解釈は言葉だけでは意味を持ちませんので、いくつかの例を解釈してみます。

送信ボタン

私の解釈がうまく当てはまらないのが送信ボタンです。送信ボタンはページの遷移やフォーカスの移動を発生させますが、ボタンです。私の解釈も所詮は解釈ですので、私も送信ボタンはボタンだと考えています。後付けの解釈よりもHTMLのセマンティクスを優先すべきだと考えています。

送信ボタンはボタンです。

モーダルダイアログを開くリンク

モーダルダイアログを開くモノはリンク、と解釈します。

一般に、ユーザーがモーダルダイアログを開くと、フォーカスはモーダルダイアログの中に移動します。例えば、ファイルを選択するダイアログはモーダルであることが一般的です。Windowsのファイルを選択するダイアログを開くと、フォーカスはダイアログの中に移動し、ダイアログを閉じるまでフォーカスをダイアログの外に移動することはできません*2

このように、フォーカスが移動するので、モーダルダイアログを開く「モノ」はリンクと解釈します。

他にもフォーカストラップが発生するモノを開くモノは、リンクと解釈します。例えばカスタム日付ピッカーを開くモノもリンクだと解釈します。

コンテンツの一部の表示・非表示を制御するボタン

summary要素のように、コンテンツの一部の表示・非表示だけを制御するモノは、ボタンと解釈します。

details要素とsummary要素を使えば良いわけですが、構造上details要素を置けないなどの理由により、自分で同様のインタフェースを実装することがあります。このような場合に、コンテンツの表示・非表示を切り替えるモノはボタンと解釈します。コンテンツの表示・非表示だけを切り替えても、フォーカスは、通常、移動しないからです。

HTML to Platform Accessibility APIs Implementation Guide(2013年10月1日草案)でも、summary要素はbuttonロールにマッピングすることが検討されています。

アコーディオン

アコーディオンは、コンテンツとヘッダーからなるパネルが複数ならび、ヘッダーを操作することでコンテンツの表示・非表示を切り替えるインタフェースです。コンテンツの開閉を行うヘッダー部分は何になるかというと、タブ(tabロール)だそうです。

WAI-ARIA 1.0 Authoring Practices(2013年3月7日草案)のAccordion Design Patternでは、アコーディオンは(複数のタブを選択できる)タブリストとして実装する、とされています。

WAI-ARIA 1.0 Authoring Practicesでは、よくある1つのパネルを開くと他のパネルが閉じるインタフェースはアコーディオンとは言わないようです。タブを1つだけ選択可能なモノは、普通のタブリストと言うのでしょう。言葉の使い分けを厳密に行うかはさておき、アコーディオンのヘッダー部分はタブとして実装することになるようです。

タブリストのタブ

タブリストの中にあるタブはタブ(tabロール)です。WAI-ARIA 1.0 Authoring Practices(2013年3月7日草案)のTab Panel Design Patternを参照してください。

マークアップの例

これまでの解釈をもとにしたマークアップの例をいくつか挙げます。

  • 基本的にパクりです
  • 見出しにあたる要素はすべてh3要素を使っていますが特に意味はありません
  • WAI-ARIAに関連する属性はJavaScriptで動的に追加する想定です

リンク

<a href="#foo">リンク</a>

ボタン

<button type="button">ボタン</button>

button要素のtype属性を省略しても、関連付けられたform要素(form owner)がなければ送信ボタンとしては機能しない(activation behaviorは結果的に何もしないと同じになる)わけですが、最近はtype属性をつける派に傾いています。

<a href="#" role="button">ボタン?</a>

hrf属性をもつa要素にrole="button"を指定するのはHTML5やHTML 5.1 Nightlyでは認められていません。厳しいですね…。

href属性をもたないa要素にrole="button"とすることはできます。ただ、私にはメリットが感じられません。

<a role="button" tabindex="0">ボタン</a>

送信ボタン

<button>送信</button>
<input type="image" alt="送信" src="foo.png">
<input type="submit" value="送信">

input要素は、type="image"の場合はalt属性、type="submit"の場合はvalue属性を使って名前を与えます。HTML5などにはtype="image"の場合、value属性は省略しなくてはならないとひっそり書いてあり注意が必要です。厳しいですね…。

モーダルダイアログを開くリンク

<a href="#dialog1" aria-controls="dialog1"
   aria-expanded="false">ダイアログを開く</a>
<div role="dialog"
     id="dialog1"
     aria-labelledby="dialog1-heading"
     aria-expanded="false">
    <h3 id="dialog1-heading">ダイアログの名前</h3>
</div>

WAI-ARIA 1.0ではコンテンツ側がダイアログに名前を与えるべきとあるので、aria-labelledby属性を使っています。名前を与えるのにaria-labelledby属性を使うかどうかはコンテンツ次第だと思います。

aria-expanded属性は、aria-controls属性が設定されている場合はaria-controls属性が指している要素の開閉情報を、設定されていない場合はその要素自身の開閉状態を表現します。

コンテンツの一部の表示・非表示を制御するボタン

<div>
    <h3><button type="button"
                aria-controls="panel"
                aria-expanded="false">見出し1<span>開く</span></button></h3>
    <div id="panel" aria-expanded="false">コンテンツコンテンツ</div>
</div>

見出しの中にbutton要素があるのは気持ち悪いかもしれません。ただ、ボタンの名前を明確にしようとすると、見出しテキストと操作(開く、閉じる)をbutton要素の中に入れる形になると思います。見出しの外にbutton要素をもってきた場合にはaria-labelledby属性などを使ってボタンの名前を明確にする方が私の好みです。これも、ボタンの名前が冗長すぎるかもしれないとも思っています。

<div>
    <h3 id="panel1-heading">見出し1</h3>
    <button type="button"
            id="panel1-button"
            aria-labelledby="panel1-heading panel1-button"
            aria-controls="panel1"
            aria-expanded="false">開く</button>
    <div id="panel1" aria-expanded="false">コンテンツコンテンツ</div>
</div>

アコーディオン

WAI-ARIA 1.0 Authoring Practices(2013年3月7日草案)のAccordion Design Patternを割と素直に実装した例です。OpenAjax Allianceの例とjQuery UIを参考にしています。

具体的な例は次の通りです。

<div role="tablist" aria-multiselectable="true">
    <h3 role="tab" tabindex="0"
        id="panel1-heading"
        aria-controls="panel1"
        aria-selected="true"
        aria-expanded="true">見出し1<span>閉じる</span></h3>
    <div id="panel1"
         aria-labelledby="panel1-heading"
         aria-hidden="false"
         aria-expanded="true">コンテンツコンテンツ</div>
    <h3 role="tab" tabindex="0"
        id="panel2-heading"
        aria-controls="panel2"
        aria-selected="false"
        aria-expanded="false">見出し2<span>開く</span></h3>
    <div id="panel2"
         aria-labelledby="panel2-heading"
         aria-hidden="true"
         aria-expanded="false">コンテンツコンテンツ</div>
</div>

tablistロールはtabロールを所有するため、アコーディオンのコンテナ(tablistロール)の直下にtabロールが来るようにしています。tabpanelロールもtablistロールの直下に来ていますが、WAI-ARIA 1.0 Authoring Practices(2013年3月7日草案)のAccordion Design PatternにはContained within the tablist is a set of tab/tabpanel pairs.とあるので、きっと大丈夫なのでしょう。

見出し要素にtabロールを設定している理由は次の通りです。

タブ

WAI-ARIA 1.0 Authoring Practices(2013年3月7日草案)のTabpanel Design Patternを割と素直に実装した例です。OpenAjax Allianceの例とjQuery UIに加えて、A Rock n Roll Guide to HTML5 & ARIA (2013)を参考にしました。

すでにイディオムが確立していると言えますが、例を挙げておきます。

<ul role="tablist">
    <li role="presentation">
        <a role="tab" tabindex="0"
           id="panel1-tab"
           href="#panel1" aria-controls="panel1"
           aria-selected="true">タブ1</a></li>
    <li role="presentation">
        <a role="tab" tabindex="-1"
           id="panel2-tab"
           href="#panel2" aria-controls="panel2"
           aria-selected="false">タブ2</a></li>
</ul>
<div role="tabpanel"
     id="panel1"
     aria-labelledby="panel1-tab"
     aria-hidden="false">コンテンツコンテンツ</div>
<div role="tabpanel"
     id="panel2"
     aria-labelledby="panel2-tab"
     aria-hidden="true">コンテンツコンテンツ</div>

タブリストにul/li/a要素を使うイディオムは頻出します。

  • 素の状態(JavaScriptが無効な場合)を考えると、タブリストがTable of Contentsになっている
  • tablistロールの直下にはtabロールが来てほしいが、JavaScriptが無効な場合との一貫性を考えるとa要素が操作対象(tabロール)となるのが自然
    • li要素はrole="presentation"をつけてスキップ
    • a要素にはtabロールを設定できる

2つ目のa要素にtabindex="-1"を指定していますが、フォーカスの処理はJavaScriptで行う想定です。

もともとのリンクかボタンかの話に戻ると、タブはリンクとしてマークアップされていますが、JavaScriptが有効な場合にタブをクリックしてもフォーカスは変化しません*3。あれれ…。role="tab"でタブはタブになりましたし、JavaScriptが無効な場合には遷移が発生するということで、見逃してください。

また、タブパネル群にul/li要素を使わなかった(例ではdiv要素を使っています)理由には次のものがあります。

  • li要素をtabpanelロールにした場合、ul要素(暗黙的にlistロール)の直下にlistitemロールでもgroupロールでもない要素が来てしまう
  • HTML5ではli要素にtabpanelロールは設定できない
  • タブリストとタブパネル群にul要素とli要素を使った場合、両者の対応関係が明示的になるという説(?)もあるが私は賛成できない

    • ul要素は順序のないリストであり、2つのリストのn番目の項目同士が対応していることは明らかではない
    • 表示されていないタブパネルにはaria-hiddenを設定するので、支援技術から見えるタブパネルは1個であり、常に全て見えているタブの個数とは対応しない
  • HTML5(2013年8月6日勧告候補)のImplicit ARIA Semantics

おわりに

話が発散してしまいましたが、最近、私は「アクションが、ページの遷移かフォーカスの移動を発生させるものはリンク、そうでなければボタン」という解釈をしています。そして、その解釈を厳密に適用するのは難しい、という話でした。

*1:実際にはリンクを実行したときにスクロールが起きないように、といった理由でclickイベントをキャンセルすることも多いわけですが…

*2:ファイル選択コントロール(input[type=file])もモーダルダイアログを開きますが、強いていえばボタンだと思います。

*3:タブを切り替えた直後にタブパネルにフォーカスを移動させると、タブを順番に切り替えようとしているユーザーが混乱すると思います。特にキーボードでタブを切り替えようとしているユーザーは現在のタブから2つ以上離れたタブに切り替えることが難しくなると思います。

BandersnatchとPandocの話

Bandersnatchは便利ですねという話とBandersnatchを見て知ったPandocの機能について書きます。

Bandersnatch

BandersnatchはMarkdownファイルをReveal.jsを使った格好いいスライドに変換するツールです。

使い方

GitHubプロジェクトに非常にわかりやすい導入方法があるのでそちらを参照しましょう。一応、こちらにも書いておきます。

  1. gitクライアントをインストールする
  2. PandocとNode.jsをインストールしてパスを通しておく
  3. リポジトリをクローン(git clone https://github.com/sansyo/bandersnatch.git sample)する
  4. sampleディレクトリでnpm installする
  5. sample/source/slides.mdを編集する
  6. sampleディレクトリでgruntを実行する

これだけでReveal.jsを使ったスライドができあがりす。一度npm installを済ませれば、あとはMarkdownの編集(とgrunt)するだけでスライドを更新できるのでとても楽です。

Pandoc

Bandersnatchでは、MarkdownからHTMLへの変換にPandoc(のコマンドラインツール、pandoc)を使っています。Bandersnatchの魔法はPandocが支えています(もちろんgruntも)。

PandocはMarkdownやHTMLなど、いろいろなファイルを別のフォーマットに変換するツールです。もちろんMarkdownもサポートしていますし、Markdownに対する拡張もいくつか追加されています。これらの拡張は最初から有効になっているものもありますし、pandocコマンドのオプションで有効・無効を切り替えることもできます。Bandersnatchではこれらの機能を活用してMarkdownからReveal.js用のHTMLを書き出しています。

--section-divs

--section-divsは見出しの構造をもとに、章や節を自動的にdiv要素やsection要素でくくる機能です。

たとえば、次のようなMarkdownファイルがあるとします。

# 見出し1

あああ

## 見出し2-1

いいい

### 見出し3

ううう

## 見出し2-2

えええ

このMarkdownからdiv要素でくくったHTMLを書き出すには以下のようにpandocコマンドを呼び出します。

pandoc --section-divs source.md

出力結果は次のようになります(視覚的にわかりやすいようにインデントを入れています)。

<div id="見出し1" class="section level1">
    <h1>見出し1</h1>
    <p>あああ</p>
    <div id="見出し2-1" class="section level2">
        <h2>見出し2-1</h2>
        <p>いいい</p>
        <div id="見出し3" class="section level3">
            <h3>見出し3</h3>
            <p>ううう</p>
        </div>
    </div>
    <div id="見出し2-2" class="section level2">
        <h2>見出し2-2</h2>
        <p>えええ</p>
    </div>
</div>

HTML5で出力する(-t html5オプション)とdiv要素ではなくsection要素でくくるようにになります。

pandoc -t html5 --section-divs source.md

出力結果は次のようになります(やはり、視覚的にわかりやすいようにインデントを入れています)。

<section id="見出し1" class="level1">
    <h1>見出し1</h1>
    <p>あああ</p>
    <section id="見出し2-1" class="level2">
        <h2>見出し2-1</h2>
        <p>いいい</p>
        <section id="見出し3" class="level3">
            <h3>見出し3</h3>
            <p>ううう</p>
        </section>
    </section>
    <section id="見出し2-2" class="level2">
        <h2>見出し2-2</h2>
        <p>えええ</p>
    </section>
</section>

(ただ、機械的に生成したsection要素が意味的に整合している場合は限られるかもしれません。)

また、機械的に生成されたid属性が気になる場合には、id属性を機械生成する拡張機能、auto_identifiersを無効にします。拡張機能の有効・無効もコマンドラインのオプションで設定できます。-f markdown(入力フォーマットはMarkdownという指定)の後ろに、有効する拡張機能+拡張機能形式、無効にする拡張機能-拡張機能形式で記述します。

auto_identifiersを無効にした場合のpandocコマンドは次のようになります。

pandoc -f markdown-auto_identifiers -t html5 --section-divs source.md

一応、id属性なしの出力結果も挙げておきます(やはり視覚的にわかりやすいようにインデントを入れています)。

<section class="level1">
    <h1>見出し1</h1>
    <p>あああ</p>
    <section class="level2">
        <h2>見出し2-1</h2>
        <p>いいい</p>
        <section class="level3">
            <h3>見出し3</h3>
            <p>ううう</p>
        </section>
    </section>
    <section class="level2">
        <h2>見出し2-2</h2>
        <p>えええ</p>
    </section>
</section>

テンプレート

Pandocでは、Markdownから生成されたHTMLを、テンプレートの中に入れて書き出すこともできます。

HTMLのテンプレートの例はたとえば次のようになります。Markdownから生成されたHTMLが入る場所には$body$と記述します。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>タイトルの指定方法はあとでやります</title>
</head>
<body>
<!-- ほげほげ -->
$body$
<!-- ふがふが -->
</body>
</html>

pandocコマンドで--template テンプレートファイルオプションを使うと、Markdownから生成したHTMLを、テンプレートに組み込んで出力することができます。

pandoc -t html5 --section-divs --template template.html source.md

出力結果も次に挙げます。$body$が記述されていた場所にMarkdownから生成されたHTMLが入っています。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>タイトルの指定方法はあとでやります</title>
</head>
<body>
<!-- ほげほげ -->
<section id="見出し1" class="level1">
<h1>見出し1</h1>
<p>あああ</p>
<section id="見出し2-1" class="level2">
<h2>見出し2-1</h2>
<p>いいい</p>
<section id="見出し3" class="level3">
<h3>見出し3</h3>
<p>ううう</p>
</section>
</section>
<section id="見出し2-2" class="level2">
<h2>見出し2-2</h2>
<p>えええ</p>
</section>
</section>
<!-- ふがふが -->
</body>
</html>

テンプレートではページのタイトルや著者、日付を参照することもできます(pandoc_title_block拡張機能(最初から有効))。Markdownファイルの先頭に、次のように「%」から始まる行を書くと、自動的にタイトル、著者や日付と認識され、テンプレートから変数として参照することができます。

% タイトル
% 著者1; 著者2; 著者3
% 2013年1月1日

参照する例を次に挙げます。

<h1>$title%</h1><!-- <h1>タイトル</h1> -->
<ol>
$for(author)$
<li>$author$</li><!-- <li>著者1</li><li>著者2</li>… -->
$endfor$
</ol>
<p>$date$</p><!-- <p>2013年1月1日</p> -->

まとめ

  • Bandersnatchを使うとReveal.jsを使ったスライドを簡単に作ることができる
  • Pandocには様々な機能があり、Bandersnatchはそれらを有効活用している

Firefox OSでWeb Speech APIを使う

Gecko勉強会の懇親会でGeckoのWeb Speech APIまわりというライトニングトークをしました。

この記事ではライトニングトークではしゃべらなかったこと、Firefox OSでWeb Speech APIを試す方法を書きます。Web Speech API音声認識をしたり、音声合成をするためのAPIです。W3CSpeech API Community Groupで議論されています。このうちFirefox OSでは音声合成をするAPI(Speech Synthesis)がそれなりに使えます(デフォルトでは無効化されています)。

準備

Firefox OSをビルドします(MDNの文書)。私はmasterしかビルドしかことがありませんが、ソースコードを見る限りv1.2でも大丈夫そうです。

ビルドできたら、adbを使ってWeb Speech APIの設定を有効化します。

まず、設定ファイル(prefs.js)を落としてきます。

adb pull  /data/b2g/mozilla/(プロファイル名)/prefs.js

prefs.jsにuser_prefs("media.webspeech.synth.enabled", true);を追加して、設定ファイルをアップロードします。

adb push prefs.js  /data/b2g/mozilla/(プロファイル名)/prefs.js

試してみる

Firefox OSが使っている音声合成ライブラリはPicoTTSです。これはAndroidの標準の音声合成エンジンで英語などに対応していますが、残念ながら日本語には対応していません。それでも以下のようなコードを書けば、手軽に音声合成を試すことができます。

speechSynthesis.speak(new SpeechSynthesisUtterance('Hello World'));

またMozillaEitan Isaacsonさんが作成したhttp://eeejay.github.io/webspeechdemos/ デモページで試すこともできます。

Firefox OSのスクリーンリーダーとの関係

Firefox OSのスクリーンリーダーも、音声合成部分はWeb Speech APIを使っています。現在のmaster(v1.2でも?)では、設定アプリの開発者向け設定からスクリーンリーダーを有効にすることもできます。

  1. Settings
  2. DeviceをDevice informationを選択
  3. Device informationのMore informationを選択
  4. Developer settingsのDeveloperを選択
  5. AccessibilityのScreen Readerにチェックを入れる

Web Speech APIを有効にした状態では、スクリーンリーダーが音声で読み上げるようになります。が、Peakで試した限りでは音量が調整できませんでした。