意外と知らない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
が優れている点は、不可視になる(値がhidden
やcollapase
になる)と同時にアクセシビリティツリーからしっかり削除され、スクリーンリーダに読み上げられずタブフォーカスも当たらなくなるというところです1。display: none;
との違いは「表示領域が残るかどうか」以外違いはありません。
特に、値collapse
はテーブルなどで特定のセルや行だけを非表示にしたい場合などにも重宝します。display: none;
でも同じような表現になりますが、collapase
を利用する方法では表のサイズが再計算されないため、パフォーマンスの観点ではこちらのほうが優れています。
サンプルを用意しましたので、レンダリング結果の違いやタブフォーカスが当たるかどうかなどいろいろ試してみてください。
See the Pen visibility property example. by Hiroya Uga 🍣🍵 (@hiroya_uga) on CodePen.
さらにもう1つ特徴があります。visibility
はhidden
な要素の子孫にある特定の要素が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
のため、auto
→100px
などはアニメーションが起こりません。
ところが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でシェアをお願いいたします!笑
ここまで読んでくださりありがとうございました!少し早いですがよいお年をお迎えください( ˘ω˘ )🙏
それでは!👋👋
1:opacity
とvisibility
のどちらを使うか考えることも大切ですが一緒に使うパターンも少なくありません。