CSS表示プロパティの遷移


1448

私は現在、CSSの「メガドロップダウン」メニューを設計しています。基本的には通常のCSS専用のドロップダウンメニューですが、さまざまなタイプのコンテンツが含まれています。

現時点では、CSS 3の遷移は「display」プロパティは適用されないようです。つまり、display: noneからdisplay: block(または任意の組み合わせ)への遷移は一切実行できません。

上記の例の2段目のメニューを、誰かがトップレベルのメニュー項目の1つにカーソルを合わせたときに「フェードイン」する方法はありますか?

visibility:プロパティでトランジションを使用できることは承知していますが、それを効果的に使用する方法は考えられません。

私も高さを使用してみましたが、それはひどく失敗しました。

JavaScriptを使用してこれを達成するのは簡単なことでもありますが、CSSだけを使用するように自分自身に挑戦したかったので、少し不足していると思います。


CSSトランジションは、表示ではなくopacityプロパティに適用すると機能しますか?
ポールD.ウェイト

13
位置:絶対; 可視性:非表示; ディスプレイと同じ:なし。
ジャワド2012

8
@Jawad:z-index:0同様に何かを追加した場合のみ。
DanMan 2012年

7
@Jawad:スクリーンリーダーで読み取らせたい場合をvisibility: hidden除いて、使用しないことをお勧めします(通常のブラウザーでは読み取れません)。要素の可視性(と言っているように)を定義するだけであり、選択、クリックなど、以前の状態のままです。見えないだけです。opacity: 0
Forest Katsch 2013年

1
pointer-eventsIE 8、9、10ではサポートされていないため、常に問題があるわけではありません
Steven Pribilinskiy

回答:


1351

2つ以上のトランジションを連結することができvisibility、今回は便利です。

div {
  border: 1px solid #eee;
}
div > ul {
  visibility: hidden;
  opacity: 0;
  transition: visibility 0s, opacity 0.5s linear;
}
div:hover > ul {
  visibility: visible;
  opacity: 1;
}
<div>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
  </ul>
</div>

transitionプロパティのベンダープレフィックスを忘れないでください。)

詳細はこの記事にあります。


10
この答えは他の答えよりも作業が少ないようであり、display:none / block;から期待されるものを実現します。ありがとう。時間を大幅に節約できました。
ブレンダン

21
ええ、これの問題は、見えなくても、その背後にあるものが重なり合うことです。私はheight:0を使用する方がはるかに優れたソリューションであることがわかりました
Josh Bedo 2013

741
これはすばらしいですが、問題は、「非表示の表示」要素がまだスペースを占有しているのに対し、「何も表示しない」要素はスペースを占有していないことです。
Rui Marques

41
私はおそらく何かが足りないのですが、なぜ可視性と不透明度の両方を変更するのですか?不透明度を0に設定して要素を非表示にしない-なぜ可視性も非表示に設定する必要があるのですか?
GMA 2014

21
@GeorgeMillo不透明度のみを設定した場合、要素は実際にはまだページレンダリング上にあります(たとえば、[考え]をクリックすることはできません)。
adriendenat 14

800

これを機能させるには、他の方法で要素を非表示にする必要があります。

私は両方<div>のsを絶対的に配置し、非表示のものをopacity: 0

displayプロパティをからnoneに切り替えた場合block、他の要素での遷移は発生しません。

これを回避するには、要素を常ににすることを許可しますがdisplay: block、次のいずれかの方法を調整して要素を非表示にします。

  1. をに設定height0ます。
  2. をに設定opacity0ます。
  3. を持つ別の要素のフレームの外側に要素を配置しますoverflow: hidden

おそらく他にも解決策がありますが、要素をに切り替えた場合、遷移を実行できませんdisplay: none。たとえば、次のようなことを試してみてください。

div {
    display: none;
    transition: opacity 1s ease-out;
    opacity: 0;
}
div.active {
    opacity: 1;
    display: block;
}

しかし、それはうまくいきません。私の経験から、これは何もしないことがわかりました。

このため、常に要素を保持する必要display: blockがありますが、次のような方法で回避できます。

div {
    transition: opacity 1s ease-out;
    opacity: 0;
    height: 0;
    overflow: hidden;
}
div.active {
    opacity: 1;
    height: auto;
}

29
徹底的な回答をしてくれたジムに感謝します。display:プロパティがまったく変更された場合、すべてのトランジションが機能しなくなるという事実については、完全に正しいです。これは残念です。その背後にある理由は何でしょうか。余談ですが、元の質問で投稿したのと同じリンクで、私がどこにいるのかがわかります。私が持っている唯一の(小さな)問題は、ページが読み込まれるときにChrome [5.0.375.125]にあり、要素がページに読み込まれると、メニューがすぐに消えていくのがわかります。Firefox 4.0b2とSafari 5.0はまったく問題ありません...バグか何か見逃しましたか?
RichardTape 2010

7
これは正しいことであり、これに貢献することに同意します。将来の旅行者に向かいます。Chromeでvisibility:hidden; opacity:0; -webkit-transition: all .2s ease-in-out;有効な解決策を見つけましたが、iPhone 4で失敗することがわかりました。これが正しく移行しないだけでなく、ターゲット要素が表示されません。QAはあなた、私、そしてあなたのお母さんを失敗させます。
SimplGy

1
実際に可視性プロパティを移行することもできます。ただ言う
Cu7l4ss

2
非表示の状態をに設定してheight: 0;移行しないと、移行は機能しません。私はこれを不透明度を変えようとしてみました。私は削除する必要がありましたheight: 0;
chovy

10
本当にoverflow: hiddenありがとうございました!
thiagoh

279

この投稿の時点では、displayプロパティを変更しようとすると、すべての主要ブラウザでCSS遷移が無効になりますが、CSSアニメーションは引き続き正常に機能するため、回避策として使用できます。

例のコード(それに応じてメニューに適用できます)デモ

次のCSSをスタイルシートに追加します。

