意外と知らないvisibilityの活用方法!

リードUI開発者 宇賀

この記事はミツエーリンクスアドベントカレンダー2019 - Qiitaの14日目の記事です。

みなさんお久しぶりです。7月ぶりの宇賀です🍣🍵!

いよいよ当社でもアドベントカレンダー🎄...感慨深いですね。さて、私のネタはCSSプロパティ「visibility」についてのご紹介です👀。

なぜvisibilityを選んだのか?そりゃクリスマスといえば、サンタさんじゃないですか。サンタさんといえば目撃することが困難な存在...不可視...visibility...という...(こじつけ😇)

なんて冗談はさておき、さっそくvisibilityについてみていきましょう!🕺🕺🕺

visibilityプロパティとは

このプロパティは要素の可視・不可視を切り替えられるプロパティで、指定できるプロパティと効果は次の通りです。

効果
visible(default) 要素が可視状態になります。
hidden 要素が不可視状態になりますが、display: none;と異なり要素の領域は確保されたままになります。
collapse hidden同様要素が不可視になります。一部の条件下ではdisplay: none;同様要素の領域が失われます。

※もっと具体的に知りたい方はCSS 2.2の11.2 Visibility: the 'visibility' propertyなどをご覧ください。

visibility vs display vs opacity

ただ要素を見えなくするだけなら透明度を操作するopacityプロパティがあります。しかしそれよりもvisibilityが優れている点は、不可視になる(値がhiddencollapaseになる)と同時にアクセシビリティツリーからしっかり削除され、スクリーンリーダに読み上げられずタブフォーカスも当たらなくなるというところです1display: none;との違いは「表示領域が残るかどうか」以外違いはありません。

特に、値collapseはテーブルなどで特定のセルや行だけを非表示にしたい場合などにも重宝します。display: none;でも同じような表現になりますが、collapaseを利用する方法では表のサイズが再計算されないため、パフォーマンスの観点ではこちらのほうが優れています。

サンプルを用意しましたので、レンダリング結果の違いやタブフォーカスが当たるかどうかなどいろいろ試してみてください。

See the Pen visibility property example. by Hiroya Uga 🍣🍵 (@hiroya_uga) on CodePen.

さらにもう1つ特徴があります。visibilityhiddenな要素の子孫にある特定の要素がvisibleだった場合、その領域だけを可視状態にすることができます。

百聞は一見に如かず、こちらのマークアップとCSSをご覧ください。

See the Pen visibility property example by Hiroya Uga 🍣🍵 (@hiroya_uga) on CodePen.

hiddenの中にあるvisibleな要素だけが見える様子がお分かりいただけたと思います。この振る舞いはdisplayプロパティにはできないですね!

実はアニメーション可能なプロパティ

ここでまた別のCSSプロパティが登場します。transitionです。このプロパティは、CSSプロパティの値が別の値に変わるまでの変化の仕方が指定できるものです。

See the Pen transition property example by Hiroya Uga 🍣🍵 (@hiroya_uga) on CodePen.

このプロパティで値の遷移をアニメーションさせられるのは原則数値の変化のみです。

初期値を設定してあげてから、条件を変化(JavaScriptでクラスを付与する、マウスオーバーで:hover疑似クラスを有効化させるなど)させてアニメーションさせるのが主な活用方法ですから、widthプロパティの場合はデフォルトがautoのため、auto100pxなどはアニメーションが起こりません。

ところがvisibilityは値が数値でないにも関わらずtransitionでアニメーション可能なプロパティに指定されています。これが意外と便利ポイントです。

コンテンツの表示・非表示を切り替えたいようなケースで、要素を非表示にする際はアクセシビリティ的に、目に見えないだけではなく操作不能かつアクセシビリティツリーから削除されている状態にしなければなりません。height: 0;opacity: 0;で隠しているだけでは、中のコンテンツをスクリーンリーダが読んでしまったり、タブフォーカスが当たってしまいユーザーが混乱する恐れがあります。しかし、transitionプロパティはdisplay: none;と相性が悪い。JavaScriptで操作するCSS TransitionとCSSOMの関係という記事でもご紹介しましたが、「要素のdisplay: none;プロパティを外したとき」の直後はうまくtransitionが動作しません。

コンテンツを非表示にしたいときのアニメーションが終わった後にdisplay: none;を充てる、というのもJavaScriptの力なしには難しい。。。そこで、このvisibilityプロパティの出番です。

visibilityで簡単コンテンツの展開

positionプロパティによって浮いている要素がサイズ固定だったり、フェードインさせたい要素が装飾ではなく中にコンテンツがある場合などはとても便利です。

ツールチップ

「help」にフォーカスが当たったときにコンテンツを可視状態にするサンプルです。

※このサンプルは非アクセシブルなため、実用的なものを組むにはWAI-ARIA Authoring Practices 1.1の3.24 Tooltip Widgetを参照してみてください。

See the Pen Tooltip example by Hiroya Uga 🍣🍵 (@hiroya_uga) on CodePen.

ディスクロージャ

「開く・閉じる」が押下されたときにコンテンツを可視状態に切り替えるサンプルです。十分にアクセシビリティを考慮する場合は3.10 Disclosure (Show/Hide)を参照してみてください。

See the Pen Disclosure example by Hiroya Uga 🍣🍵 (@hiroya_uga) on CodePen.

まとめ

さて、いかがでしたでしょうか?🙌

偏見かもしれませんがvisibilityプロパティはあまり日の目を見ていない印象があります。使いどころによってはとても便利なので、transitionでコンテンツを表示したいような場面ではぜひ使ってみてください😉

一通り書いてみて、結局クリスマス感あったのはKVと途中無理やりひねり出したtransitionのサンプルくらいでしたね...😫笑
来年のミツエーアドベントカレンダーでは6日片柳11日八尾の記事を見習ってクリスマスを絡めたネタで書きたいと思います🎉🎉🎉

本記事が面白い!😆がんばった!💪と思った方はぜひSNSでシェアをお願いいたします!笑
ここまで読んでくださりありがとうございました!少し早いですがよいお年をお迎えください( ˘ω˘ )🙏

それでは!👋👋

1opacityvisibilityのどちらを使うか考えることも大切ですが一緒に使うパターンも少なくありません。