目次
index.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>マニュアル</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="header-placeholder"></div>
<div class="page-wrapper">
<!-- ★ JSで中身を描画する -->
<div id="sidebar-placeholder"></div>
<div class="content-wrapper">
<div class="main">
<h3 class="head-i">その他</h3>
<a href="https://chatgpt.com/">ChatGPT</a>
<h3 class="head-i">データ・ツール</h3>
<a href="https://chatgpt.com/">ChatGPT</a>
</div>
</div>
</div>
<script src="favorites-data.js"></script>
<script src="load_header.js"></script>
</body>
</html>
load_header.js
document.addEventListener('DOMContentLoaded', () => {
/* ===============================
0. リンク判定(★これが必須)
=============================== */
const currentPathname = window.location.pathname;
const pathSegments = currentPathname.split('/');
const currentDir = pathSegments[pathSegments.length - 2];
let homeLink, blogLink, sonotaLink, zakkiLink, gijyutuLink;
if (currentDir === 'blog') {
homeLink = '../index.html';
blogLink = 'blog.html';
sonotaLink = '../sonota/sonota.html';
gijyutuLink= '../gijyutu/gijyutu.html';
zakkiLink = '../zakki/zakki.html';
} else if (currentDir === 'sonota') {
homeLink = '../index.html';
blogLink = '../blog/blog.html';
sonotaLink = 'sonota.html';
gijyutuLink= '../gijyutu/gijyutu.html';
zakkiLink = '../zakki/zakki.html';
} else if (currentDir === 'gijyutu') {
homeLink = '../index.html';
blogLink = '../blog/blog.html';
sonotaLink = '../sonota/sonota.html';
gijyutuLink= 'gijyutu.html';
zakkiLink = '../zakki/zakki.html';
} else if (currentDir === 'zakki') {
homeLink = '../index.html';
blogLink = '../blog/blog.html';
sonotaLink = '../sonota/sonota.html';
gijyutuLink= '../gijyutu/gijyutu.html';
zakkiLink = 'zakki.html';
} else {
homeLink = 'index.html';
blogLink = 'blog/blog.html';
sonotaLink = 'sonota/sonota.html';
gijyutuLink= 'gijyutu/gijyutu.html';
zakkiLink = 'zakki/zakki.html';
}
/* ===============================
1. ヘッダー描画
=============================== */
const headerHTML = `
<header class="site-header">
<div class="header-inner">
<!-- サイトタイトル(ロゴ) -->
<div class="header-left">
<a href="${homeLink}" class="site-logo">manual</a>
</div>
<!-- ナビ -->
<nav class="main-nav" id="main-nav-menu">
<ul>
<li><a href="${sonotaLink}">その他</a></li>
<li><a href="${blogLink}">ブログ</a></li>
<li><a href="${zakkiLink}">雑記</a></li>
<li><a href="${gijyutuLink}">技術</a></li>
</ul>
</nav>
<!-- 右側アイコン -->
<div class="header-right">
<button class="header-btn" id="toggle-sidebar" title="サイドバー切替">☰</button>
</div>
</div>
</header>
`;
document.getElementById('header-placeholder').innerHTML = headerHTML;
/* ===============================
2. サイドバー描画(JS直書き)
=============================== */
const sidebarHTML = `
<aside class="sidebar" id="sidebar">
<div class="sidebar-box">
<h3>📁 フォルダ</h3>
<ul>
<li>
<a href="◯◯◯◯">
プログラム開発フォルダ
</a>
</li>
</ul>
</div>
<div class="sidebar-box">
<h3>⭐ お気に入り</h3>
<ul id="favorites-list"></ul>
</div>
</aside>
`;
document.getElementById('sidebar-placeholder').innerHTML = sidebarHTML;
/* ===============================
3. サイドバー開閉
=============================== */
const btn = document.getElementById('toggle-sidebar');
const sidebar = document.getElementById('sidebar');
btn.addEventListener('click', () => {
sidebar.classList.toggle('is-hidden');
});
});
/*───────────────────────────────────────────────
10. トーストを表示するヘルパー関数
───────────────────────────────────────────────*/
function showToast(message, duration = 2000) {
let toast = document.getElementById('toast');
if (!toast) {
toast = document.createElement('div');
toast.id = 'toast';
document.body.appendChild(toast);
}
toast.textContent = message;
// もし前回の hide クラスが残っていたらクリア
toast.classList.remove('hide');
// show クラスを付与してフェードイン
toast.classList.add('show');
// duration 経過後にフェードアウト
setTimeout(() => {
toast.classList.remove('show');
toast.classList.add('hide');
// フェードアウト終了後に要素を消したければ、以下も追加できます:
toast.addEventListener('animationend', function onEnd(e) {
if (e.animationName === 'toast-fade-out') {
toast.removeEventListener('animationend', onEnd);
toast.remove();
}
});
}, duration);
}
// クリック時に呼び出し(変更不要)
document.querySelectorAll('a.flink').forEach(a => {
a.addEventListener('click', () => {
showToast('処理準備中', 2000);
});
});
const explorerFolderUri = dirPathWin.toLowerCase().startsWith('explorer:')
? dirPathWin
: `explorer:${dirPathWin}`;
style.css
:root {
--bg-main: #f4f6f8;
--bg-sidebar: #ffffff;
--border-soft: #e3e6ea;
--text-main: #2b2f33;
--text-sub: #6b7280;
--accent: #2563eb;
--hover-bg: #f1f5ff;
}
/* =========================================
全体の定義
========================================= */
body {
margin: 0;
font-family: "Segoe UI", "Noto Sans JP", system-ui, sans-serif;
color: var(--text-main);
background: var(--bg-main);
}
.page-wrapper {
display: flex;
flex-direction: row-reverse; /* 右サイドバー */
max-width: 1200px; /* ★ ayamanual感の核 */
margin: 32px auto; /* ★ 中央寄せ+上下余白 */
gap: 32px; /* ★ メインとサイドの距離 */
}
/* =========================================
ヘッダーの定義
========================================= */
.site-header {
background: #222;
height: 56px;
color: #fff;
}
.header-inner {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
height: 100%;
display: flex;
align-items: center;
}
.site-logo {
font-size: 20px;
font-weight: 700;
color: #fff;
text-decoration: none;
margin-right: 32px;
}
.site-logo:hover {
opacity: 0.85;
}
.main-nav ul {
display: flex; /* 横並び */
gap: 24px; /* メニュー間隔 */
list-style: none; /* ● を消す */
margin: 0;
padding: 0;
}
.main-nav li {
margin: 0; /* liの余計な余白を消す */
padding: 0;
}
.main-nav a {
color: #e5e7eb;
text-decoration: none;
font-size: 14px;
line-height: 56px; /* ヘッダー中央揃え */
}
.main-nav a:hover {
color: #ffffff;
}
.header-right {
margin-left: auto;
}
.header-btn {
background: transparent;
border: none;
color: #fff;
font-size: 20px;
cursor: pointer;
}
/* =========================================
サイドバーの定義
========================================= */
.sidebar {
width: 260px;
background: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 8px;
padding: 20px 18px;
box-shadow: 0 2px 8px rgba(0,0,0,0.04);
}
.sidebar-box {
margin-bottom: 26px;
}
.sidebar-box h3 {
font-size: 13px;
font-weight: 600;
color: var(--text-sub);
margin-bottom: 10px;
letter-spacing: .03em;
}
.sidebar-box ul {
list-style: none;
padding: 0;
margin: 0;
}
.sidebar-box li {
margin-bottom: 4px;
}
.sidebar-box a {
display: block;
padding: 8px 10px;
border-radius: 8px;
text-decoration: none;
color: var(--text-main);
font-size: 14px;
transition: background .15s ease, color .15s ease;
}
.sidebar-box a:hover {
background: var(--hover-bg);
color: var(--accent);
}
.content-wrapper {
flex: 1;
background: #ffffff;
padding: 32px 36px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
}
.main {
max-width: 900px;
}
.head-i {
font-size: 18px;
margin: 26px 0 12px;
padding-left: 10px;
border-left: 4px solid var(--accent);
}
.main a {
color: var(--accent);
text-decoration: none;
}
.main a:hover {
text-decoration: underline;
}
/* ==========================
スマホ:1カラム&横いっぱい
========================== */
@media (max-width: 900px) {
.page-wrapper {
flex-direction: column;
max-width: none;
margin: 0;
gap: 0;
}
/* コンテンツを先に */
.content-wrapper {
order: 1;
width: 100%;
margin: 0;
border-radius: 0;
box-shadow: none;
padding: 20px 16px;
}
/* ★ ここが重要 */
#sidebar-placeholder {
order: 2;
}
.sidebar {
width: 100%;
margin: 0;
border-radius: 0;
box-shadow: none;
border-left: none;
border-top: 1px solid #e5e7eb;
padding: 16px;
}
}
コメント