@-webkit-keyframes fadeIn {
    from { opacity: 0; }
      to { opacity: 1; }
}
@keyframes fadeIn {
    from { opacity: 0; }
      to { opacity: 1; }
}

次に、fadeInアニメーションを親ホバー(もちろんセットdisplay: block)の子に適用します。

.parent:hover .child {
    display: block;
    -webkit-animation: fadeIn 1s;
    animation: fadeIn 1s;
}

2019年更新-フェードアウトもサポートする方法:

(いくつかのJavaScriptコードが必要です)

// We need to keep track of faded in elements so we can apply fade out later in CSS
document.addEventListener('animationstart', function (e) {
  if (e.animationName === 'fade-in') {
      e.target.classList.add('did-fade-in');
  }
});

document.addEventListener('animationend', function (e) {
  if (e.animationName === 'fade-out') {
      e.target.classList.remove('did-fade-in');
   }
});
div {
    border: 5px solid;
    padding: 10px;
}

div:hover {
    border-color: red;
}

.parent .child {
  display: none;
}

.parent:hover .child {
  display: block;
  animation: fade-in 1s;
}

.parent:not(:hover) .child.did-fade-in {
  display: block;
  animation: fade-out 1s;
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes fade-out {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}
<div class="parent">
    Parent
    <div class="child">
        Child
    </div>
</div>


3
これをありがとう。上記のheight: 0トリック(トランジション用)は、フェードアウトトランジションで高さが0に設定されるため機能しないようですが、このトリックはうまく機能するようです。
Elliot Winkler

41
ありがとう、とても便利です。しかし、それをフェードアウトする方法は?
Illiou 2012年

1
この回答の最初の段落はあまり意味がありません。ブラウザは、displayプロパティを使用した瞬間にすべてのトランジションを完全に無効にするだけではありません-本当に理由はありません。そして、彼らそうしとしても、なぜアニメーションが機能するのでしょうか?displayCSSアニメーションでもこのプロパティを使用することはできません。
BoltClock

7
ベストアンサー。トランジションでは不可能ですが、アニメーションでは可能です。
ミケル

6
逆のアニメーションはどうですか、それは要素がゆっくりと消えるべき時です?
グリーン

77

私はと疑う理由遷移があれば無効になっていることがdisplay変更されたため、実際にはない表示するものです。スムーズにアニメーション化できると考えられるものは何も変更しませ

display: none; そして visibility: hidden; 2つのまったく異なるものです。
どちらも要素を非表示にする効果がありvisibility: hidden;ますが、それでもレイアウトにレンダリングされますが、目に見えるほどではありません。
非表示の要素は引き続きスペースを使用し、インラインまたはブロック、ブロックインライン、テーブル、またはdisplay要素がレンダリングするように指示するものとしてレンダリングされ、それに応じてスペースを使用します。
他の要素は、そのスペースを占めるように自動的に移動しませ。非表示の要素は、実際のピクセルを出力にレンダリングしません。

display: none 一方、実際には は要素が完全にレンダリングされるのを防ぎます
それは取りません任意のレイアウトスペースを。
要素がまったく存在しないかのように、この要素が占めるスペースの一部またはすべてを占有していた他の要素は、そのスペースを占有するように調整されます

display は単なる別の視覚的属性ではありません。
それは、そのようなことはありますかどうかなどの要素の全体のレンダリングモード、確立しblockinlineinline-blocktabletable-rowtable-celllist-item、または何を!
それぞれに非常に異なるレイアウトの影響があり、それらをアニメーション化したりスムーズに移行したりするための合理的な方法はありません(たとえば、blockからinlineまたはその逆へのスムーズな移行を想像してみてください!)。

表示が変更された場合遷移が(変更がへたりからであっても、無効になっている理由はここにあるnone- none!それは全くレンダリングを意味しないという独自の要素のレンダリングモードですが、単に不可視ではありません)。


8
上記の解決策と同様に、トランジションが表示属性に適用されない理由についての賢明な説明を得ることは非常に満足のいくものでした。
kqr 2014

8
同意しません。それは完全に理にかなっています。遷移の開始時にdisplay:noneからdisplay:blockまでが瞬時に発生した場合、それはすばらしいことです。そして、元に戻すために、遷移の終わりにdisplay:blockからdisplay:noneに進んだ場合、それは完璧です。
Curtis Yallop、2015年

2
ポイントから長方形へのアニメーションがどのように見えるか想像できない場合は、問題があります。スペースをまったく使用しない状態から長方形のスペースを使用する状態への移行は非常に明白です。たとえば、これまでのすべてのアプリケーションのように、マウスを使って長方形をドラッグするたびにこれを行います。この失敗の結果として、マックスハイトとネガティブマージンを含むハックが非常に多くなり、それはやり直しです。機能するのは、「実際の」高さをキャッシュし、JavaScriptを使用してゼロからキャッシュされた値までアニメーション化することだけです。悲しい。
Triynko 2017年

2
Tryniko:display:noneは、要素のサイズを0 x 0の長方形に変更しません-DOMから削除します。widthプロパティとheightプロパティをゼロにアニメーション化することにより、長方形からポイントにアニメーション化し、他の要素は「display:none」のようにその周りを流れますが、「display」属性は「block」のままです。要素はまだDOMにあります。display:blockとdisplay:noneの間のアニメーションのコンセプトはばかげています:中間状態はありません。要素は、それがどれほど小さくても見えなくても、DOMに存在するか存在しません。
Steve Thorpe

1
個別のプロパティをアニメーション化するのはばかげていません。のような個別displayのプロパティは、他のプロパティのようにスムーズに移行することはできませんが、タイミングが重要ではないという意味ではありません。からへの移行時期を制御できることは非常に重要です。@CurtisYallopが説明したように。私はから移行したい場合にし、その後、変更に私はそれを行うことができるはずです。disply:blockdisplay:noneopacity:1opacity:0display:blockdisplay:none
イェンス、

56

CSSには存在しないコールバックの代わりに、transition-delayプロパティを使用できます。

#selector {
    overflow: hidden; // Hide the element content, while height = 0
    height: 0; opacity: 0;
    transition: height 0ms 400ms, opacity 400ms 0ms;
}
#selector.visible {
    height: auto; opacity: 1;
    transition: height 0ms 0ms, opacity 600ms 0ms;
}

