🧊

display: noneはtransitionできないので

参考:css - Transitions on the display: property - Stack Overflow

そのへんで拾ったアコーディオンのライブラリとかでよく見るやつ。
もはやマークアップあるあるですよね。

displayじゃダメなので、他のプロパティで攻めましょう、っていう。

transitionできるプロパティ

参考:CSS Transitions

色とか長さとか、数値で表現できるっぽいやつはだいたいOKな感じ。

代替案を書いてみる

クラス名で切り替えるアコーディオンとか、ありがちなケースで。

元ネタ

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()とかすれば良いんやけど、もっと軽いライブラリを選んでるケースもあるよねー。