根掘り葉掘り聞く--要素が隠されていることを知っていますか?


ありふれたディスプレー
仲間たちはこのような質問をされたことがあると思います.一つの要素を隠すには、いくつの方法がありますか.従来、私たちは3つの方法display: noneopacity: 0visibility: hidden を持っています.display: noneの副作用に基づいて、すでに腐っていると言われている問題で、主に以下の欠点があります.
一、表示を切り替えるとreflow(還流)が発生し、repaint(再描画)が発生し、ページ内のreflowがある程度増加すると、cpuの使用率が高くなる.
二、要素に遷移アニメーションを設定できない、方位測定もできない(clientWidth,clientHeight,offsetWidth,offsetHeight,scrollWidth,scrollHeight,getBoundingClientRect()、getComputedStyle()を含む)
なぜなら、ブラウザはHTMLタグを解析してDOM Treeを生成し、CSSを解析してCSSOMを生成し、DOM TreeとCSSOMを合成してRender Treeを生成し、最後にRender Treeの情報レイアウトに基づいてインタフェースをレンダリングするが、display: noneの要素が設定されており、Render Treeには入れられず、もちろん遷移アニメーションもレンダリングできないからである.
三、これを用いて明示的な切り替えを設定すると、display: flexdisplay: gridと衝突して困る.
あなたは本当にopacityとvisibilityを知っていますか?
このように、エレメントの表示を設定する場合、opacityやvisibilityを使用するのがより良いようですが、opacity: 0visibility: hidden の2つには具体的な違いがあるのではないでしょうか.タイトルに根掘り葉掘りと書かれている以上、PKを数回通じてこの2つの具体的な違いを深く掘り下げてみましょう.
第1ラウンド:アニメーションアトリビュートあにめーしょんあとりびゅーと
一般的なアニメーション効果の中で、最も広く使われているのはフェードインとフェードアウトであるべきです.この場合、opacityはanimationに協力しなければなりません.visibilityという属性はアニメーションの移行を行うことができないので、アニメーションの移行を満たすには、2つの値の間に連続的な値、すなわち連続区間が存在しなければなりません.visibilityは明らかに満足していません.表示/非表示の2つの状態の間に中間状態は存在しないため、ブール非表示です.
第2ラウンド:サブエレメントの表現opacity: 0visibility: hidden の要素が設定されていますが、それらのサブ要素はどのような影響を受けますか?
まず、opacity属性は布団要素で継承できませんが、visibility属性は継承できます.詳細はCSS 3仕様opacityとvisibilityの属性紹介を参照してください.
次に、親要素がopacityを設定すると、子要素の最大透明度は親を超えることができません.つまり、親のopacityが0.5であると、子のopacityが1に設定されていても、実際の透明度は0.5*1=0.5になります.したがって、親の透明度が0である限り、子は再設定して表示することはできません.
しかし、visibilityの子は、親要素がvisibility: hiddenに設定されていても、visibility: visibleによって子要素が再設定されて表示される機会があります.
第3ラウンド:積層コンテキスト(Stacking Context)
HTMLの要素はすべて独自の積層レベルを持っていますが、場合によっては、要素は積層コンテキスト(次はSCで代用)を形成し、直接自身とサブ要素の積層レベルを「抜く」ことになります.要素間の異なる積層レベルは,それらが重なると,Z軸上で誰がより高いか,すなわち誰がユーザの目に近いかを決定する.
要素がSCを形成する場合については、MDNドキュメントの詳細を参照してください.このドキュメントでは、要素のopacity属性値が1未満の場合、SCが形成されることがわかります.次のコードを観察できます.

这种情况下,设置了绝对定位的绿色方块形成了SC,所以其层叠水平自然比红色方块高,所以此时我们看不到红色方块:

而当我们为红色方块设置了opacity属性后,比如:


このとき、緑色のブロックの上に赤いブロックが積層されます.赤いブロックのopacityは1未満でSCが形成され、両者ともz-indexが設定されていないため、同じ積層レベルに属するため、後進的に上位に位置する原則に従って、赤いブロックは図に示すように上に重なる.
同様に、opacityが0の要素でもSCが作成され、visibilityプロパティではSCは作成されず、要素の積層レベルにも影響しません.
長いこと言って、ある人は聞くかもしれませんが、要素が隠れている以上、見えないので、誰がそれを管理していますか?通常はそうですが、4回戦のPKを経て、この問題を無視できないことがあります.
第4ラウンド:インタラクティブ/アクセス可能
このラウンドでは、インタラクティブ/アクセス性を比較します.まずvisibility: hiddenと言います.この属性の要素が設定されており、バインドされたリスニングイベントはeventを無視します.targetは自身のイベントにトリガーされます.この言葉は拗ねていて、通俗的に言えば、この要素はサブ要素のイベントの泡を受信しますが、自分のイベントをトリガーすることはできません.このオンラインdemoでこの効果を体験することができます.
もちろん、自身のイベントをトリガーすることはできません.tabキーでアクセスすることはできません.つまりfocusはできません.また、スクリーン読書ソフトウェアがこの要素にアクセスできないなど、accessibilityを失うこともあります.
逆にopacity: 0が設定されている要素を見ると、以上の制限は全くありません.前のラウンドで提起された問題を無視できない理由を知っています.opacity: 0を設定した要素が見えなくても、クリックされてアクセスされ、予想外のバグが発生することがあります.
長所を取り入れ短所を補う.
両者にそれぞれの長所と短所がある以上、私たちはそれを結びつけて、長所と短所を補うことができますか?
答えはもちろんです.しかし、まず私たちが何を長くしたいのか、何を短くしたいのかを明確にしなければなりません.一般的には、要素がフェードアウトされたアニメーション効果を使用できるようにするだけでなく、消えた後にインタラクティブ/アクセス性を維持しないようにするのは簡単です.
.box {
  animation: fade 0.5s linear 0s forwards;
}
@keyframes fade {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
    visibility: hidden;
  }
}

私たちは依然としてopacityを使ってアニメーションの移行をしていますが、最後のアニメーションフレームでは、visibility: hiddenを加えると、私たちが望んでいる効果を達成することができます.このとき,要素がフェードアウトされると,意外にイベントがトリガーされることはない.また、opacityプロパティを使用してアニメーション効果を行う場合、ブラウザはこの要素をcomposite layer(合成層)に昇格させ、gpuを使用してハードウェア加速レンダリングを行い、両方の美しさを実現します.
もちろん、この要素がページの占有率を保持する必要がある場合は、そうすることはできません.
まとめ
要するに、アニメーションの必要性がない場合は、visibilityを使用して暗黙的に切り替えると便利ですが、アニメーションの必要性がある場合は、両方を組み合わせる方法が望ましいです.また、今後は、小さな知識点も深く分析し、表面にとどまらず、より系統的な認識を得ることを目的とした、根掘り葉掘りシリーズの文章が増えます.
ps:微信公衆番号に注目してください.フロントエンドローミングガイドは、定期的に良質なオリジナル文章と訳文を発表します.公衆番号に注目してください.