それで、ここで何が起こっているのですか?

  1. 場合visibleクラスが追加、双方れるheightopacity(0ミリ秒)遅延なくアニメーションを開始、しかしheight(の等価完全アニメーションに0ミリ秒を要するdisplay: block)とopacity600ミリ秒を要します。

  2. 場合visibleクラスが除去され、opacity(0ミリ秒、400ミリ秒の持続時間を遅らせる)アニメーションを開始し、そして高さが瞬時にのみ、その後400ミリ秒待機し(0ミリ秒)(同等の初期値を復元するdisplay: noneアニメーションコールバックで)。

この方法は、を使用する方法よりも優れていvisibilityます。このような場合でも、要素はページ上のスペースを占有し、常に適切であるとは限りません。

その他の例については、この記事を参照してください


8
これにはこれ以上の投票がないことに驚きました-この賢い解決策は何とか完璧に機能します。
ファンファーレ

3
height:100%場合によっては、レイアウトが破壊される可能性がある場合にのみ機能します。それが問題でなければ、素晴らしい解決策です。数少ない双方向動作の1つ。
Fabian von Ellerts、2018年

これは素晴らしい!私の場合、フェードアウトアニメーションの時間をフェードイン時間と同じにしたかったので、さらに簡略化することができました。使用するのではなくtransition: height 0ms 0ms, opacity 600ms 0msではだけtransition-delay: 0sです。
Jacob Lockard

52

display 遷移が機能するプロパティの1つではありません。

トランジションを適用できるCSSプロパティのリストについては、アニメート可能なCSSプロパティを参照してください。それらがどのように補間されるかについては、CSS値と単位モジュールレベル4、結合値:補間、加算、および累積を参照してください。

CSS 3までは9.1にリストされていましたCSSからのプロパティ(警告ポップアップを閉じるだけ)

私も高さを使用してみましたが、それはひどく失敗しました。

前回これをしなければならなかったとき、max-height代わりにそれを使用しましたが、これはアニメート可能なプロパティです(多少のハックでしたが、うまくいきました)。ただし、複雑なページやローエンドのモバイルを使用するユーザーにとっては、非常に扱いにくいかもしれません。デバイス。


リンクがアニメート可能なプロパティセクションを直接指していない。
Andrew Lam

1
@AndrewLam修正済み。ありがとう。
robocat

34

これで、カスタムアニメーションをブロックプロパティに追加できます。

@keyframes showNav {
  from {opacity: 0;}
  to {opacity: 1;}
}
.subnav-is-opened .main-nav__secondary-nav {
  display: block;
  animation: showNav 250ms ease-in-out both;
}

デモ

このデモでは、サブメニューがからdisplay:noneに変わりdisplay:block、引き続きフェードアウトします。


なければならないmyfirstことがshowNavここに?そしてFirefoxはどうですか?残念ながら、あなたが言及しているデモページに関連するものは見つかりません。
Sebastian vom Meer 2014

@SebastianGに感謝します。修正を行い、上記の情報をいくつか追加しました。
Manish Pradhan 2014

@Sebastian vom Meer:古いバージョンのFirefoxには「-moz-」ベンダープレフィックスが必要です。編集されたコードを参照してください
Herr_Schwabullek

23
何かを見逃していない限り、「デモ」リンクはサブメニュー遷移を表示しません。
現実的な

1
スペースを占有しないもの(display:noneの場合のように)からスペースを占有するもの(display:block)への正しい遷移は、フェードインではなく次元の拡張です。表示から非表示(スペースを占有するが表示されない)の可視性の問題である場合、サイズは同じままで、フェードインが適切です。これらの答えはどれも問題を解決しません。
Triynko 2017年

21

W3Cワーキングドラフトに よるとdisplay2013年11月19日アニメート可能なプロパティではありません。幸い、visibilityアニメート可能です。その遷移を不透明度の遷移(JSFiddle)と連鎖させることができます。

  • HTML:

    <a href="http://example.com" id="foo">Foo</a>
    <button id="hide-button">Hide</button>
    <button id="show-button">Show</button>
  • CSS:

    #foo {
        transition-property: visibility, opacity;
        transition-duration: 0s, 1s;
    }
    
    #foo.hidden {
        opacity: 0;
        visibility: hidden;
        transition-property: opacity, visibility;
        transition-duration: 1s, 0s;
        transition-delay: 0s, 1s;
    }
  • テスト用のJavaScript:

    var foo = document.getElementById('foo');
    
    document.getElementById('hide-button').onclick = function () {
        foo.className = 'hidden';
    };
    
    document.getElementById('show-button').onclick = function () {
        foo.className = '';
    };

を設定せずにリンクを透明にした場合、visibility: hiddenクリック可能なままになることに注意してください。


1
jsfiddleの例に遷移がまったく表示されない
Gino

@Ginoに変更0して修正しました0s。どうやら、過去にテストに使用したブラウザーは、単位なしゼロをサポートしていました。ただし、単位のない時間は、2016年9月29日のW3C候補勧告の一部ではありません
feklee 2016年

これはもっと賛成されるべきです。私はそれが最良の解決策の1つであることがわかりました。
Arthur Tarasov 2017

遅延の使用は、これがどのように機能するかを理解するための最良のロジックです。アニメーション化し、非表示にします。再表示し、アニメーション化します。私にとって完璧なソリューション
Bruno PitteliGonçalves'30 / 09/30

15

編集:この例では、display noneは適用されていません。

