はてなブログ:モジュールを伸縮させて高さを揃える

そろそろこのサイトのデザインを変えようかと思い始めての tips チップス(4)。正月休み中にもほんとど触れずいっこうに進んでいません。

今回はサイドバーモジュールを本文下に横並びで並べた時に高さを揃えようと思います。



何をやろうとしているか


まず、基本的なこととして、トップページではサイドバーモジュールをメインコンテンツの下に表示、記事ページなどその他のページでは2カラムで表示する場合の話です。

また、サイドバーモジュールは最新記事と人気記事を表示させる場合、及びそれに類する場合の話です。


はてなブログをデフォルトの設定で使おうとしますと当然トップページは最新記事の一覧表示になります。それが全文形式であれ、一覧形式であれ、最新記事が何記事か並ぶことになります。

その場合、サイドバーに最新記事モジュールを表示させますと、トップページではメインコンテンツと最新記事モジュールに同じ記事一覧が表示されることになります。


重複表示を避けるためには、

.page-index .hatena-module-recent-entries {
    display: none;
}

などとして最新記事モジュールを非表示にするしかなく、そうしますとメインコンテンツ下のサイドバーをどう表示するか問題になります。

その解決方法です。ただし、必要性はかなり怪しいです(笑)。


何をやろうとしているのかわかりにくいと思いますので画像で示します。


画像で示すと


f:id:ausnichts:20210105162034j:plain

これがトップページのメインコンテンツ下のサイドバーです。サイドバーには最新記事と人気記事を表示し、トップページのみ最新記事を非表示にしています。

また、人気記事は最大10記事が表示可能ですので10記事を2カラムに表示して最新記事の非表示スペースを埋めています。


f:id:ausnichts:20210105162100j:plain

その設定で記事ページを表示しますとこうなります。最新記事を5記事表示にしていますので人気記事のほうがだらーと長くなってしまいます。この人気記事を5記事表示にし、ボタンをクリックすると下へ伸びて10記事表示にしようということです。

最新記事を10記事表示にすれば解決するという考え方もあります(笑)。


6記事以降を非表示にする CSS


まず人気記事の6記事以降を非表示にする css を考えます。


body:not(.page-index) .entries-access-ranking-item:nth-child(n+6) {
  max-height: 0;
  margin-top: 0;
  overflow: hidden;
  transition: all .5s ease-out;
}

10記事を5記事ずつ区切れれば楽なんですが、10記事がリストで並んでいますので :nth-child() という擬似クラスを使います。引数に (n + 数値) としますとその数値以降の要素を指定できます。

:nth-child() - CSS: カスケーディングスタイルシート | MDN


高さをアニメーションする場合、高さがわかっていれば height でアニメーションさせられますが、height: auto はアニメーションしませんので max-height を使います。マージンを取っている場合はマージンもアニメーションの対象です。


ボタンを挿入する Javascript


クリックイベントを発生させるボタンがありませんので Javascript で挿入します。


(function(){
    function toggleRanking(){
        document.getElementById('box2').classList.toggle('ranking-show');
    };

    const seemoreDiv = document.createElement('div');
    seemoreDiv.classList.add('urllist-see-more', 'ranking-see-more');
    seemoreDiv.addEventListener('click', toggleRanking);
    const rankingModule = document.getElementsByClassName('hatena-module-entries-access-ranking')[0];
    rankingModule.appendChild(seemoreDiv);
})();


新しく div要素を作り、クラスとクリックイベントを設定し、人気記事モジュールの後ろに挿入しています。関数 toggleRanking は伸縮をコントロールするクラスを親要素に追加したり削除したりするだけです。


6記事以降を伸縮させる CSS


ボタンのスタイルと親要素にクラス ranking-show を追加した場合の css を加えます。


body:not(.page-index) .ranking-show .entries-access-ranking-item:nth-child(n+6) {
  max-height: 100px;
  margin-top: 30px;
}
body:not(.page-index) .ranking-see-more {
  background: linear-gradient(to right, #4b2e9b 0%, #bdaee7 100%);
  padding: 10px 0;
  text-decoration: none;
  color: #ffffff;
  display: block;
  margin-left: 51%;
  text-align: center;
  font-size: 1.6rem;
  font-weight: bold;
}
body:not(.page-index) .ranking-see-more::before {
  content: 'もっと見る';
}
body:not(.page-index) .ranking-see-more::after {
  content: '\f008';
  font-family: blogicon;
  margin-left: 10px;
  text-shadow: 0 5px 0;
  font-weight: normal;
}
body:not(.page-index) .ranking-show .ranking-see-more::before {
  content: '閉じる';
}
body:not(.page-index) .ranking-show .ranking-see-more::after {
  content: '\f007';
}


`max-height: 100px' はやや大きめの数値を指定しておきます。あまり大きくしますとアニメーションがぎこちなくなります。これで 100px以内であれば実際の高さで止まり、それ以上であれば非表示になります。


完成図


デモサイトではなくこんな感じという画像です。


f:id:ausnichts:20210105162146j:plain

「もっと見る」ボタンが挿入されています。


f:id:ausnichts:20210105162242j:plain

ボタンをクリックし30%ほど伸びたところです。リストの各要素にアニメーションが掛かっています。


f:id:ausnichts:20210105162329j:plain

100%伸び切りました。ボタンの表示が「閉じる」に変わっています。