display: noneはtransitionできないので
参考:css - Transitions on the display: property - Stack Overflow
そのへんで拾ったアコーディオンのライブラリとかでよく見るやつ。
もはやマークアップあるあるですよね。
displayじゃダメなので、他のプロパティで攻めましょう、っていう。
代替案を書いてみる
クラス名で切り替えるアコーディオンとか、ありがちなケースで。
元ネタ
Html
<section class="accordion"> <h1>Accordion 1</h1> <ul> <li>Sample li 1</li> <li>Sample li 1</li> <li>Sample li 1</li> <li>Sample li 1</li> </ul> </section> <section class="accordion"> <h1>Accordion 1</h1> <ul> <li>Sample li 1</li> <li>Sample li 1</li> <li>Sample li 1</li> <li>Sample li 1</li> </ul> </section>
Css
.accordion { text-align: center; margin-bottom: 16px; } .accordion > h1 { font-weight: 900; height: 44px; line-height: 44px; background-color: #000; color: #fff; } .accordion > ul { display: none; -webkit-transition: all 1s ease-out;/* displayには効かない! */ transition: all 1s ease-out; } .accordion > ul.active { display: block; } .accordion > ul > li { height: 44px; line-height: 44px; } .accordion > ul > li:nth-child(odd) { background-color: #eee; }
JavaScript
// jQuery or something loaded... jQuery(function(win, $){ var doc = win.document, accordions = $('.accordion'), accordionObj = {}; var Accordion = function(accordion){ var self = $(accordion), trigger = self.find('h1'), target = trigger.next(); trigger.on('click', function(){ target.toggleClass('active'); }); }; accordions.each(function(id, accordion){ accordionObj['accordion-' + id] = new Accordion(accordion); }); }(this, jQuery));
ちゃんと動作するけど、No Transition!
ほんとはもうちょっときっちり書いた方がいい気もする。
代替案
displayがダメなのであれば、heightで攻めてみる。
Css
/* ... */ .accordion > ul { height: 0px;/* heightだけでもいいけど */ opacity: 0;/* transitionっぽくするならコレも */ overflow: hidden; -webkit-transition: all 1s ease-out; transition: all 1s ease-out; } .accordion > ul.active { height: auto; opacity: 1; } /* ... */
というわけで、無事にfadeToggleっぽくなった!
slideToggle()にしたい場合はたぶん、
- newした時に要素の高さも取得する
- クリックイベントに貼るのはtoggleClassじゃなくてwhile(高さ){高さ--}みたいな関数
ってすればいけるかな?
と思って適当に書いたらすごくいやな感じになったw
// jQuery or something loaded... jQuery(function(win, $){ var doc = win.document, accordions = $('.accordion'), accordionObj = {}; var Accordion = function(accordion){ var self = $(accordion), trigger = self.find('h1'), target = trigger.next(), isActive = false, height = target.height(); trigger.on('click', function(){ /* ------------- TODO: どうにかしたい ------------ */ var counter = (isActive) ? height : 0; if(isActive){ while(counter){ target.height(counter); counter--; } }else{ while(counter < height){ target.height(counter); counter++; } } isActive = !isActive; /* ------------- TODO: どうにかしたい ------------ */ }); target.height(0); isActive = false; }; accordions.each(function(id, accordion){ accordionObj['accordion-' + id] = new Accordion(accordion); }); }(this, jQuery));
・・・精進が足りませんね。
まぁ、jQuery使ってるならslideToggle()とかfadeToggle()とかすれば良いんやけど、もっと軽いライブラリを選んでるケースもあるよねー。