diff --git a/html-css-slide/README.md b/html-css-slide/README.md new file mode 100644 index 00000000..08e23914 --- /dev/null +++ b/html-css-slide/README.md @@ -0,0 +1,28 @@ +# HTML/CSS を始めよう — Web ページの構造と見た目 + +> この資料は jig.jp のインターン/勉強会向けに作成されたものです。 + +## 目的 + +HTML(構造)・CSS(見た目)・JavaScript(動き)の役割を、**スライド内の実行環境で手を動かしながら**学びます。 + +元になった自習用ドキュメント([jigintern/intern-dev-tutorial の html-css](https://github.com/jigintern/intern-dev-tutorial/blob/main/html-css/DOCS.md))を、勉強会向けに再構成したものです。 + +## 対象 + +- プログラミング/Web 開発の初学者 +- 特別な前提知識は不要です + +## 準備 + +- **ブラウザだけで OK**。スライド内の「▶ 実行」できるコード欄でその場で試せます +- インストールは不要 + +## 困ったときは + +- 質問がある場合、スライド右下の通し番号(章節)といっしょに質問してもらえると対応しやすいです。 + +## 本編 + +- [markdown版](./slide.md) +- [HTML版](https://jigintern.github.io/study_session_materials/html-css-start-2026/slide.html) diff --git a/html-css-slide/imgs/box-model-in-art.png b/html-css-slide/imgs/box-model-in-art.png new file mode 100644 index 00000000..d993959a Binary files /dev/null and b/html-css-slide/imgs/box-model-in-art.png differ diff --git a/html-css-slide/imgs/open-dev-tool.png b/html-css-slide/imgs/open-dev-tool.png new file mode 100644 index 00000000..5895737a Binary files /dev/null and b/html-css-slide/imgs/open-dev-tool.png differ diff --git a/html-css-slide/imgs/show-conputed-tab.gif b/html-css-slide/imgs/show-conputed-tab.gif new file mode 100644 index 00000000..3081db8e Binary files /dev/null and b/html-css-slide/imgs/show-conputed-tab.gif differ diff --git a/html-css-slide/imgs/usually-website-layout-with-description.png b/html-css-slide/imgs/usually-website-layout-with-description.png new file mode 100644 index 00000000..6c4bea21 Binary files /dev/null and b/html-css-slide/imgs/usually-website-layout-with-description.png differ diff --git a/html-css-slide/imgs/visbug-guide-tool.gif b/html-css-slide/imgs/visbug-guide-tool.gif new file mode 100644 index 00000000..dfda4518 Binary files /dev/null and b/html-css-slide/imgs/visbug-guide-tool.gif differ diff --git a/html-css-slide/rehearsal/README.md b/html-css-slide/rehearsal/README.md new file mode 100644 index 00000000..ad26330e --- /dev/null +++ b/html-css-slide/rehearsal/README.md @@ -0,0 +1,66 @@ +# リハーサル計測 + +スライドを通しで読んだときの所要時間を、章ごと・スライドごとに記録するためのブックマークレットです。 + +読み上げながらページを送るだけで記録が残ります。 +リハーサル中に操作を足す必要はありません。 + +## 準備 + +ブックマークを 1 つ作り、URL 欄に [bookmarklet.txt](./bookmarklet.txt) の中身をそのまま貼り付けます。 +名前は「リハ計測」など分かるものにしてください。 + +`javascript:` で始まる長い 1 行ですが、途中で改行せずに全体を貼れば動きます。 + +## 使い方 + +1. スライドを開きます。ローカルの `slide.html` でも、公開されている HTML 版でも構いません。 +2. ブックマーク「リハ計測」をクリックします。右上に `REC` のバッジが出れば記録中です。 +3. いつもどおりスライドを送ります。 +4. 読み終えたら Ctrl+Shift+E を押します。Markdown ファイルがダウンロードされ、同じ内容がクリップボードにも入ります。 +5. ダウンロードしたファイルを [records/](./records/) に置いてコミットします。 + +## キー操作 + +- Ctrl+Shift+E — 記録を Markdown で書き出します +- Ctrl+Shift+P — 一時停止と再開を切り替えます (右上のバッジをクリックしても同じです) +- Ctrl+Shift+X — 記録を破棄して最初から測り直します + +休憩スライドで止まるときや、途中で中断するときは一時停止してください。 +止めていた時間は所要時間から除かれます。 + +## 記録される内容 + +書き出される Markdown は 2 段構えです。 + +章ごとの表には、章の所要時間と、通しの何分時点でその章に入ったかが並びます。 +資料冒頭の「所要時間目安: 180 分」と突き合わせるのはこちらです。 + +スライドごとの表には、1 枚あたりの滞在時間と訪問回数が並びます。 +どの節で時間を使ったかを追うのはこちらです。 +戻って読み直したスライドは訪問回数が 2 以上になり、滞在時間は合算されます。 + +章の区切りは、スライドの h1 見出しから自動で判定します。 +`# Chapter 1` のように h1 を置いたスライドが章の扉として扱われるため、章を増やしても設定を直す必要はありません。 + +## 途中で閉じてしまったとき + +記録は 5 秒ごとにブラウザの localStorage へ保存しています。 +同じスライドをもう一度開いてブックマークレットを起動すると、続きから記録するか、破棄して最初からやり直すかを聞かれます。 + +保存は URL のパスごとに分かれています。 +ローカルの `slide.html` と公開版の記録は混ざりません。 + +## bookmarklet.js を編集したとき + +`bookmarklet.txt` は `bookmarklet.js` から生成しています。 +ソースを直したら再生成して、ブックマークに貼り直してください。 + +```sh +node rehearsal/build.mjs +``` + +## 発表練習(読み上げ台本) + +このフォルダの [`transcript/`](./transcript/) には、`slide.md` から起こした「講師の話し言葉」の台本を置きます。 +`say` コマンドで読み上げて発表練習ができます。作り方と使い方は [`transcript/README.md`](./transcript/README.md) を参照してください。 diff --git a/html-css-slide/rehearsal/build-notes.mjs b/html-css-slide/rehearsal/build-notes.mjs new file mode 100644 index 00000000..524bf24b --- /dev/null +++ b/html-css-slide/rehearsal/build-notes.mjs @@ -0,0 +1,120 @@ +/* + * slide.md と rehearsal/transcript/*.md から、発表者ノート入りの slide.notes.md を生成します。 + * + * node rehearsal/build-notes.mjs # このスクリプトのある教材に対して実行 + * node rehearsal/build-notes.mjs <教材dir> # 別教材を指定(例: 2026/shinkei-suijaku) + * + * transcript の各ブロック(## 見出し)を、slide.md の「同じ見出し」のスライドに + * 発表者ノート(HTML コメント)として差し込みます。 + * → 見出しは transcript 側で、スライドの見出しを一字一句そのままコピーしておくのが前提です + * (transcript/README.md の「生成ルール」を参照)。 + * + * 生成した slide.notes.md を marp でビルドし、ブラウザで P キーを押すと + * 発表者ビューに台本が表示されます(投影スライドには出ません)。 + */ +import { readFileSync, writeFileSync, readdirSync, existsSync } from 'node:fs'; +import { dirname, join, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const scriptDir = dirname(fileURLToPath(import.meta.url)); // .../rehearsal +const arg = process.argv[2]; +const materialDir = arg ? resolve(arg) : dirname(scriptDir); +const rehearsalDir = arg ? join(materialDir, 'rehearsal') : scriptDir; +const transcriptDir = join(rehearsalDir, 'transcript'); +const slidePath = join(materialDir, 'slide.md'); +const outPath = join(materialDir, 'slide.notes.md'); + +// 見出しの表記ゆれ(全角半角・空白・末尾記号・強調)を吸収して比較するためのキー。 +const norm = s => + s.normalize('NFKC').replace(/[`*_]/g, '').replace(/\s+/g, '').replace(/[.:。、]+$/, '').toLowerCase(); + +// スライド/ブロックの先頭見出し(コードブロック内は無視)。 +const firstHeading = block => { + let inFence = false; + for (const line of block.split(/\r?\n/)) { + if (/^```/.test(line)) { inFence = !inFence; continue; } + if (inFence) continue; + const m = line.match(/^#{1,6}\s+(.*\S)\s*$/); + if (m) return m[1]; + } + return null; +}; + +if (!existsSync(transcriptDir)) { + console.error('transcript/ が見つかりません: ' + transcriptDir); + process.exit(1); +} +if (!existsSync(slidePath)) { + console.error('slide.md が見つかりません: ' + slidePath); + process.exit(1); +} + +// --- transcript を「## 見出し」ブロックに分解 --- +const files = readdirSync(transcriptDir).filter(f => /^\d{2}-.*\.md$/.test(f)).sort(); +const blocks = []; // { heading, note } +for (const f of files) { + const text = readFileSync(join(transcriptDir, f), 'utf8'); + for (const part of text.split(/^(?=##\s)/m)) { + const m = part.match(/^##\s+(.*\S)\s*$/m); + if (!m) continue; // 先頭の「# タイトル」や「> 前書き」は無視 + const note = part.replace(/^##\s+.*$/m, '').trim(); + if (note) blocks.push({ heading: m[1], note }); + } +} +const noteByHeading = new Map(); +for (const b of blocks) { + const k = norm(b.heading); + if (!noteByHeading.has(k)) noteByHeading.set(k, []); + noteByHeading.get(k).push(b.note); +} + +// --- slide.md を frontmatter + スライド配列に分解 --- +const lines = readFileSync(slidePath, 'utf8').split(/\r?\n/); +let fmEnd = -1; +if (lines[0].trim() === '---') { + for (let i = 1; i < lines.length; i++) { + if (lines[i].trim() === '---') { fmEnd = i; break; } + } +} +const frontmatter = fmEnd >= 0 ? lines.slice(0, fmEnd + 1).join('\n') : ''; +const body = (fmEnd >= 0 ? lines.slice(fmEnd + 1) : lines).join('\n'); +const slides = body.split(/^---$/m); + +// --- 各スライドにノートを差し込む --- +const used = new Set(); +let matched = 0; +const unmatchedSlides = []; +const merged = slides.map(slide => { + const h = firstHeading(slide); + if (!h) return slide; + const q = noteByHeading.get(norm(h)); + if (q && q.length) { + // HTML コメントを閉じてしまう "--" を全角ダッシュに置換してから差し込む。 + const note = q.shift().replace(/-{2,}/g, '—'); + matched++; + used.add(norm(h)); + return slide.replace(/\s*$/, '') + `\n\n\n`; + } + unmatchedSlides.push(h); + return slide; +}); + +writeFileSync(outPath, (frontmatter ? frontmatter + '\n' : '') + merged.join('---')); + +// --- レポート --- +const withHeading = slides.filter(s => firstHeading(s)).length; +const leftover = blocks.filter(b => !used.has(norm(b.heading))).map(b => b.heading); +const rel = arg ? arg.replace(/\/$/, '') + '/' : ''; +console.log(`生成しました: ${outPath}`); +console.log(`スライド ${slides.length} 枚(見出しあり ${withHeading} 枚)/ ノートを差し込めた: ${matched} 枚`); +if (unmatchedSlides.length) { + console.log(`\n台本が見つからなかったスライド (${unmatchedSlides.length}) — transcript 側の見出しをスライドに合わせると埋まります:`); + unmatchedSlides.forEach(h => console.log(' - ' + h)); +} +if (leftover.length) { + console.log(`\nどのスライドにも一致しなかった台本ブロック (${leftover.length}):`); + leftover.forEach(h => console.log(' - ' + h)); +} +console.log(`\n次のコマンドで発表者ノート付き HTML を作成:`); +console.log(` pnpm exec marp ${rel}slide.notes.md --html -o ${rel}slide.notes.html --allow-local-files`); +console.log(` → ブラウザで開き、P キーで発表者ビュー(台本が表示されます)`); diff --git a/html-css-slide/rehearsal/records/.gitkeep b/html-css-slide/rehearsal/records/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/html-css-slide/rehearsal/transcript/README.md b/html-css-slide/rehearsal/transcript/README.md new file mode 100644 index 00000000..75e6f80f --- /dev/null +++ b/html-css-slide/rehearsal/transcript/README.md @@ -0,0 +1,98 @@ +# 発表文字起こし(読み上げ用台本) + +このフォルダには、**完成した `slide.md` を元にした「講師の話し言葉」の台本**を置きます。 +macOS の `say` コマンドで読み上げれば、授業を受けている感覚で聞けて、**発表練習**にも使えます。 + +台本は Claude に生成してもらう前提です。以下はその**指示書**と、`say` での練習方法です。 + +--- + +## 使い方(3 ステップ) + +1. `slide.md` を仕上げる(`{{ }}` プレースホルダを残さない)。 +2. Claude に台本を生成してもらう(下の「Claude への依頼」)。 +3. `say` で読み上げて練習する(下の「say で発表練習」)。 + +--- + +## Claude への依頼(コピペ用) + +Claude に次のように頼んでください(このファイルを指し示すだけでも動きます)。 + +``` +rehearsal/transcript/README.md の「生成ルール」に従って、slide.md から発表用の文字起こし台本を作ってください。 +章ごとにファイルを分け、講師の話し言葉で書いてください。読み上げは自分で行うので、台本の生成だけで大丈夫です。 +``` + +Claude に頼むのは**台本の生成まで**です。`say` での読み上げは、下のコマンドを自分で実行します。 + +### 生成ルール(Claude はこれに従って書く) + +- **入力**: 一つ上の階層の `../../slide.md`。**出力**: このフォルダ(`transcript/`)に Markdown で保存。 +- **ファイル分割と命名**: スライドの章立てに合わせて、聞く順に並ぶ 2 桁プレフィックスを付ける。 + - `00-intro.md`(タイトル〜「進め方」「詰まったとき」までの導入) + - `01-chapter1.md`, `02-chapter2.md`, …(各 Chapter に 1 ファイル) + - `99-appendix.md`(完成・お疲れさま・応用課題・付録) +- **文体**: 講師の一人称の話し言葉。聞き手に語りかける丁寧語(「〜します」「〜してみましょう」)。読み上げて自然な、耳で分かる文章にする。 +- **スライドとの対応(重要)**: 台本は**スライドの並び順どおり**に書き、各ブロックの `##` 見出しには、対応するスライドの見出しを**一字一句そのままコピー**する(句読点・全角半角も変えない。例: スライドが `## 準備: StackBlitz テンプレを開こう` なら台本も同じ文字列)。こうしておくと、`build-notes.mjs` が見出しをキーにして各スライドの**発表者ノート**へ機械的に流し込めます(→「発表者ノートに流し込む」)。手元のスライドと合わせて聞くのにも役立ちます。 +- **コード**: 記号を 1 文字ずつ読み上げない。「何をしているか」を言葉で説明する(例: `getElementById("board")` →「board という id の要素を取ってくる」)。`===` は「厳密に等しいかを比べる」のように意味で言う。 +- **記号・絵文字**: 言葉にする(🍎🍌🍇 →「りんご」「ばなな」「ぶどう」)。 +- **演習タイマー**: スライドの `data-seconds` を分に直して「ここで◯分ほど時間を取ります」と案内する。 +- **休憩スライド**(`section.break`): 「ここで◯分休憩します」と案内する。 +- **各ファイルの冒頭**: タイトル(`# …`)と、`>` の 1 段落(この台本の位置づけの注記)を置く。 +- **プレースホルダ**: `slide.md` に `{{ }}` が残っている場合は題材が未確定なので、**生成せずに先に slide.md を仕上げるよう伝える**。 + +--- + +## say で発表練習 + +読み上げは自分で実行します。macOS の `say` を使います(日本語音声は `Kyoko` が手軽。全一覧は `say -v '?'`)。 + +```sh +# 1 章をそのまま読み上げる +say -v Kyoko -f 01-chapter1.md + +# 見出し(#)・区切り線(---)・引用(>)・画像行を除いてきれいに読む +sed -E 's/^#+ +//; s/^> ?//; /^---$/d; /^!\[/d' 01-chapter1.md | say -v Kyoko + +# 速度を上げる(1 分あたりの語数。既定は約 175) +say -r 210 -v Kyoko -f 01-chapter1.md + +# 全章を順に通し読み +for f in [0-9][0-9]-*.md; do echo "▶ $f"; say -v Kyoko -f "$f"; done +``` + +- 途中で止めるときは `Ctrl+C`。 +- 音声を書き出して倍速で聞くなら `say -v Kyoko -f 01-chapter1.md -o 01.aiff`。 + +--- + +## 発表者ノートに流し込む(本番用) + +台本を、スライドの**発表者ノート**に自動で差し込めます。本番では投影スライドの裏で台本を見ながら話せます。 + +```sh +# slide.md + transcript/ から、ノート入りの slide.notes.md を生成 +node rehearsal/build-notes.mjs + +# ノート入りスライドをビルド +npx marp slide.notes.md --html -o slide.notes.html --allow-local-files +``` + +- 生成された `slide.notes.html` をブラウザで開き、**P キー**で発表者ビューを開くと、各スライドに台本が表示されます(投影側には出ません)。 +- ひも付けは**見出しの一致**で行います。実行後のレポートに「台本が見つからなかったスライド」が並んだら、transcript 側の `##` 見出しをそのスライドの見出しにそろえてください(上の生成ルール参照)。 +- `slide.notes.md` / `slide.notes.html` は生成物です(`slide.md` 本体は変更しません)。コミット対象から外して構いません。 + +--- + +## 聞く順番(生成後に埋める) + +台本を作ったら、この表を実際のファイルに合わせて更新しておくと便利です。 + +| 順 | ファイル | 内容 | +| --- | -------------- | -------------------------------------------- | +| 1 | 00-intro.md | 導入(ゴール・流れ・進め方・準備) | +| 2 | 01-chapter1.md | Chapter 1 … | +| … | … | … | +| — | (休憩 ◯分) | | +| n | 99-appendix.md | 完成・応用課題・付録(あとで自分のペースで) | diff --git a/html-css-slide/slide.html b/html-css-slide/slide.html new file mode 100644 index 00000000..b19d1b90 --- /dev/null +++ b/html-css-slide/slide.html @@ -0,0 +1,1458 @@ +
文章は「かたまり」に分けると読みやすくなります。HTML では見出しと段落で構造を表します。
+<h1>〜<h6> の 6 段階<p><span>使い方のコツ <h1> はページに 1 つ / 大きさを飛ばさない(h2 の下に h3)/ 多用は 3 段階まで。
各見出しの大きさと、段落・span の違いを ▶ 実行して見比べましょう。
+<h1>見出し1(ページの題)</h1>
+<h2>見出し2</h2>
+<h3>見出し3</h3>
+<p>これは段落(p)。まとまった文章に使います。</p>
+<span>span はただの文字。見た目は変わりません。</span>
+
+項目を並べるときはリストを使います。
+<ul> … 順序が関係ない箇条書き(行頭に点)<ol> … 順序が大事な箇条書き(行頭に番号)<li>。リストの中にリストを入れる入れ子もできます記述 中身を自分の情報に書き換えて ▶ 実行。ul(点)と ol(番号)の違いを確かめましょう。
<h2>自己紹介</h2>
+<ul>
+ <li>名前: <strong>じぐ太郎</strong></li>
+ <li>好きな食べ物ランキング:
+ <ol>
+ <li>うどん</li>
+ <li>そば</li>
+ </ol>
+ </li>
+</ul>
+
+見た目ではなく「意味」で選ぶのがポイントです。
+<em> … 強調(標準では斜体で表示される)<strong> … 重要(標準では太字で表示される)「斜体にしたいだけ」「太字にしたいだけ」なら <span> + CSS を使います(意味づけタグの誤用を避ける)。
▶ 実行して、em(斜体)と strong(太字)の表示を確かめましょう。
<p>日本で <em>一番</em> 高い山は富士山です。</p>
+<p><strong>締め切りは今日です。</strong></p>
+
+画像は <img>、リンクは <a>。img は閉じタグの要らない空要素です。タグの後ろに 名前="値" の形で書く追加設定を属性と呼びます。
<img src="./icon.png" alt="アイコン" />
+<img src="https://example.com/user.png" alt="ユーザー" />
+
+<a href="https://jig.jp">株式会社 jig.jp</a>
+<a href="https://jig.jp" target="_blank">新しいタブで開く</a>
+
+src … 画像ファイルの場所(./=サイト内の相対パス/https://=外部 URL の絶対パス)alt … 画像の代替テキスト(表示できない時や読み上げ時に読まれる説明文)href … リンク先の URL(hypertext reference)/ target="_blank" … 新しいタブで開くよく見る Web ページのレイアウト(聖杯レイアウト)は、意味を表す要素で組み立てられます。
+<header> ヘッダー / <nav> ナビゲーション<main> メインコンテンツ / <aside> サイドバー<footer> フッター<div> … 意味を持たない万能の「箱」(要素をまとめて装飾)<span> … 文字用の箱
意味の合う要素を使うと、ブラウザや読み上げ機能に構造が正しく伝わります(アクセシビリティ向上)。
+チェックポイント
+head(見せない情報)と body(表示される中身)の役割を説明できる次は、この骨組みに CSS で見た目をつけていきます。
+CSS の書き方 ・ ボックスモデル ・ 優先度 ・ セレクタ ・ 疑似クラス ・ 変数 ・ 文字 ・ 背景と枠 ・ 図形
+HTML の骨組みに CSS で色・大きさ・余白・枠をつけ、見た目を仕上げます。
+CSS は どの要素を・どう飾るかを指定します。基本の形は セレクタ { プロパティ: 値; }。
この章で扱うスタイル
+color / font-size / font-weight / line-height / text-decoration / font-familybackground(-color / -image) / border / border-radiuswidth / height / padding / margin / box-sizingdisplay / cursor一覧の中の color から始めましょう。1 つのタグに 1 つのスタイルを当てるのが基本です。
h1 { color: red; } … すべての <h1> 要素の文字色を赤にする、という意味。
+セレクタ(h1)・プロパティ(color)・値(red)が 1 つずつ対応します。
次のページで、実際に色を変えて動かしてみましょう。
+<style> の中の色を変えて ▶ 実行してみましょう。
<style>
+ h1 { color: red; }
+</style>
+<h1>Hello, World !</h1>
+
+すべての要素は「額に入った絵」のように、内側から content → padding → border → margin の四角で囲まれています。
+content … 中身(文字や画像)padding … 中身と枠の間の内側の余白border … 枠線margin … 要素どうしの外側の余白
要素の幅は content + padding + border の合計です。既定の content-box では width が
+content だけを指すため、下の例では 160 + 16×2 + 4×2 = 200px に膨らみます。
+box-sizing: border-box にすると width が 枠込みになり、実寸は 160px のまま(content 側が縮む)。
現代の Web 開発では最初に * { box-sizing: border-box; } と書くのが定番です。
同じ width: 160px でも border-box の方が枠込みで収まります。▶ 実行して見比べましょう。
<style>
+ .box {
+ width: 160px;
+ padding: 16px;
+ border: 4px solid #333;
+ background: #cfd8dc;
+ margin: 6px 0;
+ }
+ .border {
+ box-sizing: border-box;
+ }
+</style>
+<div class="box">content-box(既定・実寸は width より大きい)</div>
+<div class="box border">border-box(width=160px に収まる)</div>
+
+スタイルシートは 3 種類あり、後のものほど優先されます。
+<h1> が大きいのはこれ)私たちアプリ開発者が実際に編集するのは、オーサースタイルシートだけ。 他の 2 つは「こういう仕組みがある」と知っておけば十分です。
+デフォルトのスタイルをまとめて整える「CSS リセット」という仕組みもあります(付録)。
+「どの要素に効かせるか」を細かく指定できます。
+| 書き方 | +意味 (対応するHTMLの要素) | +
|---|---|
h1 |
+すべての h1 要素(要素型) | +
.box |
+class="box" の要素(クラス) |
+
#main |
+id="main" の要素(ID・重複禁止) |
+
a, p |
+a と p の両方(グループ化) | +
p span |
+p の子孫の span(子孫結合子・スペース) | +
p > span |
+p の直接の子の span(子結合子) | +
.card > strong(直接の子)だけ色が変わることを、▶ 実行して確かめましょう。
<style>
+ .card {
+ border: 2px solid #3f51b5;
+ padding: 8px;
+ }
+ .card > strong {
+ color: #e91e63;
+ }
+</style>
+<div class="card">通常の文字 <strong>強調された子</strong></div>
+
+HTML に書かれていない「状態」や、要素にもスタイリングを当てられます。
+:hover などが疑似クラス(: ひとつ)… ホバー中などの状態::first-letter などが疑似要素(:: ふたつ)… 要素の一部下のボタンにカーソルを乗せて、:hover で色が変わるのを確かめましょう。
<style>
+ .btn {
+ display: inline-block;
+ padding: 8px 16px;
+ border-radius: 6px;
+ background: #3f51b5;
+ color: #fff;
+ cursor: pointer;
+ }
+ .btn:hover {
+ background: #e91e63;
+ }
+ p::first-letter {
+ font-size: 2em;
+ color: #e91e63;
+ }
+</style>
+<div class="btn">ホバーしてね</div>
+<p>最初の一文字が大きく色づきます。</p>
+
+色などを :root に変数として定義し、var() で使い回せます。1 か所直すと使っている全部に反映されます。
変数名は必ず -- で始めます。色の意味を名前で伝えられ、可読性も上がります。
--brand の色を変えると、使っている箇所すべてに反映されます。▶ 実行して試しましょう。
<style>
+ :root {
+ --brand: #3f51b5;
+ }
+ h2 {
+ color: var(--brand);
+ }
+ .tag {
+ background: var(--brand);
+ color: #fff;
+ padding: 2px 10px;
+ border-radius: 4px;
+ }
+</style>
+<h2>ブランドカラー</h2>
+<span class="tag">同じ色を使い回す</span>
+
+文字の見た目を変える代表的なプロパティです。
+color … 文字色font-size … 文字の大きさfont-weight … 太さ(normal / bold)line-height … 行の高さ(行間)text-decoration … 下線・打ち消し線などfont-family … フォントの種類<style> の値をいじって、文字の変化を ▶ 実行して確かめましょう。
<style>
+ p {
+ color: #3f51b5;
+ font-size: 20px;
+ font-weight: bold;
+ line-height: 1.8;
+ text-decoration: underline;
+ font-family: sans-serif;
+ }
+</style>
+<p>文字の見た目は CSS で自由に変えられます。<br>
+色・大きさ・太さ・行間・下線・フォントを試してみましょう。</p>
+
+背景色・枠・角丸を組み合わせると「カード」のような見た目が作れます。
+background-color / background-image / border / border-radius など。ほかにも多数あるので、使うときに調べましょう。
背景・枠・角丸の値を変えて ▶ 実行。自分好みのカードにしてみましょう。
+<style>
+ .card {
+ width: 220px;
+ padding: 16px;
+ background: #e8f0fe;
+ border: 2px solid #3f51b5;
+ border-radius: 12px;
+ }
+</style>
+<div class="card">角丸のカード</div>
+
+border-radius を大きくすると、四角形が円や丸帯型になります。
border-radius: 50% … 円border-radius: 100vh … 丸帯型もっと凝った形(吹き出しなど)も CSS で作れます(付録参照)。
+▶ 実行して円と丸帯型を確かめましょう。数値を変えると形が変わります。
+<style>
+ .circle {
+ width: 120px;
+ height: 120px;
+ background: #4dd0e1;
+ border-radius: 50%;
+ }
+ .band {
+ width: 220px;
+ height: 56px;
+ margin-top: 10px;
+ background: #aed581;
+ border-radius: 100vh;
+ }
+</style>
+<div class="circle"></div>
+<div class="band"></div>
+
+チェックポイント
+セレクタ { プロパティ: 値 } の形で書けるbox-sizing を説明できるフレックスボックス ・ グリッド ・ 使い分け
+要素を思いどおりの位置に並べます。実務で最もよく使う 2 大レイアウトです。
+display: flex を付けた要素(親)の中では、子要素が主軸に沿って一列に並びます。既定は横(行)方向です。
display: flex … 子が横並びになるgap … 子どうしのすき間記述 gap の値を変えたり、flex-direction: column を足して縦並びも試しましょう。
<style>
+ .row {
+ display: flex;
+ gap: 8px;
+ }
+ .box {
+ width: 80px;
+ height: 60px;
+ background: #90caf9;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+</style>
+<div class="row">
+ <div class="box">A</div>
+ <div class="box">B</div>
+ <div class="box">C</div>
+</div>
+
+justify-content と align-items で、子要素を主軸・交差軸それぞれの方向に揃えます。
justify-content … 主軸(既定は横)方向
+flex-start / center / flex-endspace-between / space-around / space-evenlyalign-items … 交差軸(既定は縦)方向
+stretch(既定)/ center / flex-start / flex-end記述 justify-content を space-between や flex-end に変えて、並びの変化を見ましょう。
<style>
+ .row {
+ display: flex;
+ /* ↓ ここを space-between / flex-end などに変えてみよう */
+ justify-content: center;
+ align-items: center;
+ gap: 8px;
+ height: 120px;
+ background: #eceff1;
+ }
+ .box {
+ width: 70px;
+ height: 50px;
+ background: #90caf9;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+</style>
+<div class="row">
+ <div class="box">A</div>
+ <div class="box">B</div>
+ <div class="box">C</div>
+</div>
+
+余ったスペースの扱いをコントロールします。
+flex: 1(子に付ける)… その子が余白を埋めて伸びる。複数に付ければ比率で分け合うナビバーの「ロゴを左・メニューを右」は、間の要素に flex: 1 を入れると作れます。
記述 中央の flex: 1 を消すと、伸びずに縮みます。値を変えて挙動を見ましょう。
<style>
+ .bar {
+ display: flex;
+ gap: 8px;
+ background: #eceff1;
+ padding: 8px;
+ }
+ .item {
+ padding: 12px;
+ background: #90caf9;
+ text-align: center;
+ }
+ /* ↓ flex: 1 を消すと「伸びない」。数値を増やすと取り分が増える */
+ .grow {
+ flex: 1;
+ background: #a5d6a7;
+ }
+</style>
+<div class="bar">
+ <div class="item">ロゴ</div>
+ <div class="item grow">中央(伸びる)</div>
+ <div class="item">メニュー</div>
+</div>
+
+display: grid は行と列の 2 次元で配置します。まず「何列にするか」を grid-template-columns で決めます。
grid-template-columns: 1fr 1fr 1fr … 3 等分の 3 列fr … 余ったスペースを分け合う比率(2fr 1fr は 2 : 1)repeat(3, 1fr) … 1fr 1fr 1fr の短い書き方gap … マス目のすき間記述 grid-template-columns を 2fr 1fr や repeat(4, 1fr) に変えて、列の割り方を試しましょう。
<style>
+ .grid {
+ display: grid;
+ /* ↓ 列の数や比率を変えてみよう */
+ grid-template-columns: repeat(3, 1fr);
+ gap: 8px;
+ }
+ .cell {
+ height: 56px;
+ background: #90caf9;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+</style>
+<div class="grid">
+ <div class="cell">1</div>
+ <div class="cell">2</div>
+ <div class="cell">3</div>
+ <div class="cell">4</div>
+ <div class="cell">5</div>
+ <div class="cell">6</div>
+</div>
+
+grid-template-areas を使うと、エリアに名前を付けて絵のように配置できます。ヘッダー・左右カラム・メイン・フッターからなる「よくあるレイアウト(聖杯レイアウト)」も一気に組めます。
grid-template で行・列と各エリアの並びを、grid-area で「どの要素をどのエリアに置くか」を指定します。
記述 左右カラムの幅(120px)や main の色を変えて ▶ 実行 してみましょう。
<style>
+ * {
+ box-sizing: border-box;
+ margin: 0;
+ }
+ body {
+ display: grid;
+ gap: 4px;
+ grid-template:
+ 'header header header' 40px
+ 'left main right' 150px
+ 'footer footer footer' 40px / 120px auto 120px;
+ }
+ header { grid-area: header; background: #90caf9; }
+ .left { grid-area: left; background: #ffab91; }
+ main { grid-area: main; background: #a5d6a7; }
+ .right { grid-area: right; background: #ffab91; }
+ footer { grid-area: footer; background: #90caf9; }
+ body > * { display: grid; place-content: center; }
+</style>
+<header>ヘッダー</header>
+<div class="left">左</div>
+<main>メイン</main>
+<div class="right">右</div>
+<footer>フッター</footer>
+
+迷ったら「一列に並べる? → Flex」「縦横きっちり? → Grid」。2 つを組み合わせるのも普通です。
+チェックポイント
+display: flex で横並び、justify-content / align-items で位置を揃えられるflex: 1 で伸ばす、flex-wrap で折り返せるgrid-template-columns と fr で列を作れるgrid-template-areas で聖杯レイアウトを組めるもっと遊びたい人へ: Flexbox Froggy / Grid Garden
+HTML の構造化から、CSS の装飾・レイアウト(Grid / Flexbox)まで、ひととおり体験しました。
+この HTML と CSS が、あらゆる Web ページの土台です。
+続けて JavaScript を学ぶと、クリックで動くページも作れます。
今日触れられなかった要素・プロパティはたくさんあります。作るときに調べながら足していきましょう。
+ページ上で右クリック → 検証、またはショートカット(Win/ChromeOS: Ctrl+Shift+I / Mac: Cmd+Option+I)で開きます。

「意図しない大きさ」を見つけるのに Computed タブが便利です。
+Chrome 拡張 VisBug を入れると、Alt+Shift+D で起動。

リファレンス(困ったら引く)
+デザインシステム / ガイドライン
+MDN は「これどう書くんだっけ?」を引く辞書。
+デザインシステムは「どう並べ・配色すると使いやすいか」の指針集です。
============================================================================ + HTML/CSS を始めよう(勉強会スライド) + ビルド: npx marp slide.md --html -o slide.html --allow-local-files --theme-set themes/jig.css + ============================================================================
↓ 演習タイマーの実装。題材を問わずそのまま使う。触らないでください。 + 各スライドに <div class="timer-box" data-seconds="秒数">…</div> を置くと右上にタイマーが出ます。 + クリックで開始/停止、右クリックでリセット、± ボタンで 60 秒単位の増減。
↓ コードブロックにコピーボタンを付ける。題材を問わずそのまま使う。触らないでください。 + 各 <pre> の右上に「コピー」が出て、コード全文をクリップボードにコピーします(@@ ハイライトの記号は含まれません)。
↓ インライン playground(その場で試せるミニ実行環境)。題材を問わずそのまま使う。触らないでください。 + スライド本文に次のように書くと、編集→実行できる小さな実行環境になります(詳細は TEMPLATE_GUIDE.md): + + <div class="playground" data-mode="console"> + + ```js + console.log("hello"); + ``` + + </div> + + data-mode="console"(既定)は console.log の出力を、data-mode="dom" は HTML の描画結果+console を表示。 + data-height="200" で出力領域の高さ(px)を調整できます。コードは sandbox iframe(allow-scripts のみ)内で実行され、 + さらに CSP で外部通信を遮断しているため、スライド本体にも外部にも影響しません。
`
+- 意味を持たないただの文字 … ``
+
+ これは段落(p)。まとまった文章に使います。 日本で 一番 高い山は富士山です。 締め切りは今日です。 最初の一文字が大きく色づきます。 文字の見た目は CSS で自由に変えられます。 ============================================================================
+ JavaScript を始めよう(勉強会スライド)
+ ビルド: npx marp slide.md --html -o slide.html --allow-local-files --theme-set themes/jig.css
+============================================================================ ↓ 演習タイマーの実装。題材を問わずそのまま使う。触らないでください。
+ 各スライドに <div class="timer-box" data-seconds="秒数">…</div> を置くと右上にタイマーが出ます。
+ クリックで開始/停止、右クリックでリセット、± ボタンで 60 秒単位の増減。 ↓ コードブロックにコピーボタンを付ける。題材を問わずそのまま使う。触らないでください。
+ 各 <pre> の右上に「コピー」が出て、コード全文をクリップボードにコピーします(@@ ハイライトの記号は含まれません)。 ↓ インライン playground(その場で試せるミニ実行環境)。題材を問わずそのまま使う。触らないでください。
+ スライド本文に次のように書くと、編集→実行できる小さな実行環境になります(詳細は TEMPLATE_GUIDE.md):
+
+ <div class="playground" data-mode="console">
+
+ ```js
+ console.log("hello");
+ ```
+
+ </div>
+
+ data-mode="console"(既定)は console.log の出力を、data-mode="dom" は HTML の描画結果+console を表示。
+ data-height="120" で出力領域の高さ(px)を調整できます。コードは sandbox iframe(allow-scripts のみ)内で実行され、
+ さらに CSP で外部通信を遮断しているため、スライド本体にも外部にも影響しません。 ここが変わる` はページに 1 つ / 大きさを飛ばさない(h2 の下に h3)/ 多用は 3 段階まで。
+
+
見出し1(ページの題)
+見出し2
+見出し3
+` … 順序が関係ない箇条書き(行頭に点)
+- `
` … 順序が大事な箇条書き(行頭に番号)
+- どちらも項目は `
自己紹介
+
+
+```
+
+
+
+ `、リンクは ``。`img` は閉じタグの要らない**空要素**です。タグの後ろに `名前="値"` の形で書く追加設定を**属性**と呼びます。
+
+```html
+
+
+
+株式会社 jig.jp
+新しいタブで開く
+```
+
+` 要素**の**文字色**を**赤**にする、という意味。
+セレクタ(`h1`)・プロパティ(`color`)・値(`red`)が 1 つずつ対応します。
+
+
Hello, World !
+```
+
+` が大きいのはこれ)
+- **オーサースタイルシート** … 開発者が書く CSS
+- **ユーザースタイルシート** … 閲覧者の設定(最優先)
+
+**私たちアプリ開発者が実際に編集するのは、オーサースタイルシートだけ。** 他の 2 つは「こういう仕組みがある」と知っておけば十分です。
+
+
ブランドカラー
+同じ色を使い回す
+```
+
+
+色・大きさ・太さ・行間・下線・フォントを試してみましょう。