cBlog

Tips for you.

脱jQueryその1 はてなブログの目次をクリックで.slideDown()させる

f:id:cruller:20170712215607p:plain

こんにちは。いつも人にインスパイアされるcrullerです。

今回は、シロマティさんのbrand-newデザインテーマ「SOHO」に触発されました。

www.notitle-weblog.com

どこにかというと、SOHOとともに提供されているカスタマイズにjQueryを一切使っていないところ。まんまと(?)、私も脱jQueryしたくなりました。うずうず。jQueryはこのブログでも何か所か使っていますが、まずはゆきひーさんの「最初は隠しておいて、クリックしたら表示するようにする」目次から取り掛かることにしました。

www.yukihy.com

ここまで働いてくれたコードの製作者ゆきひーさんにこの場より感謝を(-人-)

途中で力尽きなければ、たぶん連載します。

 

DEMO

まずはデモです。というか、この記事の目次です。

 

数字付きになっているのとだんだん小さくなるのと小見出しが非表示になるのは、上のゆきひーさんの記事を参考にして導入してください。

 

カスタマイズ方法と開発日記

初め、無知な私はjQueryを素のJavaScriptに書き換えていけばいいと思ったのですが、.slideDown()で詰みました。時間ごとに高さをいちいち計算しなければならないのでとてもバグりそうです。

というわけでCSS3のアニメーションに頼ることにしました。何故最初からそうしなかったんでしょう。

しかしながら、問題に遭遇しました。「heightを0→autoにtransitionさせればいい。簡単、簡単。」と思ったのですが、どうみても一瞬で開いています。本当にありがとうございました。なんと、heightは指定値にしないとtransitionしないとのこと。代わりにmax-heightを使い、高さの目標値を大きめに指定してあげるという方法もありましたが、それだと短い目次の場合は早く開き過ぎてしまうし、何より内部にパラメータを保持しておくというのは私の一番キライなやり方でもあります。

そこで、JavaScriptの力を借ります。後から<ul>のheightを取得し、追加してやります。もちろん、素のJavaScriptで。

 

1) Font Awesomeの導入

chevronアイコンにFont Awesomeを使っています。未導入の方は以下のコードをフッタに。

HTML

<!-- Font Awesome -->
<script>
var cbFa = document.createElement('link');
cbFa.rel = 'stylesheet';
cbFa.href = 'https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css';
document.head.appendChild(cbFa);
</script>

 

2) 高さの取得とボタンを追加するJavaScript

同じくフッタに以下のスクリプトを挿入します。

ざっくり言うと、1つ目のブロックでは目次のheightを取得したあと高さ0(非チェック時用)と取得した高さ(チェック時用)のスタイルを追加しています。2つ目のブロックではボタンの代わりとなるチェックボックスを、3つ目のブロックはチェックボックスとクリックが連動するラベル(装飾してボタンとする)を書き込んでいます。

HTML

<!-- 目次をクリックでスライドさせる -->
<script>
var cbToc = document.getElementsByClassName('table-of-contents')[0];
var cbStyle = document.createElement('style');
var cbH = document.defaultView.getComputedStyle(cbToc, '').height;
var cbRuleUnck = '.table-of-contents {height: 0;}';
var cbRuleCk = 'input#cb-toc-checkbox:checked ~ .table-of-contents {height: ' + cbH + ';}';
cbStyle.innerHTML = cbRuleUnck + cbRuleCk;
cbToc.parentNode.insertBefore(cbStyle, cbToc);

var cbIn = document.createElement('input');
cbIn.id = 'cb-toc-checkbox';
cbIn.type = 'checkbox';
cbToc.parentNode.insertBefore(cbIn, cbToc);

var cbLbl = document.createElement('label');
cbLbl.className = 'cb-toc-btn';
cbLbl.setAttribute('for', 'cb-toc-checkbox');
cbLbl.innerHTML = 'Contents ';
cbToc.parentNode.insertBefore(cbLbl, cbToc);
</script>

最初の目次しか取得していないので、トップページが全文形式で複数記事表示しているブログでは期待通り動作しないと思います。要望が来れば、気が向いたら対応します。

 

3) CSSでアニメーションとデザインをつける

次のコードをデザインCSS欄に追加します。

CSS

/* 目次 */
input#cb-toc-checkbox {
    display: none;
}
.cb-toc-btn {
    color: #fff;
    background: #000;
    font-size: 140%;
    font-weight: bold;
    line-height: 1;
    cursor: pointer;
    display: inline-block;
    padding: 0.5em 1em;
    border-radius: 3px;
}
.cb-toc-btn:hover {
    opacity: 0.65;
}
.cb-toc-btn:after {
    font-family: FontAwesome;
    content: '\f078';
}
input#cb-toc-checkbox:checked ~ .cb-toc-btn:after {
    content: '\f077';
}
.table-of-contents {
    overflow: hidden;
    transition: 0.5s;
    transition-property: height, padding-top, padding-bottom, margin-top, margin-bottom;
}
ul.table-of-contents {
    padding-top: 0;
    padding-bottom: 0;
    border-top: none;
    border-bottom: none;
    margin-top: 0;
    margin-bottom: 0;
}
input#cb-toc-checkbox:checked ~ ul.table-of-contents {
    margin-top: 1em;
    margin-bottom: 1em;
    /*  ulにpaddingやborderが設定されている場合は
        元の設定値をここに書く */
}

paddingとmarginも忘れずにスライドさせてやります。もともとulにpaddingやborderがついている人は、指定箇所に現在のスタイルを書かないと消えるので注意。ボタンのデザインはもっとセンスのいい人を頼ってくれるとありがたい。

ちゃんとchevronの向きも変わるようにしたんだからね。

デモ用小見出し

ヾ(。゜▽゜)ノ

 

何かご指導ありましたらお願いします。

次回の記事

yaritakunai.hatenablog.com

 

改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで

改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで