Day 83:HTML・CSS作成
Day 83では、JavaScriptを書く前に、アプリの画面の骨組みと見た目を作ります。前回の画面設計をもとに、レイアウト、入力フォーム、ボタン、学習記録の一覧をHTMLとCSSで形にします。
この段階では、ボタンを押して記録を保存したり、一覧を自動更新したりする機能はまだ作りません。まず画面の部品をそろえ、入力欄や一覧の配置が使いやすいかを確認します。
今日の作業順
次の順番で進めます。
- プロジェクトのファイルを用意します。
- HTMLで画面の構造を作ります。
- CSSでレイアウトや見た目を整えます。
- 画面幅を変えて、スマートフォンでも使えるか確認します。
- JavaScriptから操作する要素に、わかりやすい`id`を付けておきます。
ステップ1:ファイルを用意する
まず、次のようなフォルダー構成を用意します。
study-record-app/
├── index.html
└── styles.css
今回はHTMLとCSSだけを作ります。JavaScriptファイルは、次回以降に追加できます。
ステップ2:HTMLで画面の構造を作る
index.htmlを作成し、次のコードを記述します。画面設計で決めた入力項目と一覧を、HTML要素に置き換えています。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<!-- スマートフォンでも画面幅に合わせて表示する -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>学習管理アプリ</title>
<!-- CSSファイルを読み込む -->
<link rel="stylesheet" href="./styles.css">
</head>
<body>
<main class="app">
<!-- アプリの名前と目的を伝える部分 -->
<header class="app-header">
<p class="eyebrow">STUDY TRACKER</p>
<h1>学習管理アプリ</h1>
<p class="app-description">
学習した内容と時間を記録して、日々の積み重ねを振り返りましょう。
</p>
</header>
<!-- 学習記録を入力するフォーム -->
<section class="panel" aria-labelledby="form-heading">
<h2 id="form-heading">学習を記録する</h2>
<form id="study-form">
<div class="form-field">
<label for="study-title">学習内容</label>
<input
id="study-title"
name="title"
type="text"
maxlength="100"
placeholder="例:JavaScriptの配列"
required
>
</div>
<div class="form-grid">
<div class="form-field">
<label for="study-minutes">学習時間(分)</label>
<input
id="study-minutes"
name="minutes"
type="number"
min="1"
step="1"
placeholder="例:45"
required
>
</div>
<div class="form-field">
<label for="study-date">学習日</label>
<input
id="study-date"
name="date"
type="date"
required
>
</div>
</div>
<div class="form-field">
<label for="study-note">メモ <span class="optional">任意</span></label>
<textarea
id="study-note"
name="note"
rows="3"
maxlength="500"
placeholder="学んだことや、あとで復習したいこと"
></textarea>
</div>
<button class="button button-primary" type="submit">
記録する
</button>
</form>
<!-- JavaScript追加後に入力エラーや保存結果を表示する場所 -->
<p
id="status-message"
class="status-message"
role="status"
aria-live="polite"
></p>
</section>
<!-- 合計時間と学習記録を表示する部分 -->
<section class="panel" aria-labelledby="history-heading">
<div class="history-header">
<div>
<p class="eyebrow">YOUR PROGRESS</p>
<h2 id="history-heading">学習履歴</h2>
</div>
<!-- JavaScript追加後に合計時間を更新する -->
<p id="total-time" class="total-time">
合計 <strong>70</strong> 分
</p>
</div>
<!-- 記録がない場合にJavaScriptで表示する案内 -->
<p id="empty-message" class="empty-message" hidden>
まだ記録がありません。最初の学習内容を入力してみましょう。
</p>
<!-- 最初は画面確認用のサンプル記録を表示する -->
<ul id="study-list" class="study-list">
<li class="study-item">
<div class="study-item-content">
<h3>JavaScriptの配列</h3>
<p class="study-meta">2026年11月8日 ・ 40分</p>
<p class="study-note">mapとfilterを復習しました。</p>
</div>
<!-- 削除機能は後の学習でJavaScriptから追加する -->
<button
class="button button-danger"
type="button"
aria-label="JavaScriptの配列の記録を削除"
>
削除
</button>
</li>
<li class="study-item">
<div class="study-item-content">
<h3>関数の復習</h3>
<p class="study-meta">2026年11月7日 ・ 30分</p>
<p class="study-note">引数と戻り値を確認しました。</p>
</div>
<!-- このボタンも、現時点では見た目だけのもの -->
<button
class="button button-danger"
type="button"
aria-label="関数の復習の記録を削除"
>
削除
</button>
</li>
</ul>
</section>
<footer class="app-footer">
<p>学習記録は自分のペースで続けていきましょう。</p>
</footer>
</main>
</body>
</html>
ここでは、入力欄にlabelを付けています。labelのforと入力欄のidを一致させると、項目名をクリックしたときに対応する入力欄へ移動できます。画面読み上げを使う場合にも、入力項目の意味が伝わりやすくなります。
requiredやmin、maxlengthは、ブラウザーが入力を確認するためのHTML属性です。ただし、これだけでアプリ全体の入力チェックが完成するわけではありません。次のJavaScript作成時には、JavaScript側でも必要な確認を行います。
ステップ3:CSSでレイアウトを整える
styles.cssを作成し、次のコードを記述します。全体の幅、パネル、フォーム、ボタン、一覧の見た目を整えています。
/* 余白や幅の計算を扱いやすくする */
* {
box-sizing: border-box;
}
/* ページ全体の基本設定 */
body {
margin: 0;
min-height: 100vh;
background: #f4f7fb;
color: #202b3c;
font-family:
system-ui,
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
sans-serif;
line-height: 1.6;
}
/* アプリ全体の幅と上下の余白 */
.app {
width: min(100% - 32px, 760px);
margin: 0 auto;
padding: 48px 0 24px;
}
/* アプリ名と説明 */
.app-header {
margin-bottom: 28px;
}
.eyebrow {
margin: 0 0 6px;
color: #5268c8;
font-size: 0.78rem;
font-weight: 700;
letter-spacing: 0.12em;
}
h1,
h2,
h3,
p {
margin-top: 0;
}
h1 {
margin-bottom: 8px;
font-size: clamp(1.8rem, 5vw, 2.4rem);
line-height: 1.2;
}
h2 {
margin-bottom: 18px;
font-size: 1.25rem;
}
h3 {
margin-bottom: 4px;
font-size: 1rem;
}
.app-description {
max-width: 58ch;
margin-bottom: 0;
color: #596579;
}
/* 入力フォームや履歴を囲むパネル */
.panel {
margin-bottom: 20px;
padding: 24px;
border: 1px solid #e2e8f0;
border-radius: 16px;
background: #ffffff;
box-shadow: 0 8px 24px rgb(32 43 60 / 5%);
}
/* フォーム内の項目を縦に並べる */
#study-form {
display: grid;
gap: 16px;
}
/* ラベルと入力欄をまとめる */
.form-field {
display: grid;
gap: 6px;
}
.form-field label {
font-size: 0.92rem;
font-weight: 650;
}
.optional {
margin-left: 4px;
color: #68758a;
font-size: 0.8rem;
font-weight: 400;
}
/* 入力欄の基本デザイン */
input,
textarea {
width: 100%;
padding: 11px 12px;
border: 1px solid #cbd5e1;
border-radius: 9px;
background: #ffffff;
color: #202b3c;
font: inherit;
}
textarea {
resize: vertical;
}
/* 入力欄を選択していることが分かるようにする */
input:focus,
textarea:focus,
button:focus-visible {
outline: 3px solid rgb(82 104 200 / 28%);
outline-offset: 2px;
border-color: #5268c8;
}
/* 学習時間と日付を横並びにする */
.form-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
}
/* ボタンの共通デザイン */
.button {
min-height: 42px;
padding: 9px 14px;
border: 0;
border-radius: 9px;
font: inherit;
font-weight: 650;
cursor: pointer;
}
/* 主な操作ボタン */
.button-primary {
justify-self: start;
background: #5268c8;
color: #ffffff;
}
.button-primary:hover {
background: #4055b3;
}
/* 削除ボタン */
.button-danger {
flex: 0 0 auto;
border: 1px solid #f0caca;
background: #fff7f7;
color: #a83232;
}
.button-danger:hover {
background: #ffeded;
}
/* JavaScriptから案内文を設定する場所 */
.status-message {
min-height: 1.5em;
margin: 12px 0 0;
color: #4055b3;
}
/* 履歴見出しと合計時間を左右に配置する */
.history-header {
display: flex;
align-items: end;
justify-content: space-between;
gap: 16px;
}
.history-header h2 {
margin-bottom: 0;
}
.total-time {
margin-bottom: 0;
color: #5268c8;
white-space: nowrap;
}
.total-time strong {
font-size: 1.4rem;
}
/* 学習記録の一覧 */
.study-list {
display: grid;
gap: 12px;
margin: 20px 0 0;
padding: 0;
list-style: none;
}
/* 一件分の学習記録 */
.study-item {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
padding: 16px;
border: 1px solid #e2e8f0;
border-radius: 12px;
}
.study-item-content {
min-width: 0;
}
.study-meta {
margin-bottom: 4px;
color: #596579;
font-size: 0.88rem;
}
.study-note {
margin-bottom: 0;
color: #38465a;
overflow-wrap: anywhere;
}
/* 記録がないときの案内 */
.empty-message {
margin: 20px 0 0;
padding: 16px;
border-radius: 10px;
background: #f4f7fb;
color: #596579;
}
/* ページ下部の補足 */
.app-footer {
padding: 8px 0;
color: #68758a;
font-size: 0.88rem;
text-align: center;
}
/* 画面幅が狭い場合のレイアウト */
@media (max-width: 560px) {
.app {
width: min(100% - 24px, 760px);
padding-top: 28px;
}
.panel {
padding: 18px;
}
/* 小さな画面ではフォーム項目を縦に並べる */
.form-grid {
grid-template-columns: 1fr;
}
/* 一覧の内容と削除ボタンを縦方向に配置する */
.study-item {
align-items: flex-start;
flex-direction: column;
}
/* 履歴見出しと合計を縦に並べる */
.history-header {
align-items: flex-start;
flex-direction: column;
}
}
ステップ4:画面をブラウザーで確認する
index.htmlをブラウザーで開き、次の点を確認します。
- アプリ名と説明が読みやすく表示されますか。
- 各入力欄に項目名が付いていますか。
- フォーム、合計時間、一覧の順番が自然ですか。
- ボタンの文字が見やすく、押せることが分かりますか。
- 画面を狭くしたとき、入力欄や一覧が画面からはみ出しませんか。
- キーボードのTabキーで入力欄やボタンを順番に選べますか。
この時点では、記録ボタンや削除ボタンを押してもデータは変化しません。ボタンと入力欄が配置されていることを確認する段階です。動作は次回以降にJavaScriptで実装します。
なぜ先にHTMLとCSSを作るのか
JavaScriptを書く前に画面を作ると、必要な入力欄や表示場所が具体的になります。HTMLにidを付けておけば、JavaScriptからどの要素を取得するかも明確です。
- HTMLは、見出し、フォーム、ボタン、一覧など画面の構造を表します。
- CSSは、配置、色、余白、文字サイズなど見た目を整えます。
- JavaScriptは、入力への反応、記録の追加・削除、表示の更新など動作を担当します。
役割を分けると、表示の修正と機能の修正を区別しやすくなります。
重要な注意点
ボタンの種類を正しく使う
フォームの送信に使うボタンにはtype="submit"を指定します。削除ボタンのようにフォーム送信ではない操作にはtype="button"を指定しています。フォーム内のボタンは、種類を省略すると送信ボタンとして扱われることがあるため、目的に合わせて明示しましょう。
JavaScriptを追加するまでは、送信ボタンを押すとページが再読み込みされる場合があります。これは今回の段階では想定内です。次回以降にフォーム送信イベントを受け取り、ページ再読み込みを防ぐ処理を追加します。
入力値をHTMLに直接埋め込まない
あとでJavaScriptを追加すると、利用者が入力した学習内容やメモを一覧へ表示します。その際、入力文字列をHTMLとして挿入するのではなく、文字列として表示する方法を使います。入力内容をそのまま実行可能なHTMLとして扱わないことが、安全な画面更新の基本です。
サンプルデータは画面確認用
HTML内の「JavaScriptの配列」や「関数の復習」は、現時点でレイアウトを確認するためのサンプルです。JavaScriptでデータ表示を実装するときには、この固定表示を削除し、保存データから一覧を作る設計に切り替えます。
Day 83のゴール
Day 83では、次の状態を目指します。
- HTMLでフォーム、ボタン、一覧を配置できています。
- CSSで画面幅や余白、文字、ボタンを整えています。
- スマートフォン程度の幅でも、内容が読みやすく表示されます。
- JavaScriptから操作する要素に、意味の分かる`id`が付いています。
- 入力欄やボタンの役割が、画面上で利用者に伝わります。
まとめ
Day 83では、JavaScriptを書く前に、学習管理アプリのレイアウト、入力フォーム、ボタン、一覧表示をHTMLとCSSで作りました。HTMLで画面の構造を用意し、CSSで見やすさや画面幅への対応を整えます。
この段階では、ボタンに機能がなくても問題ありません。まず画面の部品がそろい、利用者が何を入力し、どこに結果が表示されるかが分かる状態にします。
