📝

操作系ページHTMLテンプレ

2025/01/08に公開

https://zenn.dev/20230830/articles/0b91102b6288cc
のつづき

ポイント

  • サイト用ヘッダ、フッタがあること
  • ページ用ヘッダがあること
  • レスポンシブ対応であること
  • CDN利用であること
<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>操作系サンプル</title>
  <!-- Google Fonts -->
  <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet" />
  <!-- Bootstrap CSS -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" />
  <style>
    /* ベースフォントと背景 */
    body {
      font-family: "Roboto", sans-serif;
      background-color: #f5f7f9;
      margin: 0;
      padding: 0;
    }

    /* Flexboxでフッタ固定 */
    .page-wrapper {
      display: flex;
      flex-direction: column;
      min-height: 100vh;
    }

    .content-wrapper {
      flex: 1;
      display: flex;
    }

    /* ===== 全体ヘッダー ===== */
    .site-header {
      background: linear-gradient(135deg, #2c3e50, #3a6073);
      color: #fff;
      padding: 15px 20px;
      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    }

    .site-header h1 {
      font-size: 1.5rem;
      margin: 0;
    }

    .site-header nav a {
      color: #fff;
      text-decoration: none;
      margin-right: 15px;
      transition: opacity 0.2s ease;
    }

    .site-header nav a:hover {
      opacity: 0.8;
    }

    /* ===== ページ固有のヘッダー ===== */
    .page-header {
      background-color: #e9ecef;
      padding: 15px 20px;
      margin-bottom: 0;
    }

    .page-header h2 {
      margin: 0 0 8px 0;
      font-size: 2rem;
    }

    .page-header p {
      margin: 0;
      color: #6c757d;
    }

    /* ===== ペインエリア ===== */
    .left-pane,
    .right-pane {
      padding: 10px;
      background-color: #fff;
      height: auto;
    }

    .left-pane {
      border-right: 1px solid #dee2e6;
    }

    .right-pane {
      border-left: 1px solid #dee2e6;
    }

    /* ===== メインコンテンツ ===== */
    .content {
      padding: 10px;
      background-color: #fff;
      margin: 0;
      flex: 1;
      /* 余ったスペースを占有 */
    }

    /* ===== フォーム ===== */
    .operation-form {
      max-width: 600px;
      margin: 0 auto;
    }

    .operation-form .form-label {
      font-weight: 700;
    }

    /* ===== フッター ===== */
    .footer {
      background-color: #2c3e50;
      color: #fff;
      text-align: center;
      padding: 15px 0;
    }

    .footer a {
      color: #fff;
      text-decoration: none;
      margin: 0 5px;
      transition: opacity 0.2s ease;
    }

    .footer a:hover {
      opacity: 0.8;
    }

    /* ===== トースト通知 ===== */
    .toast-container {
      position: fixed;
      top: 20px;
      right: 20px;
      z-index: 1050;
    }
  </style>
</head>

<body>
  <div class="page-wrapper">
    <!-- ===== サイト全体のヘッダー ===== -->
    <header class="site-header">
      <div class="container-fluid d-flex justify-content-between align-items-center">
        <h1 class="mb-0">サイトロゴ</h1>
        <nav>
          <a href="#">ホーム</a>
          <a href="#">ブログ</a>
          <a href="#">お問い合わせ</a>
        </nav>
      </div>
    </header>

    <!-- ===== ページ固有のヘッダー ===== -->
    <header class="page-header">
      <div class="container-fluid">
        <h2>操作系ページ</h2>
        <p class="text-muted">
          フォーム入力やデータ操作など、インタラクティブな機能を提供します。
        </p>
      </div>
    </header>

    <div class="content-wrapper container-fluid">
      <div class="row flex-grow-1">
        <!-- 左ペイン: ナビゲーション -->
        <nav class="col-md-2 left-pane"></nav>

        <!-- 中央ペイン: メインコンテンツ -->
        <main class="col-md-8 content">
          <!-- 通知エリア -->
          <div id="notification-area" class="mb-4">
            <!-- 成功メッセージ -->
            <div id="successMessage" class="alert alert-success alert-dismissible fade show" role="alert">
              <span id="successMessageText">フォームが正常に送信されました。</span>
              <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="閉じる"></button>
            </div>
            <!-- 失敗メッセージ -->
            <div class="alert alert-danger alert-dismissible fade show" role="alert">
              <span id="alertMessageText">送信中にエラーが発生しました。再度お試しください。</span>
              <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="閉じる"></button>
            </div>
          </div>
          <div class="operation-form">
            <div class="mb-4 mt-3">
              <h1 class="display-5">お問い合わせフォーム</h1>
              <p class="text-muted">必要事項をご記入の上、送信ボタンを押してください。</p>
            </div>
            <form onsubmit="handleSubmit(event)">
              <div class="mb-3">
                <label for="inputName" class="form-label">お名前</label>
                <input type="text" class="form-control" id="inputName" placeholder="お名前を入力" required />
              </div>
              <div class="mb-3">
                <label for="inputEmail" class="form-label">メールアドレス</label>
                <input type="email" class="form-control" id="inputEmail" placeholder="メールアドレスを入力" required />
              </div>
              <div class="mb-3">
                <label for="inputMessage" class="form-label">お問い合わせ内容</label>
                <textarea class="form-control" id="inputMessage" rows="4" placeholder="ご用件を入力" required></textarea>
              </div>
              <button type="submit" class="btn btn-primary w-100">送信</button>
            </form>
          </div>
        </main>

        <!-- 右ペイン: 関連コンテンツ -->
        <aside class="col-md-2 right-pane">
          <h5 class="mb-3">入力方法・注意点</h5>
          <ul class="list-unstyled">
            <li class="mb-2">
              <strong>お名前:</strong> フルネームを入力してください。
            </li>
            <li class="mb-2">
              <strong>メールアドレス:</strong> 有効な形式でご入力ください。
            </li>
            <li class="mb-2">
              <strong>お問い合わせ内容:</strong> 詳細にご記入ください。
            </li>
          </ul>
          <div class="alert alert-info" role="alert">
            <p>
              必要事項を入力後、「送信」ボタンを押してください。</p>
            <p>
              フォーム送信後、通知が表示されます。</p>
          </div>

          <h5 class="mb-3">関連コンテンツ</h5>
          <ul class="list-unstyled">
            <li><a href="#">関連記事 1</a></li>
            <li><a href="#">関連記事 2</a></li>
          </ul>
        </aside>
      </div>
    </div>

    <!-- ===== サイト全体のフッター ===== -->
    <footer class="footer">
      <p class="mb-2">&copy; 2025 サイト名. All rights reserved.</p>
    </footer>
  </div>

  <!-- トースト通知 -->
  <div class="toast-container">
    <div id="successToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true" data-bs-delay="3000">
      <div class="toast-header">
        <strong class="me-auto text-success">成功</strong>
        <small>今</small>
        <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="閉じる"></button>
      </div>
      <div class="toast-body">
        お問い合わせ内容が送信されました。
      </div>
    </div>
  </div>

  <!-- Bootstrap JS -->
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
  <script>
    function handleSubmit(event) {
      event.preventDefault();

      // 通知エリアを取得
      const notificationArea = document.getElementById("notification-area");

      // 成功メッセージ要素を作成(必要に応じて再利用可能)
      const successAlert = document.getElementById("successMessage");

      if (!successAlert) {
        // 初回のみ成功メッセージ要素を作成
        successAlert = document.createElement("div");
        successAlert.id = "successMessage";
        successAlert.className = "alert alert-success alert-dismissible fade show";
        successAlert.setAttribute("role", "alert");

        // メッセージ部分を作成
        const messageText = document.createElement("span");
        messageText.id = "successMessageText";
        messageText.textContent = "フォームが正常に送信されました";
        successAlert.appendChild(messageText);

        // 閉じるボタンを追加
        const closeButton = document.createElement("button");
        closeButton.type = "button";
        closeButton.className = "btn-close";
        closeButton.setAttribute("data-bs-dismiss", "alert");
        closeButton.setAttribute("aria-label", "閉じる");
        successAlert.appendChild(closeButton);

        // 通知エリアに追加
        notificationArea.appendChild(alertDiv);
      } else {
        // メッセージを更新(再利用する場合)
        const messageText = document.getElementById("successMessageText");
        if (messageText) {
          messageText.textContent = "フォームが正常に送信されました。";
        }
      }

      // トースト通知を表示
      const toastElement = document.getElementById("successToast");
      const toast = new bootstrap.Toast(toastElement);
      toast.show();
    }
  </script>
</body>

</html>

Discussion