@keyframes hide {
  0% {
    display: block;
    opacity: 1;
  }
  99% {
    display: block;
  }
  100% {
    display: none;
    opacity: 0;
  }
}

上で起こっていることは、不透明度がフェードアウトする間、アニメーション表示の99%がブロックするように設定されていることです。最後の瞬間では、displayプロパティはnoneに設定されています。

そして最も重要なのは、アニメーションが終了した後、animation-fill-modeを使用して最後のフレームを保持することです。

.hide {
   animation: hide 1s linear;
   animation-fill-mode: forwards;
}

次に2つの例を示します。https//jsfiddle.net/qwnz9tqg/3/


このソリューションでdisplay: noneは機能しませんか?
Bart Calixto 2016年

「animation-fill-mode:forwards」ではなく「forward」でなければなりません
Alex

編集は6文字である必要があり、編集のみを提案できるため、コメント
Alex

1
@アレックスOK。誤植を修正しました。興味深いのは、私の答えが期待どおりに機能しないことですが、そうなると考えるのは理にかなっているので、ブラウザーがサポートするまでそのままにしておきます。
Pawel

3
カーソルセットを使用したこのフィドルでわかるように、display: none実際には実装されていません。jsfiddle.net/3e6sduqh
robstarbuck

14

私のきちんとしたJavaScriptトリックは、シナリオ全体を2つの異なる関数に分離することですです!

準備のために、1つのグローバル変数が宣言され、1つのイベントハンドラーが定義されます。

  var tTimeout;
  element.addEventListener("transitionend", afterTransition, true);//firefox
  element.addEventListener("webkitTransitionEnd", afterTransition, true);//chrome

次に、要素を非表示にするときに、次のようなものを使用します。

function hide(){
  element.style.opacity = 0;
}

function afterTransition(){
  element.style.display = 'none';
}

要素を再表示するために、私は次のようなことをしています:

function show(){
  element.style.display = 'block';
  tTimeout = setTimeout(timeoutShow, 100);
}

function timeoutShow(){
  element.style.opacity = 1;
}

今のところうまくいきます!


これは、javascriptコマンドが別の関数にあるためではなく、時間遅延のために機能します。多くの場合、時間遅延は良い解決策のようです:)

10

今日、position: fixed私は再利用していたモーダルでこれに遭遇しました。私はそれを維持してdisplay: noneアニメーション化することはできませんでした。それはただ出現しただけで、そしてz-index(負の値など)奇妙なこともしたからです。

私はheight: 0to も使用してheight: 100%いましたが、モーダルが表示されたときにのみ機能しました。これは使用した場合と同じですleft: -100%何かです。

それから私は簡単な答えがあることに私を驚かせました。Et voila:

まず、あなたの隠されたモーダル。通知はheightあり0、およびチェックアウトするheightことがあり...トランジションで宣言し500ms私よりも長くなるopacityの移行を。これは、出力のフェードアウト遷移に影響を与えることに注意してください。モーダルをデフォルトの状態に戻します。

#modal-overlay {
    background: #999;
    background: rgba(33,33,33,.2);
    display: block;
    overflow: hidden;
    height: 0;
    width: 100%;
    position: fixed;
    top: 0;
    left: 0;
    opacity: 0;
    z-index: 1;
    -webkit-transition: height 0s 500ms, opacity 300ms ease-in-out;
       -moz-transition: height 0s 500ms, opacity 300ms ease-in-out;
            -ms-transition: height 0s 500ms, opacity 300ms ease-in-out;
         -o-transition: height 0s 500ms, opacity 300ms ease-in-out;
        transition: height 0s 500ms, opacity 300ms ease-in-out;
}

第二に、あなたの目に見えるモーダル。をに設定する.modal-activeとしbodyます。今height100%あり、私の移行も変更されました。私が欲しいheight瞬時に変更すること、およびopacity取ります300ms

.modal-active #modal-overlay {
    height: 100%;
    opacity: 1;
    z-index: 90000;
    -webkit-transition: height 0s, opacity 300ms ease-in-out;
       -moz-transition: height 0s, opacity 300ms ease-in-out;
        -ms-transition: height 0s, opacity 300ms ease-in-out;
         -o-transition: height 0s, opacity 300ms ease-in-out;
            transition: height 0s, opacity 300ms ease-in-out;
}

それだけです、それは魅力のように機能します。


ベンダー接頭辞プロパティ👍揃えるのあなたのスタイルにUpvoting
ジョージグリーン

9

これらの回答のいくつかと他のいくつかの提案から、以下はホバーメニューに最適です( 特にこれをBootstrap 3で使用しています)。

nav .dropdown-menu {
    display: block;
    overflow: hidden;
    max-height: 0;
    opacity: 0;
    transition: max-height 500ms, opacity 300ms;
    -webkit-transition: max-height 500ms, opacity 300ms;
}
nav .dropdown:hover .dropdown-menu {
    max-height: 500px;
    opacity: 1;
    transition: max-height 0, opacity 300ms;
    -webkit-transition: max-height 0, opacity 300ms;
}

はで許可されていないため、両方の値を指定する場合heightはの代わりに使用することもできmax-heightます。のホバー値は、メニューの値よりも大きくする必要があります。height:autotransitionmax-heightheight


3
それは素晴らしいトリックですが、欠点もあります。遷移時間は高さに依存します。高さが可変のメニューが複数ある場合は、高さがmax-heightに近い要素がうまくアニメーション化されます。ただし、短いものはアニメーションが速すぎて、一貫性のないエクスペリエンスが発生します。
ユーザー

8

この問題のより良い方法を見つけました。CSSアニメーションを使用して、アイテムを表示するための素晴らしい効果を作成できます。

    .item {
     display: none;
}

.item:hover {
     display: block;
     animation: fade_in_show 0.5s
}

@keyframes fade_in_show {
     0% {
          opacity: 0;
          transform: scale(0)
     }
     100% {
          opacity: 1;
          transform: scale(1)
     }
}

この便利なヒントをありがとうございます。
セダクムク

