博客園(CNBlogs)のデフォルトデザインを拡張し、サイドバーに動的な要素を追加する方法について解説します。具体的には、Live2D モデルの表示と記事内の見出しに基づいた自動目次生成機能を導入し、CSS によって全体のレイアウトを調整します。
環境設定の手順
管理コンソールにて、「設定」メニューから「ブログ設定」へ進み、「ブログ皮膚」セクションを開きます。皮膚の選択後、「ページ定制 CSS コード」および「ブログ側边栏公告(サイドバー公告)」の編集画面で以下のコードをそれぞれ適用します。また、テンプレート固有の CSS を無効化するオプションにチェックを入れることを推奨します。
スタイルシートの定義
全体のレイアウト、ナビゲーション、記事本文の装飾、およびレスポンシブ対応を担う CSS を以下に示します。アニメーション効果やコードブロックの配色も含んでいます。
/* 全体レイアウト */
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
color: #555;
font-family: "Microsoft YaHei", sans-serif;
}
#home, #sideBar {
height: 100%;
}
#main {
min-height: 1800px;
position: relative;
}
/* リンク装飾 */
a {
text-decoration: none;
color: #e06c75;
transition: all 0.3s;
}
a:hover {
color: #fff;
text-shadow: 0 0 5px #1487cc;
}
/* ヘッダーとナビゲーション */
div#header {
width: 100%;
position: absolute;
height: 60px;
z-index: 999;
}
div#blogTitle {
display: none;
}
ul#navList {
list-style: none;
float: right;
margin-right: 50px;
}
ul#navList li {
float: left;
padding-left: 20px;
}
/* メインコンテンツエリア */
#mainContent {
float: left;
width: 100%;
padding-top: 60px;
}
.forFlow {
margin: 0 auto;
margin-left: 370px;
margin-right: 50px;
border-top: 1px solid #ccc;
}
/* 記事タイトルと本文 */
.postTitle, .entrylistPosttitle {
font-size: 22px;
font-weight: bold;
padding: 40px;
display: inline-block;
animation: title-float 5s infinite ease-in-out;
}
.postCon, .entrylistPostSummary {
font-size: 14px;
line-height: 1.8;
padding-left: 20px;
}
/* コードブロックとテーブル */
.cnblogs-markdown code.hljs, .hljs {
background: #282c34;
color: #abb2bf;
padding: 1em;
display: block;
overflow-x: auto;
}
#cnblogs_post_body table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
box-shadow: 0 0 5px #999;
border-radius: 8px;
}
#cnblogs_post_body table th {
background: #73b1e0;
color: #FFF;
padding: 10px 20px;
text-align: left;
}
#cnblogs_post_body table tr:nth-child(odd) {
background: #F4F4F4;
}
/* サイドバー設定 */
#sideBar {
position: absolute;
background: #262a30;
width: 280px;
height: 100%;
color: #999;
padding: 0 10px;
overflow-y: auto;
}
#sideBar h3 {
color: #61afef;
border-bottom: 1px outset #D4D4D4;
margin-top: 20px;
}
/* アニメーション定義 */
@keyframes title-float {
0% { transform: translate(0, 0) rotate(0deg); }
50% { transform: translate(5px, -5px) rotate(2deg); }
100% { transform: translate(0, 0) rotate(0deg); }
}
/* レスポンシブ対応 */
@media screen and (max-width: 1000px) {
#sideBar, #blog_stats {
display: none;
}
#mainContent, .forFlow {
margin: 0;
padding: 0 20px;
}
div#live2d-widget {
display: none;
}
}
サイドバー機能スクリプト
サイドバー公告欄には、Live2D ウィジェットの初期化と、記事内の見出し(h2, h3)を抽出して目次を生成する JavaScript を配置します。
<script src="https://blog-static.cnblogs.com/files/yyhh/L2Dwidget.min.js"></script>
<script type="text/javascript">
// Live2D ウィジェットの起動
L2Dwidget.init();
// 目次生成ロジック
function renderTableOfContents() {
const postBody = $('#cnblogs_post_body');
if (postBody.length === 0) return;
const headings = postBody.find('h2');
if (headings.length === 0) return;
let navHtml = '<a id="_topAnchor"></a><div id="navCategory"><h3>目次</h3><ul>';
headings.each(function(index) {
const anchorId = '_section_' + index;
$(this).before('<div id="' + anchorId + '"></div>');
const subHeadings = $(this).nextAll('h3');
let subList = '';
subHeadings.each(function() {
const prevH2 = $(this).prevAll('h2').first();
if (!prevH2.is(headings.eq(index))) return false;
const subId = anchorId + '_sub_' + $(this).index();
$(this).before('<div id="' + subId + '"></div>');
subList += '<li><a href="#' + subId + '">' + $(this).text() + '</a></li>';
});
if (subList) {
navHtml += '<li><a href="#' + anchorId + '">' + $(this).text() + '</a><ul>' + subList + '</ul></li>';
} else {
navHtml += '<li><a href="#' + anchorId + '">' + $(this).text() + '</a></li>';
}
});
navHtml += '</ul></div>';
$('#sideBar').prepend(navHtml);
}
$(document).ready(function() {
renderTableOfContents();
});
</script>
すべてのコード入力後、設定を保存しブログページを再読み込みすることで、カスタマイズされたサイドバーと動的な目次機能が有効になります。