6

私はこの問題に何度も遭遇しましたが、今は単に次のようになりました:

.block {
  opacity: 1;
  transition: opacity 250ms ease;
}

.block--invisible {
  pointer-events: none;
  opacity: 0;
}

クラスを追加すると、block--invisible要素全体がクリックできなくなりますが、その背後にあるすべての要素pointer-events:noneは、すべての主要なブラウザでサポートされているためです(IE <11ではありません)。


これを例に挙げてもらえますか?
GarethAS 2017

1
これはうまく機能しますが、pointer-eventsは11未満のIEでは機能しないことに注意してください
user1702965

IE 11未満のメモを追加
DominikAngerer

すべての要素(メニューなど)の上に上記の要素を配置する必要がある場合、これは正直言ってこれを行う最もクリーンな方法です。2019年のサポートは堅実ですpointer-events
Josh Davenport

5

に変更overflow:hiddenoverflow:visibleます。それはよりよく機能します。私はこのように使用します:

#menu ul li ul {
    background-color:#fe1c1c;
    width:85px;
    height:0px;
    opacity:0;
    box-shadow:1px 3px 10px #000000;
    border-radius:3px;
    z-index:1;
    -webkit-transition:all 0.5s ease;
    -moz-transition:all 0.6s ease;
}

#menu ul li:hover ul  {
    overflow:visible;
    opacity:1;
    height:140px;
}

visibleoverflow:hiddenように振る舞うので、より良いdisplay:noneです。


これが僕の切符だった。ありがとう!
Dan Loewenherz

5

JavaScriptは不要であり、法外に巨大な最大高さは必要ありません。代わりに、max-heightテキスト要素にを設定し、remまたはなどのフォント相対単位を使用しますem。このようにして、メニューが閉じたときの遅延や「飛び出し」を回避しながら、コンテナよりも最大の高さを高く設定できます。

HTML

<nav>
  <input type="checkbox" />
  <ul>
    <li>Link 1</li>
    <li>Link 1</li>
    <li>Link 1</li>
    <li>Link 1</li>
  </ul>
</nav>

CSS

nav input + ul li { // Notice I set max-height on li, not ul
   max-height: 0;
}

nav input:checked + ul li {
   max-height: 3rem; // A little bigger to allow for text-wrapping - but not outrageous
}

こちらの例をご覧ください:http : //codepen.io/mindfullsilence/pen/DtzjE


これと同様に、テキストの行の高さを設定して、ゼロに変換できます。内部にテキストしかない場合、これによりコンテナが非表示になります。
vicmortelmans 2014

なぜそれほど投票しないのですか?これは本当に良い答えであり、私が使用するものかもしれません。
mwilcox 2017

@mwilcoxは固定の高さを使用するため、動的コンテンツ(推定高さであっても)で作業する場合は不適切です。そして、それはテキストコンテンツでのみ有用です。
Fabian von Ellerts、2018年

5

ギジェルモからの承認された回答が書かれた後、2012-04-03のCSS移行仕様により、可視性の移行の動作が変更され、transition-delayを使用せずに、この問題をより短時間で解決できるようになりました

.myclass > div {
                   transition:visibility 1s, opacity 1s;
                   visibility:hidden;  opacity:0
               }
.myclass:hover > div
               {   visibility:visible; opacity:1 }

両方のトランジションに指定された実行時間は、通常同じである必要があります(ただし、表示されるまでに少し長い時間は問題ありません)。

実行中のバージョンについては、私のブログ投稿「CSS Transition Visibility」を参照してください

質問のタイトル「ディスプレイ上の遷移:プロパティ」 Rui Marquesからのコメントへの回答と受け入れられた回答へのジョシュ:

このソリューションは、displayプロパティまたはvisibilityプロパティが使用されているかどうかに関係がない場合に機能します(この質問の場合と同様です)。

要素を完全に削除するわけではありません。 display:none、単にますが、ドキュメントフローに残り、後続の要素の位置に影響を与えます。

同様の要素を完全に削除するトランジションは、display:none高さ(他の回答とコメントで示される)、max-height、またはmargin-top / bottomを使用して実行できますが、高さをトランジションするにどうすればよいですか:0; 高さ:自動; CSSを使用していますか?と私のブログ投稿ディスプレイと高さのプロパティでのCSSトランジションの回避策

GeorgeMilloからのコメントへの応答:両方のプロパティと両方のトランジションが必要です。不透明度プロパティは、フェードインとフェードアウトのアニメーションを作成するために使用され、可視性プロパティは、要素がまだマウスイベントに反応しないようにします。トランジションは、視覚効果の不透明度と、フェードアウトが完了するまで非表示を遅らせる可視性で必要です。


4

と組み合わせることopacityで、最終的に私に解決策を見つけましたposition absolute(非表示のときにスペースを占有しないようにする)。

.toggle {
  opacity: 0;
  position: absolute;
  transition: opacity 0.8s;
}

.parent:hover .toggle {
  opacity: 1;
  position: static;
}

4

CSSトランジションを開始したばかりの人は、表示プロパティ(block / none)を同時に変更している場合、CSSトランジションが機能しないことにすぐに気付くと思います。まだ言及されていない回避策の1つはdisplay:block/none、要素の非表示/表示に引き続き使用できることですが、その不透明度を0に設定して、display:block見えないようにします。

次に、フェードインするには、不透明度を1に設定し、不透明度の遷移を定義する "on"などの別のCSSクラスを追加します。ご想像のとおり、「on」クラスを要素に追加するにはJavaScriptを使用する必要がありますが、少なくとも実際の遷移にはCSSを使用しています。

PS両方を行う必要がありdisplay:block、同時にクラスを「オン」に追加する必要がある場合は、setTimeoutを使用して後者を延期します。それ以外の場合、ブラウザは両方が同時に起こっていると見なし、遷移を無効にします。


すばらしい、ありがとう!実際に動作する例を使って別の回答を書きましたdisplay:none
mojuba 2012

4

それは次のように簡単です:)

@keyframes fadeout {
    0% { opacity: 1; height: auto; }
    90% { opacity: 0; height: auto; }
    100% { opacity: 0; height: 0;
}
animation: fadeout linear 0.5s 1 normal forwards !important;

フェードアウトしてから、作成しheight 0;ます。また、転送が最終状態に留まるように、必ず転送を使用してください。


それは良い考えではありませんので、クラスを削除するとき、これは瞬時にリセットする
ショーンT

2

このソリューションには優れた互換性があり、まだ見ていません。

.hidden-element {
  position: absolute;
  z-index: -1;
  pointer-events: none;
  visibility: hidden;
  opacity: 0;
  transition: visibility 0s, opacity .5s ease-out;
}

.hidden-element.visible {
  position: static;
  z-index: auto;
  pointer-events: auto;
  visibility: visible;
  opacity: 1;
}

説明visibility: hidden(1つのステップで「表示とアニメーション」と互換性がある)トリックを使用しますが、組み合わせposition: absolute; z-index: -1; pointer-events: none;を使用して、非表示のコンテナーがスペース取らず、ユーザーの操作に応答しないようにします


1
しかし、positionまだの変更は要素をぐちゃぐちゃにするでしょう、いいえ?
アーシルム2018

まあ、もちろん:position: absolute説明で説明したように、要素がスペースを取らないことを意味します。に切り替わってposition: static現れると、通常の要素のようにスペースを取ります。これがこの質問のポイントです。ぜひお試しください!
クリストフマロワ2018

2
やった。しかし、私が正しく理解していれば、問題は移行についてでした。「滑らかなアニメーション」のように。
アーシルム2018

2

ディスプレイを使用して、これを期待どおりの自然な方法で機能させることができますが、JavaScriptを使用するか、他のタグが別のタグ内にある巧妙なトリックを提案しているため、ブラウザーをスロットルして機能させる必要があります。内部タグはCSSと寸法をさらに複雑にするので、気にしません。JavaScriptソリューションは次のとおりです。

https://jsfiddle.net/b9chris/hweyecu4/17/

次のようなボックスから始めます。

<div id="box" class="hidden">Lorem</div>

隠しボックス。

div.hidden {
    display: none;
}
#box {
    transition: opacity 1s;
}

関連するq / aにあるトリックを使用して、offsetHeightをチェックし、ブラウザーを瞬時にスロットルします。

https://stackoverflow.com/a/16575811/176877

まず、上記のトリックを形式化したライブラリ:

$.fn.noTrnsn = function () {
    return this.each(function (i, tag) {
        tag.style.transition = 'none';
    });
};
$.fn.resumeTrnsn = function () {
    return this.each(function (i, tag) {
        tag.offsetHeight;    
        tag.style.transition = null;
    });
};

次に、それを使用してボックスを表示し、フェードインします。

$('#button').on('click', function() {
    var tag = $('#box');
    if (tag.hasClass('hidden'))
        tag.noTrnsn().removeClass('hidden')
        .css({ opacity: 0 })
        .resumeTrnsn().css({ opacity: 1 });
    else
        tag.css({ opacity: 0 });
});

これにより、ボックスがフェードインおよびフェードアウトします。したがって、.noTrnsn()遷移をオフhiddenにしてdisplayから、クラスを削除noneしますblock。これにより、デフォルトからに戻ります。次に、不透明度を0に設定してフェードインの準備をします。ステージを設定したので、を使用してトランジションをオンに戻し.resumeTrnsn()ます。最後に、不透明度を1に設定してトランジションを開始します。

ライブラリがなければ、表示の変更と不透明度の変更の両方で、望ましくない結果が生じることになります。ライブラリの呼び出しを削除しただけでは、遷移はまったく発生しません。

上記では、フェードアウトアニメーションの最後に表示を再びなしに設定しないことに注意してください。でももっと凝ったものにできます。フェードインして高さが0から大きくなるものを使用してみましょう。

ファンシー!

https://jsfiddle.net/b9chris/hweyecu4/22/

#box {
    transition: height 1s, opacity 1s;
}

高さと不透明度の両方を移行しています。高さを設定していないことに注意してください。つまり、高さがデフォルトですauto。通常、これは遷移できません。autoからピクセル値(0など)に移動しても、遷移はありません。これをライブラリともう1つのライブラリメソッドで回避します。

$.fn.wait = function (time, fn) {
    if (time)
        this.delay(time);
    if (!fn)
        return this;

    var _this = this;
    return this.queue(function (n) {
        fn.call(_this);
        n();
    });
};

これは、jQuery 3.xで除外されているアニメーションフレームワークを必要とせずに、jQueryの既存のfx / animationキューに参加できる便利なメソッドです。jQueryがどのように機能するかを説明するつもりはありませんが.queue().stop()、jQueryが提供する配管は、アニメーションが互いに干渉するのを防ぐのに役立ちます。

スライドダウン効果をアニメーション化してみましょう。

$('#button').on('click', function() {
    var tag = $('#box');
    if (tag.hasClass('hidden')) {
        // Open it
        // Measure it
        tag.stop().noTrnsn().removeClass('hidden').css({
            opacity: 0, height: 'auto'
        });
        var h = tag.height();
        tag.css({ height: 0 }).resumeTrnsn()
        // Animate it
        .css({ opacity: 1, height: h })
        .wait(1000, function() {
            tag.css({ height: 'auto' });
        });
    } else {
        // Close it
        // Measure it
        var h = tag.noTrnsn().height();
        tag.stop().css({ height: h })
        .resumeTrnsn()
        // Animate it
        .css({ opacity: 0, height: 0 })
        .wait(1000, function() {
            tag.addClass('hidden');
        });
    }
});

このコードは#box、クラスをチェックすることで、チェックされ、現在非表示になっているかどうかを確認することから始まります。しかし、スライドアウト/フェードアニメーションの最後にクラスをwait()追加することにより、ライブラリコールを使用してより多くのことを実現hiddenします。これは、実際に非表示になっている場合に見つかるはずです。上の単純な例ではできません。これにより、要素を繰り返し表示/非表示にすることもできます。これは、非表示のクラスが復元されなかったため、前の例のバグでした。

また、呼び出し前に.noTrnsn()最終的な高さを測定するなど、測定を行うなど、アニメーションのステージを設定するために呼び出されたCSSとクラスの変更を確認することもでき#boxます。.resumeTrnsn()、をや、その完全なセットからアニメーション化することなどが含まれます。目標のCSS値にステージングします。

古い答え

https://jsfiddle.net/b9chris/hweyecu4/1/

あなたはクリックでそれを移行させることができます:

function toggleTransition() {
  var el = $("div.box1");

  if (el.length) {
    el[0].className = "box";
    el.stop().css({maxWidth: 10000}).animate({maxWidth: 10001}, 2000, function() {
        el[0].className = "box hidden";
    });
  } else {
    el = $("div.box");
    el[0].className = "box";
    el.stop().css({maxWidth: 10001}).animate({maxWidth: 10000}, 50, function() {
        el[0].className = "box box1";
    });
  }

  return el;
}

someTag.click(toggleTransition);

CSSはあなたが推測するものです:

.hidden {
    display: none;
}
.box {
    width: 100px;
    height: 100px;
    background-color: blue;
    color: yellow;
    font-size: 18px;
    left: 20px;
    top: 20px;
    position: absolute;
    -webkit-transform-origin: 0 50%;
    transform-origin: 0 50%;
    -webkit-transform: scale(.2);
    transform: scale(.2);
    -webkit-transition: transform 2s;
    transition: transform 2s;
}
.box1{
    -webkit-transform: scale(1);
    transform: scale(1);
}

キーは、表示プロパティを調整することです。隠されたクラスを削除してから、50ミリ秒を待っていることで、その後追加されたクラスを経由して移行を開始し、我々はそれがただのアニメーションせずに画面上にブリッピングの代わりに、それが表示されるように取得し、我々が望んでいたように、次に展開します。アニメーションが終了するまで待ってから非表示を適用することを除いて、同じことが他の方法でも起こります。

注:競合状態.animate(maxWidth)を回避するためにここで悪用していsetTimeoutます。setTimeout自分や他の誰かが気づかないコードを見つけたときに、隠れたバグをすばやく導入します。.animate()で簡単に殺すことができます.stop()。これを使用して、標準のfxキューに50ミリ秒または2000ミリ秒の遅延を設定しているだけで、この上に構築している他のコーダーが簡単に検索/解決できます。


1

答えが見つからなかった同様の問題がありました。いくつかのGoogle検索が後で私をここに導いた。私が望んでいた簡単な答えが見つからなかったので、エレガントで効果的な解決策を見つけました。

それは判明visibilityCSSプロパティの値がありcollapse、一般的にテーブルの項目に使用されます。ただし、他の要素で使用した場合、それらは効果的に非表示としてレンダリングされます。これは、要素とほとんど同じdisplay: hiddenですが、要素がスペースをとらず、問題の要素をアニメーション化できるという機能が追加されています。

以下は、この動作の簡単な例です。

function toggleVisibility() {
  let exampleElement = document.querySelector('span');
  if (exampleElement.classList.contains('visible')) {
    return;
  }
  exampleElement.innerHTML = 'I will not take up space!';
  exampleElement.classList.toggle('hidden');
  exampleElement.classList.toggle('visible');
  setTimeout(() => {
    exampleElement.classList.toggle('visible');
    exampleElement.classList.toggle('hidden');
  }, 3000);
}
#main {
  display: flex;
  flex-direction: column;
  width: 300px;
  text-align: center;
}

.hidden {
  visibility: collapse;
  opacity: 0;
  transition: visibility 2s, opacity 2s linear;
}

.visible {
  visibility: visible;
  opacity: 1;
  transition: visibility 0.5s, opacity 0.5s linear;
}
<div id="main">
  <button onclick="toggleVisibility()">Click Me!</button>
  <span class="hidden"></span>
  <span>I will get pushed back up...</span>
</div>


1

問題の最も簡単なユニバーサルソリューションは次のとおりdisplay:noneです。CSSで自由に指定してください。ただしblock、JavaScriptを使用してそれを(または他の何でも)に変更し、実際に問題の要素にクラスを追加する必要があります。setTimeout()で遷移を行います。それで全部です。

すなわち:

<style>
    #el {
        display: none;
        opacity: 0;
    }
    #el.auto-fade-in {
        opacity: 1;
        transition: all 1s ease-out; /* Future, future, please come sooner! */
        -webkit-transition: all 1s ease-out;
        -moz-transition: all 1s ease-out;
        -o-transition: all 1s ease-out;
    }
</style>

<div id=el>Well, well, well</div>

<script>
    var el = document.getElementById('el');
    el.style.display = 'block';
    setTimeout(function () { el.className = 'auto-fade-in' }, 0);
</script>

これは最新の健全なブラウザでテストされました。もちろん、Internet Explorer 9以前では機能しないはずです。


1

SalmanPKが最も近い答えだと思います。次のCSSアニメーションを使用して、アイテムをフェードインまたはフェードアウトします。ただし、displayプロパティはスムーズにアニメーション化せず、不透明度のみをアニメーション化します。

@-webkit-keyframes fadeIn {
    from { opacity: 0; }
      to { opacity: 1; }
}

@-webkit-keyframes fadeOut {
    from { opacity: 1; }
      to { opacity: 0; }
}

要素を表示ブロックから何も表示しないようにアニメーション化する場合、現在CSSだけで可能であるとは思えません。高さを取得し、CSSアニメーションを使用して高さを下げる必要があります。これは、以下の例に示すようにCSSで可能ですが、要素でアニメーション化する必要がある正確な高さの値を知るのは難しいでしょう。

jsFiddleの

CSS

@-webkit-keyframes pushDown {
  0% {
    height: 10em;
  }
  25% {
    height: 7.5em;
  }
  50% {
    height: 5em;
  }
  75% {
    height: 2.5em;
  }
  100% {
    height: 0em;
  }
}

.push-down {
    -webkit-animation: pushDown 2s forwards linear;
}

JavaScript

var element = document.getElementById("element");

// Push item down
element.className = element.className + " push-down";

1

これは遷移イベントで実行できるため、遷移用に2つのCSSクラスを作成します。1つはアニメーションを保持し、もう1つは表示なしの状態を保持します。そして、アニメーションが終了した後にそれらを切り替えますか?私の場合、ボタンを押すとdivを再度表示して、両方のクラスを削除できます。

以下のスニペットを試してください...

$(document).ready(function() {
  // Assign transition event
  $("table").on("animationend webkitAnimationEnd", ".visibility_switch_off", function(event) {
    // We check if this is the same animation we want
    if (event.originalEvent.animationName == "col_hide_anim") {
      // After the animation we assign this new class that basically hides the elements.
      $(this).addClass("animation-helper-display-none");
    }

  });

  $("button").click(function(event) {

    $("table tr .hide-col").toggleClass(function() {
      // We switch the animation class in a toggle fashion...
      // and we know in that after the animation end, there
      // is will the animation-helper-display-none extra
      // class, that we nee to remove, when we want to
      // show the elements again, depending on the toggle
      // state, so we create a relation between them.
      if ($(this).is(".animation-helper-display-none")) {
        // I'm toggling and there is already the above class, then
        // what we want it to show the elements , so we remove
        // both classes...
        return "visibility_switch_off animation-helper-display-none";
      }
      else {
        // Here we just want to hide the elements, so we just
        // add the animation class, the other will be added
        // later be the animationend event...
        return "visibility_switch_off";
      }
    });
  });
});
table th {
  background-color: grey;
}

table td {
  background-color: white;
  padding: 5px;
}

.animation-helper-display-none {
  display: none;
}

table tr .visibility_switch_off {
  animation-fill-mode: forwards;
  animation-name: col_hide_anim;
  animation-duration: 1s;
}

@-webkit-keyframes col_hide_anim {
  0% {opacity: 1;}
  100% {opacity: 0;}
}

@-moz-keyframes col_hide_anim {
  0% {opacity: 1;}
  100% {opacity: 0;}
}

@-o-keyframes col_hide_anim {
  0% {opacity: 1;}
  100% {opacity: 0;}
}

@keyframes col_hide_anim {
  0%   {opacity: 1;}
  100% {opacity: 0;}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <theader>
    <tr>
      <th>Name</th>
      <th class='hide-col'>Age</th>
      <th>Country</th>
    </tr>
  </theader>
  <tbody>
    <tr>
      <td>Name</td>
      <td class='hide-col'>Age</td>
      <td>Country</td>
    </tr>
  </tbody>
</table>

<button>Switch - Hide Age column with fadeout animation and display none after</button>


0

jQueryを使用してクラスを設定している場合、これは100%機能します。

$(document).ready(function() {
  $('button').click(function() {
    var container = $('.container');
    
    if (!container.hasClass('active')) {
      container.addClass('show').outerWidth();
      container.addClass('active');
    }
    else {
      container.removeClass('active').one('transitionend', function() {
        container.removeClass('show');
      });
    }
  });
});
.container {
  display: none;
  opacity: 0;
  transition: opacity 0.3s ease;
}

.container.show {
  display: flex;
}
 
.container.active {
  opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button">Toggle</button>

<div class="container">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>

もちろん、jQuery .fadeIn().fadeOut()関数だけを使用することもできますが、代わりにクラスを設定する利点は、block.fadeIn()およびのデフォルトのように.fadeOut())以外の表示値に移行する場合です。

ここではflex、フェード効果の良いディスプレイに移行しています。


0

使用displayする代わりに、必要になるまで要素を「オフスクリーン」で保存し、その位置を必要な場所に設定し、同時に変換することができます。ただし、これにより他の多くの設計上の問題が発生するため、マイレージは異なる場合があります。

おそらくdisplayコンテンツをスクリーンリーダーにアクセスできるようにしたいので、おそらく使用したくないでしょう。つまり、ほとんどの場合、可視性のルールに従うことを試みます。つまり、目に見えないようにする必要がある場合は、エージェントのコンテンツとして表示されません。


0

あなたは単にCSSの可視性を使用することができます表示の代わりに非表示/可視:なし/ブロック

div {
    visibility:hidden;
    -webkit-transition: opacity 1s ease-out;
    -moz-transition: opacity 1s ease-out;
    -o-transition: opacity 1s ease-out;
    transition: opacity 1s ease-out;
    opacity: 0;
}

parent:hover > div {
    opacity: 1;
    visibility: visible;
}

5
これによりスペースが予約され、空の穴が残ります。スペースを折りたたむ場合は、高さまたはその他のプロパティをアニメーション化する必要があります。
Marcy Sutton

0

Toggle Display Animateというオープンソースのスケルトンプロジェクトを開始しました。

このスケルトンヘルパーを使用すると、jQueryの表示/非表示を簡単に模倣できますが、CSS 3の遷移アニメーションを使用できます。

クラストグルを使用するため、display:none | block | table | inlineなど以外の要素に必要なCSSメソッドを使用できるほか、考えられる他の代替使用法も使用できます。

その主な設計目的は要素のトグルステートであり、オブジェクトを非表示にすると、キーフレームを逆方向に実行したり、要素を非表示にする代替アニメーションを再生したりできる状態に戻ります。

私が取り組んでいるコンセプトのマークアップのほとんどはCSSであり、実際に使用されているJavaScriptはほとんどありません。

ここにデモがあります:http : //marcnewton.co.uk/projects/toggle-display-animate/

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.