Angular todo リストアプリの事始め - ウェブ開発を学ぶ

Angular todo リストアプリの事始め
=======================

* 前のページ
* Overview: Client-side JavaScript frameworks
* 次のページ

この時点で、Angular を使用して todo リストアプリケーションの作成を開始する準備が整いました。 完成したアプリケーションには、やることのリストが表示され、機能の編集、削除、追加が含まれます。 この記事では、アプリケーションの構造を理解し、やることの基本的なリストを表示するようになります。

|  |  |
| --- | --- |
| 前提条件: |
HTML、
 CSS、
 JavaScript に精通していること、
 ターミナル/コマンドラインに関する知識があること。
  |
| 目的: | 基本的なアプリ構造を作成するには、to-do items のリストを表示をすることで、コンポーネント構造、コンポーネント間でのデータ共有、コンテンツの作成、ループなどの基本的な Angular の概念を理解することです。 |

to-do アプリケーションの構造
-----------------

 フレームワークを使用しない基本的なアプリケーションと同様に、Angular アプリケーションには `index.html` があります。
 `index.html` の `<body>` タグ内で、Angular は特別な要素 `<app-root>` を使用してメインコンポーネントを挿入します。メインコンポーネントには、作成した他のコンポーネントが含まれます。
 通常、 `index.html`に触れる必要はありません。代わりに、コンポーネントと呼ばれるアプリケーションの特殊な領域に作業を集中させます。

### コンポーネントを使用して、アプリケーションの構成

 コンポーネントは、Angular アプリケーションの中心的な構成要素です。
 この to-do アプリケーションには、アプリケーションの基盤としてのコンポーネントと、to-do アイテムを処理するためのコンポーネントの 2 つのコンポーネントがあります。

 各コンポーネントは、TypeScript クラス、HTML、および CSS で構成されています。
 TypeScript は JavaScript にトランスパイルまたは変換されます。つまり、アプリケーションは最終的にプレーンな JavaScript になりますが、Typescript の拡張機能と合理化された構文を使用できるという便利さがあります。

### \*ngIf and \*ngFor を使用して UI を動的変更

 このチュートリアルでは、DOM の構造を動的に変更するための 2 つの重要な Angular ディレクティブについても説明します。
 ディレクティブは、アプリケーションの変更に影響を与えるために HTML で使用できるコマンドのようなものです。

 このチュートリアルで取り上げる最初のディレクティブは、Angular のイテレーター `*ngFor` です。
 `*ngFor` は、配列内のアイテムに基づいて DOM 要素を動的に作成できます。

 このチュートリアルで学習する 2 番目のディレクティブは `*ngIf` です。
 `*ngIf` を使用して、条件に基づいて DOM に要素を追加または DOM から削除できます。
 たとえば、ユーザーが to-do リストの項目を編集したい場合は、その項目を編集する手段をユーザーに提供できます。
 アイテムを編集したくない場合は、編集用のインターフェイスを削除できます。

### コンポーネント間でのデータの共有

 この to-do アプリケーションでは、データを共有するようにコンポーネントを構成します。
 to do リストに新しいアイテムを追加するには、メインコンポーネントが新しいアイテムを 2 番目のコンポーネントに送信する必要があります。
 この 2 番目のコンポーネントは、アイテムを管理し、編集、完了のマーク、および個々のアイテムの削除を処理します。

`@Input()` および `@Output()` と呼ばれる特別なデコレータを使用して、Angular コンポーネント間でデータを共有します。
 これらのデコレータを使用して、特定のプロパティでデータがコンポーネントに出入りできるように指定します。
 `@Output()` を使用するには、一方のコンポーネントでイベントを発生させて、もう一方のコンポーネントが利用可能なデータがあることを認識できるようにします。

Item の定義
--------

`app` ディレクトリーに、次の内容の `item.ts` という名前の新しいファイルを作成します。

```js
export interface Item {
  description: string;
  done: boolean;
}
```

このファイルは後で使用するまで使用しませんが、 `item` が何であるかを知って記録する良い機会です。 `Item` `interface` は、アプリケーションが `item` が何であるかを理解できるように、 `item` オブジェクトモデルを作成します。この to-do リストの場合、 `item` は説明があり、実行できるオブジェクトです。

AppComponent にロジックを追加
---------------------

`item` が何であるかがわかったので、TypeScript ファイル `app.component.ts` に追加することで、アプリケーションにいくつかのアイテムを与えることができます。
 `app.component.ts` で、内容を次のように置き換えます。

```js
import { Component } from "@angular/core";

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"],
})
export class AppComponent {
  title = "todo";

  filter: "all" | "active" | "done" = "all";

  allItems = [
    { description: "eat", done: true },
    { description: "sleep", done: false },
    { description: "play", done: false },
    { description: "laugh", done: false },
  ];

  get items() {
    if (this.filter === "all") {
      return this.allItems;
    }
    return this.allItems.filter((item) =>
      this.filter === "done" ? item.done : !item.done
    );
  }
}
```

 最初の行は、Angular をインポートする JavaScript インポートです。
 `@Component()` デコレータは、 `AppComponent` に関するメタデータを指定します。
 デフォルトのメタデータプロパティは次のとおりです。

* `selector`: このコンポーネントをインスタンス化するためにテンプレートで使用する CSS セレクターの名前を示します。 これが `'app-root'` です。
 `index.html` の `body` タグ内で、AngularCLI はアプリケーションの生成時に `<app-root></app-root>` を追加しました。
 すべてのコンポーネントセレクターを他のコンポーネント HTML テンプレートに追加することにより、同じように使用します。
* `templateUrl`: このコンポーネントに関連付ける HTML ファイルを指定します。
 これが、'./app.component.html' です。
* `styleUrls`: このコンポーネントに特に適用されるスタイルのファイルの場所と名前を提供します。 これが `'./app.component.css'` です。

`filter` プロパティは `union` 型です。つまり、 `filter` は `all`, `active` 又は、 `done` の値を持つことができます。
 `union` タイプでは、 `filter` プロパティに割り当てる値にタイプミスをすると、TypeScript はバグを早期に発見できるように通知します。
 このガイドでは、後の手順でフィルタリングを追加する方法を示しますが、フィルターを使用してすべての items のデフォルトリストを表示することもできます。

`allItems` 配列には、to-do items と `done` が含まれます。
 最初のアイテムである `eat` は、 `done` の値が true です。

 getter の `get items()` は、 `filter` が `all` と等しい場合、 `allItems` 配列からアイテムを取得します。
 それ以外の場合、 `get items()` は、ユーザーがビューをフィルタリングする方法に応じて、 `done` items または未処理の items を返します。
 ゲッターはまた、配列の名前を `items` として確立します。これは、次のセクションで使用します。

AppComponent テンプレートに HTML を追加
-----------------------------

ブラウザーで items のリストを表示するには、 `app.component.html` の内容を次の HTML に置き換えます。

```html
<div class="main">
  <h1>My To Do List</h1>
  <h2>What would you like to do today?</h2>

  <ul>
    <li \*ngFor="let item of items">{{item.description}}</li>
  </ul>
</div>
```

`<li>` には、 `items` 配列内のアイテムを反復処理する組み込みの Angular ディレクティブである `*ngFor` が含まれています。
 アイテムごとに、 `*ngFor` は新しい `<li>` を作成します。
 `item.description` を含む二重中括弧は、各 `<li>` に各アイテムの説明のテキストを入力するように Angular に指示します。

ブラウザーに、次のようなアイテムのリストが表示されます。
```

My To Do List
What would you like to do today?

* eat
* sleep
* play
* laugh
```

リストに items を追加
--------------

to-do リストには、 items を追加する方法が必要です。

`app.component.ts` で、次のメソッドをクラスに追加します。

```js
addItem(description: string) {
  this.allItems.unshift({
    description,
    done: false
  });
}
```

`addItem()` メソッドは、ユーザーが提供したアイテムを受け取り、ユーザーが[**Add**]ボタンをクリックすると、そのアイテムを配列に追加します。
 `addItem()` メソッドは、配列メソッド `unshift()` を使用して、配列の先頭とリストの先頭に新しいアイテムを追加します。
 または、 `push()` を使用して、配列の最後とリストの一番下に新しいアイテムを追加することもできます。

`addItem()` メソッドを使用するには、 `AppComponent` テンプレートの HTML を編集します。

`app.component.html` で、 `<h2>` を次のように置き換えます。

```js
<label for="addItemInput">What would you like to do today?</label>

<input
  #newItem
  placeholder="add an item"
  (keyup.enter)="addItem(newItem.value); newItem.value = ''"
  class="lg-text-input"
  id="addItemInput"
/>

<button class="btn-primary" (click)="addItem(newItem.value)">Add</button>
```

 ユーザーが `<input>` に新しいアイテムを入力して**Enter**を押すと、 `addItem()` メソッドはその値を `items` 配列に追加します。
 **Enter** キーを押すと、 `<input>` の値も空の文字列にリセットされます。
 または、同じ `addItem()` メソッドを呼び出す**追加**ボタンをクリックすることもできます。

まとめ
---

これで、ブラウザーに to-do の基本的なリストが表示されるはずです。 それは大きな進歩です！ もちろん、やるべきことはまだたくさんあります。 次の記事では、アプリケーションにスタイルを追加する方法について説明します。

* 前のページ
* Overview: Client-side JavaScript frameworks
* 次のページ


Angular アプリのスタイリング - ウェブ開発を学ぶ

Angular アプリのスタイリング
==================

* 前のページ
* Overview: Client-side JavaScript frameworks
* 次のページ

基本的なアプリケーション構造がセットアップされ、アプリケーションが表示されるようになったので、次の段階へ移って、Angular がアプリケーションのスタイリングをどのように処理するかを見てみましょう。

|  |  |
| --- | --- |
| 前提条件: |
HTML、
 CSS、
 JavaScript に精通していること、
 ターミナル/コマンドラインに関する知識があること。
  |
| 目的: | Angular アプリのスタイルを設定する方法を学びます。 |

Angular にスタイルを追加する
------------------

Angular CLI は、次の 2 種類のスタイルファイルを生成します。

* Component styles: Angular CLI は、各コンポーネントにスタイル用の独自のファイルを提供します。
 このファイルのスタイルは、そのコンポーネントにのみ適用されます。
* `styles.css`: `src` ディレクトリーでは、コンポーネントレベルでスタイルを指定しない限り、このファイルのスタイルはアプリケーション全体に適用されます。

 CSS プリプロセッサを使用しているかどうかによって、CSS ファイルの拡張子は異なる場合があります。
 Angular は、プレーン CSS、SCSS、Sass、Less、および Stylus をサポートします。

`src/styles.css` に、次のスタイルを貼り付けます。

```css
body {
  font-family: Helvetica, Arial, sans-serif;
}

.btn-wrapper {
  /\* flexbox \*/
  display: flex;
  flex-wrap: nowrap;
  justify-content: space-between;
}

.btn {
  color: #000;
  background-color: #fff;
  border: 2px solid #cecece;
  padding: 0.35rem 1rem 0.25rem 1rem;
  font-size: 1rem;
}

.btn:hover {
  background-color: #ecf2fd;
}

.btn:active {
  background-color: #d1e0fe;
}

.btn:focus {
  outline: none;
  border: black solid 2px;
}

.btn-primary {
  color: #fff;
  background-color: #000;
  width: 100%;
  padding: 0.75rem;
  font-size: 1.3rem;
  border: black solid 2px;
  margin: 1rem 0;
}

.btn-primary:hover {
  background-color: #444242;
}

.btn-primary:focus {
  color: #000;
  outline: none;
  border: #000 solid 2px;
  background-color: #d7ecff;
}

.btn-primary:active {
  background-color: #212020;
}
```

`src/styles.css` の CSS はアプリケーション全体に適用されますが、これらのスタイルがページのすべてに影響するわけではありません。
 次のステップは、特に `AppComponent` に適用されるスタイルを追加することです。

`app.component.css` に、次のスタイルを追加します。

```css
body {
  color: #4d4d4d;
  background-color: #f5f5f5;
  color: #4d4d4d;
}

.main {
  max-width: 500px;
  width: 85%;
  margin: 2rem auto;
  padding: 1rem;
  text-align: center;
  box-shadow:
    0 2px 4px 0 rgba(0, 0, 0, 0.2),
    0 2.5rem 5rem 0 rgba(0, 0, 0, 0.1);
}

@media screen and (min-width: 600px) {
  .main {
    width: 70%;
  }
}

label {
  font-size: 1.5rem;
  font-weight: bold;
  display: block;
  padding-bottom: 1rem;
}

.lg-text-input {
  width: 100%;
  padding: 1rem;
  border: 2px solid #000;
  display: block;
  box-sizing: border-box;
  font-size: 1rem;
}

.btn-wrapper {
  margin-bottom: 2rem;
}

.btn-menu {
  flex-basis: 32%;
}

.active {
  color: green;
}

ul {
  padding-inline-start: 0;
}

ul li {
  list-style: none;
}
```

最後のステップは、ブラウザーに再度アクセスして、スタイルがどのように更新されたかを確認することです。 スタイルが更新された事を確認出来ます。

まとめ
---

Angular でのスタイリングの簡単なツアーが終了したので、アプリ機能の作成に戻りましょう。 次の記事では、to-do items に適切なコンポーネントを作成し、to-do items を確認、編集、および削除できるようにします。

* 前のページ
* Overview: Client-side JavaScript frameworks
* 次のページ


Angular アプリケーションのビルドとその他のリソース - ウェブ開発を学ぶ

Angular アプリケーションのビルドとその他のリソース
=============================

* 前のページ
* Overview: Client-side JavaScript frameworks

この Angular の最後の記事では、本番環境に対応したアプリをビルドする方法について説明し、学習の旅を続けるためその他のリソースを提供します。

|  |  |
| --- | --- |
| 前提条件: |
HTML、
 CSS、
 JavaScript に精通していること、
 ターミナル/コマンドラインに関する知識があること。
  |
| 目的: | Angular アプリをビルドする方法を学ぶ。 |

完成したアプリケーションのビルド
----------------

 アプリケーションの開発が完了したので、Angular CLI の `build` コマンドを実行できます。
 `todo` ディレクトリで `build` コマンドを実行すると、アプリケーションは `dist/` という名前のディレクトリにコンパイル結果が出力されます。

`todo` ディレクトリで、コマンド ラインで次のコマンドを実行します。

```bash
ng build -c production
```

 CLI はアプリケーションをコンパイルし、コンパイル結果を新しい `dist` ディレクトリに出力します。
 `ng build` の `--configuration production`/`-c production` フラグは、プロダクションに不要なものを取り除きます。

アプリケーションのデプロイ
-------------

 アプリケーションをデプロイするには、 `dist/my-project-name` フォルダーを Web サーバーに追加します。
 これらのファイルは静的であるため、次のようなファイルを提供できる任意の Web サーバーでホストできます。

* Node.js
* Java
* .NET

Firebase, Google Cloud, or App Engine などのバックエンドを使用できます

その次
---

 ここまで基本的なアプリケーションを作成しましたが、Angular の学びはまだ始まったばかりです。
 以下の Angular のドキュメントを調べることで、さらに学ぶことができます。

* Tour of Heroes: サービスの使用、ナビゲーション、サーバーからのデータの取得など、Angular の機能に焦点を当てた詳細なチュートリアル。
* Angular Components ガイド: ライフサイクル、コンポーネントの相互作用、ビューのカプセル化などのトピックをカバーする一連の記事。
* Forms ガイド: Angular でのリアクティブ フォームの作成、入力の検証、動的フォームの作成について説明する記事。
まとめ
---

以上です。 Angular を楽しんでいただければ幸いです。

* 前のページ
* Overview: Client-side JavaScript frameworks


React ToDoリストをはじめる - ウェブ開発を学ぶ

React ToDoリストをはじめる
==================

* 前のページ
* Overview: Client-side JavaScript frameworks
* 次のページ

例えば、React でアイディアを検証するためにアプリを試作してみることになったとします(いわゆる、Proof of Concept - 概念実証)。ユーザーが作業したいタスクを追加、編集、削除することができ、また、タスクを削除せずに完了とすることができるアプリです。この記事では、基本的な `App` コンポーネントの構造とスタイルを整え、後から追加する個々のコンポーネントの定義とインタラクティブな機能の準備を行っていきます。

**メモ:** コードを我々のバージョンと照らし合わせる必要がある場合は、我々の todo-react リポジトリからサンプルの React アプリコードの完成版を確認することができます。実際に動作しているアプリのバージョンについては、https://mdn.github.io/todo-react-build/ を参照してください。

| 前提条件： | HTML 、CSS 、JavaScript の基本的な知識を持っていること。また ターミナル/コマンドライン に関する知識を持っていること。 |
| --- | --- |
| 目的： | todo リストの実際の利用例を紹介し、基本的なアプリの構造とスタイルを整えていきます。 |

アプリの「ユーザーストーリー」
---------------

ソフトウェア開発においてユーザーストーリーとは、ユーザーの視点から見た実行可能な目標のことを指します。作業を始める前にユーザーストーリーを定義することで、作業に集中することができます。私たちのアプリは、次のようなストーリーを満たす必要があります：

ユーザーができること

* タスクのリストを読むこと
* マウスまたはキーボードを使用してタスクを追加すること
* マウスまたはキーボードを使用して、タスクに完了のマークを付けること
* マウスまたはキーボードを使用して、タスクを削除すること
* マウスまたはキーボードを使用して、タスクを編集すること
* タスクの特定の一部を表示する：すべてのタスク、アクティブなタスクのみ、完了したタスクのみ。

これらのストーリーに 1 つずつ取り組んでいきます。

プロジェクトに入る前に現状整理
---------------

create-react-app を用いた場合、今回のプロジェクトでは使用しないファイルがいくつか作られます。

* コンポーネントごとにスタイルシートを書く予定はないので、まず `App.js` の冒頭にある `App.css` のインポートを削除してください。
* `logo.svg` を使用する予定もないので、このインポートも削除してください。

次に、以下のコマンドをコピーしてターミナルに貼り付け、不要なファイルをいくつか削除します。アプリのルートディレクトリーから開始していることを確認してください。

```bash
# Move into the src directory of your project
cd src
# Delete a few files
rm -- App.test.js App.css logo.svg serviceWorker.js setupTests.js
# Move back up to the root of the project
cd ..
```

注意点：

* 今回削除するうちの 2 つのファイルは、アプリケーションのテスト用です。ここではテストについては説明しません。
* 上記のターミナルで作業を行うためにサーバーを停止した場合は、`npm start` を使用してサーバーを再度起動する必要があります。
プロジェクトの出発地点のコード
---------------

このプロジェクトの出発地点として、次の 2 つを用意します。今あるものを置き換えた `App()` 関数と、アプリのスタイルを設定するための CSS です。

### JSX

次のスニペットをクリップボードにコピーして `App.js` に貼り付け、既存の `App()` 関数を置き換えます。

```js
function App(props) {
  return (
    <div className="todoapp stack-large">
      <h1>TodoMatic</h1>
      <form>
        <h2 className="label-wrapper">
          <label htmlFor="new-todo-input" className="label\_\_lg">
            What needs to be done?
          </label>
        </h2>
        <input
          type="text"
          id="new-todo-input"
          className="input input\_\_lg"
          name="text"
          autoComplete="off"
        />
        <button type="submit" className="btn btn\_\_primary btn\_\_lg">
          Add
        </button>
      </form>
      <div className="filters btn-group stack-exception">
        <button type="button" className="btn toggle-btn" aria-pressed="true">
          <span className="visually-hidden">Show </span>
          <span>all</span>
          <span className="visually-hidden"> tasks</span>
        </button>
        <button type="button" className="btn toggle-btn" aria-pressed="false">
          <span className="visually-hidden">Show </span>
          <span>Active</span>
          <span className="visually-hidden"> tasks</span>
        </button>
        <button type="button" className="btn toggle-btn" aria-pressed="false">
          <span className="visually-hidden">Show </span>
          <span>Completed</span>
          <span className="visually-hidden"> tasks</span>
        </button>
      </div>
      <h2 id="list-heading">3 tasks remaining</h2>
      <ul
        role="list"
        className="todo-list stack-large stack-exception"
        aria-labelledby="list-heading">
        <li className="todo stack-small">
          <div className="c-cb">
            <input id="todo-0" type="checkbox" defaultChecked={true} />
            <label className="todo-label" htmlFor="todo-0">
              Eat
            </label>
          </div>
          <div className="btn-group">
            <button type="button" className="btn">
              Edit <span className="visually-hidden">Eat</span>
            </button>
            <button type="button" className="btn btn\_\_danger">
              Delete <span className="visually-hidden">Eat</span>
            </button>
          </div>
        </li>
        <li className="todo stack-small">
          <div className="c-cb">
            <input id="todo-1" type="checkbox" />
            <label className="todo-label" htmlFor="todo-1">
              Sleep
            </label>
          </div>
          <div className="btn-group">
            <button type="button" className="btn">
              Edit <span className="visually-hidden">Sleep</span>
            </button>
            <button type="button" className="btn btn\_\_danger">
              Delete <span className="visually-hidden">Sleep</span>
            </button>
          </div>
        </li>
        <li className="todo stack-small">
          <div className="c-cb">
            <input id="todo-2" type="checkbox" />
            <label className="todo-label" htmlFor="todo-2">
              Repeat
            </label>
          </div>
          <div className="btn-group">
            <button type="button" className="btn">
              Edit <span className="visually-hidden">Repeat</span>
            </button>
            <button type="button" className="btn btn\_\_danger">
              Delete <span className="visually-hidden">Repeat</span>
            </button>
          </div>
        </li>
      </ul>
    </div>
  );
}
```

次に `public/index.html` を開いて、`<title>`要素のテキストを `TodoMatic` に変更します。こうすることでアプリ上部の `<h1>` と一致します。

```html
<title>TodoMatic</title>
```

ブラウザーを更新すると、次のように表示されます。

![todo-maticアプリ、スタイルなし、乱雑なラベル、入力、ボタンの混乱を表示](/ja/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning/unstyled-app.png)

まだ見た目が整っていなくて、機能もしていませんが、一旦問題はありません。すぐにスタイルを設定します。まず現在の JSX と、それがユーザーストーリーにどのように対応しているかを考えてみます。

* 新しいタスクを書き込むための `<input type="text">` 要素と、フォームを送信するためのボタンを備えた `<form>` 要素があります。
* タスクのフィルタリングに使用するためのボタンが並んでいます。
* 残っているタスクの数を示す見出しがあります。
* 3 つのタスクがあり、順序付けられていないリストとして配置されています。それぞれのタスクはリストアイテム（`<li>`）であり、タスクを編集および削除するためのボタンと、完了したことをチェックするためのチェックボックスがあります。

フォームはタスクを作成するためのもので、ボタンはタスクをフィルタリングするためのもの、また見出しとリストはタスクを読むためのものです。今のところタスクを編集するための UI は分かりづらいですが、そちらについては後でコードを書き足していきます。

### アクセシビリティ

ここでいくつかの珍しい属性に気付くかもしれません。例えば：

```html
<button type="button" className="btn toggle-btn" aria-pressed="true">
  <span className="visually-hidden">Show </span>
  <span>all</span>
  <span className="visually-hidden"> tasks</span>
</button>
```

`aria-pressed` は支援技術（スクリーン・リーダーなど）に対して、ボタンが押された状態と押されていない状態の 2 つの状態のうちの 1 つであることを伝えます。これは `on` と `off` (あるいは `pressed` か `unpressed` )を切り替えるようなものだと考えてください。 `true` の値を設定すると、デフォルトでボタンが押された状態となります。

`visually-hidden` というクラスについては、CSS を記述していないので、まだ意味はありません。ただし、スタイルを設定すると、このクラスの要素はすべて目の見えるユーザーからは隠され、スクリーンリーダーのユーザーは引き続き使用できるようになります。これらの単語は、目の見えるユーザーには必要ありません。視覚的な文脈を持たないスクリーンリーダーのユーザーに、ボタンが何をするのかという情報を提供するためにあります。

さらに下には `<ul>` 要素があります：

```html
<ul
 role="list"
 className="todo-list stack-large stack-exception"
 aria-labelledby="list-heading"></ul>
```

`role`属性は、タグがどのような要素を表しているのかを説明するのに役立ちます。 `<ul>` はデフォルトではリストのように扱われますが、これから追加するスタイルはその機能を壊します。この `role` 属性は、`<ul>` 要素に「リスト」であることを再度伝えます。なぜこれが必要な理由なのか詳しく知りたい方は、Scott O'Hara の記事「Fixing Lists」 をご覧ください。

`aria-labelledby` 属性は、リストの見出しをその下にあるリストの目的を説明するラベルとして扱っていることを支援技術に伝えます。この関連付けを行うことで、リストの情報がより豊富になり、スクリーンリーダーのユーザーがリストの目的をよりよく理解できるようになります。

最後に、リスト項目のラベルと入力には、JSX 特有の属性がいくつかあります。

```html
<input id="todo-0" type="checkbox" defaultChecked="{true}" />
<label className="todo-label" htmlFor="todo-0"> Eat </label>
```

`<input/ >` タグの `defaultChecked` 属性は、React にこのチェックボックスを最初にチェックするように指示します。通常の HTML のように `checked` を使用した場合、React はチェックボックスのイベント処理に関連する警告をブラウザーコンソールに表示させます。今のところは気にしないで大丈夫です。後ほどイベントを使用するときにこれについては説明します。

また `htmlFor` 属性は、HTML で使用されている `for` 属性に対応しています。 JSX では `for` は予約語であるため、属性として使用できません。そのため React は `for` の代わりに `htmlFor` を使用します。

注意点：

* JSX の属性でブール値（ `true` および `false` ）を使用するには、それらを中括弧で囲む必要があります。もし `defaultChecked="true"` と書いた場合、`defaultChecked` の値は文字列リテラルである `"true"` になります。これは実際には HTML ではなく JavaScript であることを忘れないでください。
* 先ほどのコードで使われていた `aria-pressed` 属性は `"true"` でしたが、これは `checked` のようにブール値としての true とは扱われないためです。
### スタイルを実装する

次の CSS コードを `src/index.css` に貼り付けて、現在のコードを置き換えてください。

```css
/\* RESETS \*/
\*,
\*::before,
\*::after {
  box-sizing: border-box;
}
\*:focus {
  outline: 3px dashed #228bec;
  outline-offset: 0;
}
html {
  font: 62.5% / 1.15 sans-serif;
}
h1,
h2 {
  margin-bottom: 0;
}
ul {
  list-style: none;
  padding: 0;
}
button {
  border: none;
  margin: 0;
  padding: 0;
  width: auto;
  overflow: visible;
  background: transparent;
  color: inherit;
  font: inherit;
  line-height: normal;
  -webkit-font-smoothing: inherit;
  -moz-osx-font-smoothing: inherit;
  -webkit-appearance: none;
}
button::-moz-focus-inner {
  border: 0;
}
button,
input,
optgroup,
select,
textarea {
  font-family: inherit;
  font-size: 100%;
  line-height: 1.15;
  margin: 0;
}
button,
input {
  overflow: visible;
}
input[type="text"] {
  border-radius: 0;
}
body {
  width: 100%;
  max-width: 68rem;
  margin: 0 auto;
  font:
    1.6rem/1.25 Arial,
    sans-serif;
  background-color: #f5f5f5;
  color: #4d4d4d;
}
@media screen and (min-width: 620px) {
  body {
    font-size: 1.9rem;
    line-height: 1.31579;
  }
}
/\*END RESETS\*/
/\* GLOBAL STYLES \*/
.form-group > input[type="text"] {
  display: inline-block;
  margin-top: 0.4rem;
}
.btn {
  padding: 0.8rem 1rem 0.7rem;
  border: 0.2rem solid #4d4d4d;
  cursor: pointer;
  text-transform: capitalize;
}
.btn.toggle-btn {
  border-width: 1px;
  border-color: #d3d3d3;
}
.btn.toggle-btn[aria-pressed="true"] {
  text-decoration: underline;
  border-color: #4d4d4d;
}
.btn\_\_danger {
  color: #fff;
  background-color: #ca3c3c;
  border-color: #bd2130;
}
.btn\_\_filter {
  border-color: lightgrey;
}
.btn\_\_primary {
  color: #fff;
  background-color: #000;
}
.btn-group {
  display: flex;
  justify-content: space-between;
}
.btn-group > \* {
  flex: 1 1 49%;
}
.btn-group > \* + \* {
  margin-left: 0.8rem;
}
.label-wrapper {
  margin: 0;
  flex: 0 0 100%;
  text-align: center;
}
.visually-hidden {
  position: absolute !important;
  height: 1px;
  width: 1px;
  overflow: hidden;
  clip: rect(1px 1px 1px 1px);
  clip: rect(1px, 1px, 1px, 1px);
  white-space: nowrap;
}
[class\*="stack"] > \* {
  margin-top: 0;
  margin-bottom: 0;
}
.stack-small > \* + \* {
  margin-top: 1.25rem;
}
.stack-large > \* + \* {
  margin-top: 2.5rem;
}
@media screen and (min-width: 550px) {
  .stack-small > \* + \* {
    margin-top: 1.4rem;
  }
  .stack-large > \* + \* {
    margin-top: 2.8rem;
  }
}
.stack-exception {
  margin-top: 1.2rem;
}
/\* END GLOBAL STYLES \*/
.todoapp {
  background: #fff;
  margin: 2rem 0 4rem 0;
  padding: 1rem;
  position: relative;
  box-shadow:
    0 2px 4px 0 rgba(0, 0, 0, 0.2),
    0 2.5rem 5rem 0 rgba(0, 0, 0, 0.1);
}
@media screen and (min-width: 550px) {
  .todoapp {
    padding: 4rem;
  }
}
.todoapp > \* {
  max-width: 50rem;
  margin-left: auto;
  margin-right: auto;
}
.todoapp > form {
  max-width: 100%;
}
.todoapp > h1 {
  display: block;
  max-width: 100%;
  text-align: center;
  margin: 0;
  margin-bottom: 1rem;
}
.label\_\_lg {
  line-height: 1.01567;
  font-weight: 300;
  padding: 0.8rem;
  margin-bottom: 1rem;
  text-align: center;
}
.input\_\_lg {
  padding: 2rem;
  border: 2px solid #000;
}
.input\_\_lg:focus {
  border-color: #4d4d4d;
  box-shadow: inset 0 0 0 2px;
}
[class\*="\_\_lg"] {
  display: inline-block;
  width: 100%;
  font-size: 1.9rem;
}
[class\*="\_\_lg"]:not(:last-child) {
  margin-bottom: 1rem;
}
@media screen and (min-width: 620px) {
  [class\*="\_\_lg"] {
    font-size: 2.4rem;
  }
}
.filters {
  width: 100%;
  margin: unset auto;
}
/\* Todo item styles \*/
.todo {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
.todo > \* {
  flex: 0 0 100%;
}
.todo-text {
  width: 100%;
  min-height: 4.4rem;
  padding: 0.4rem 0.8rem;
  border: 2px solid #565656;
}
.todo-text:focus {
  box-shadow: inset 0 0 0 2px;
}
/\* CHECKBOX STYLES \*/
.c-cb {
  box-sizing: border-box;
  font-family: Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  font-weight: 400;
  font-size: 1.6rem;
  line-height: 1.25;
  display: block;
  position: relative;
  min-height: 44px;
  padding-left: 40px;
  clear: left;
}
.c-cb > label::before,
.c-cb > input[type="checkbox"] {
  box-sizing: border-box;
  top: -2px;
  left: -2px;
  width: 44px;
  height: 44px;
}
.c-cb > input[type="checkbox"] {
  -webkit-font-smoothing: antialiased;
  cursor: pointer;
  position: absolute;
  z-index: 1;
  margin: 0;
  opacity: 0;
}
.c-cb > label {
  font-size: inherit;
  font-family: inherit;
  line-height: inherit;
  display: inline-block;
  margin-bottom: 0;
  padding: 8px 15px 5px;
  cursor: pointer;
  touch-action: manipulation;
}
.c-cb > label::before {
  content: "";
  position: absolute;
  border: 2px solid currentColor;
  background: transparent;
}
.c-cb > input[type="checkbox"]:focus + label::before {
  border-width: 4px;
  outline: 3px dashed #228bec;
}
.c-cb > label::after {
  box-sizing: content-box;
  content: "";
  position: absolute;
  top: 11px;
  left: 9px;
  width: 18px;
  height: 7px;
  transform: rotate(-45deg);
  border: solid;
  border-width: 0 0 5px 5px;
  border-top-color: transparent;
  opacity: 0;
  background: transparent;
}
.c-cb > input[type="checkbox"]:checked + label::after {
  opacity: 1;
}
```

保存してブラウザーを確認すると、アプリに適切なスタイルが設定されているはずです。

まとめ
---

これで、私達の todo リストアプリは実際のアプリのようになりました。ただし、まだ実際には何も動きません。次の章で修正をしていきます。

* 前のページ
* Overview: Client-side JavaScript frameworks
* 次のページ


React のリソース - ウェブ開発を学ぶ

React のリソース
===========

* 前のページ  (en-US)
* Overview: Client-side JavaScript frameworks
* 次のページ  (en-US)

最後の記事では、更に学習を進めるために利用できる React のリソースを紹介します。

|  |  |
| --- | --- |
| 前提条件: |
HTML、
 CSS、
 JavaScript に精通していること、
 ターミナル/コマンドラインに関する知識があること。
  |
| 目的: | React をより学習するためのさらなるリソースを提供する |

コンポーネントレベルのスタイル
---------------

このチュートリアルではこのアプローチは使用しませんが、多くの React アプリケーションでは、単一のモノリシックなスタイルシートではなく、コンポーネントごとにスタイルを定義しています。

`create-react-app` を使うと、CSS ファイルが JavaScript モジュールにインポートできるので、対応するコンポーネントがレンダリングされるときにだけ CSS がユーザーに送信されるようになります。このアプリでは、例えば、専用の `Form.css` ファイルを書いて、それぞれのコンポーネントのスタイルを記載し、次のようにそれぞれのモジュールにスタイルをインポートすることができます。

```js
import Form from "./Form";
import "./Form.css";
```

この方法だと、特定のコンポーネントに属する CSS を簡単に特定し、管理することができます。しかし、コードベース全体でスタイルシートを断片化することになり、この断片化は価値のあるものにならないかもしれません。何百ものユニークなビューと多くの可動部分を持つ大規模なアプリケーションの場合、ユーザーに送信される無関係なコードの量を制限することは理にかなっています。アプリケーション全体のスタイルと、その上に構築された特定のコンポーネントのスタイルをもつことになるでしょう。

コンポーネントのスタイルシートについては、 create-react-app のドキュメントに詳しく書かれています。

React DevTools
--------------

このチュートリアルでは `console.log()` を使ってアプリケーションの state や props を確認しました。また、 React が CLI やブラウザーの JavaScript コンソールに表示する便利な警告やエラーメッセージも見てきたと思います。しかし、ここでできることはまだあります。

React DevTools はブラウザーで React アプリケーションの内部を直接検査できるようにするものです。ブラウザーの開発者ツールに新しいパネルが追加され、それを使って様々なコンポーネントの state や props を検査したり、 state や props を編集してアプリケーションにすぐに変更を加えたりすることができます。

このスクリーンショットは React DevTools に表示される私達が作成したアプリケーションの最終形を示します。

![Our project being shown in React devtools](/ja/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_resources/react-devtools.png)

左側には、アプリケーションを構成するすべてのコンポーネントが表示され、配列からレンダリングされるものの一意なキーが表示されます。右側には、 App コンポーネントが利用する props とフックが表示されています。また、`Form`、`FilterButton`、`Todo` コンポーネントは右側にインデントされていることに注意してください。より複雑なアプリでは、このビューは親子関係を一目で理解するために最適です。

React DevTools は様々な形態で提供されています。

* Chrome 拡張
* Firefox 拡張
* Chromium 版 Edge 拡張 （近日公開）
* NPM か Yarn でインストールできるスタンドアロンアプリケーション

これらのうち一つをインストールしてみて、作ったアプリの検査に使ってみてください！

React のブログで React DevTools について詳しく読むことができます。

コンテクスト API
----------

このチュートリアルで作成したアプリケーションでは、 `App` コンポーネントからデータを必要とする子コンポーネントにデータを渡すために、コンポーネントの props を利用しました。ほとんどの場合、 props はデータを共有するための適切な方法です。しかし、複雑で深くネストされたアプリケーションでは、必ずしも最適とは言えません。

React はコンポーネントツリーの下に props を渡さずに、データを必要とするコンポーネントにデータを提供する方法として コンテクスト API を提供します。また、これを容易にする useContext フック も提供されています。

自身でこの API を試したいというかたは、 Smashing Magazine が書いた React コンテクストの紹介記事 を読むといいでしょう。

クラスコンポーネント
----------

このチュートリアルでは触れていませんが、 ES6 のクラスを使用して React コンポーネントを構築することは可能です。これらはクラスコンポーネントと呼ばれます。フックが登場するまで、 ES6 のクラスはコンポーネントに state をもたせたり、副作用のある描画の管理を行うための唯一の方法でした。これらは、他の特定のエッジケースな機能を処理する唯一の方法であり、従来の React プロジェクトでは非常に一般的です。公式の React ドキュメントは、それらについて学び始めるのに最適です。

* React ドキュメントで学ぶ状態とライフサイクル
* React ドキュメントで学ぶ React 入門
* MDN で学ぶ JavaScript のクラス
テスト
---

`create-react-app` はアプリケーションがすぐにテストできるツールを提供しています。しかし、チュートリアルの前半で関連するファイルを削除してしまったかもしれません。 `create-react-app` のドキュメントには テストのための基本的なことが書かれています 。

ルーティング
------

ルーティングは従来、ユーザーのコンピューター上のアプリケーションではなく、サーバーによって処理されていました。しかし、現在では、ウェブアプリケーションがブラウザーの位置を読み取り、更新し、特定のユーザーインターフェースをレンダリングすることが可能です。これをクライアントサイドルーティングと呼びます。アプリケーションのために多くの一意なルート (`/home` または `/dashboard` 、 `login/` など) を作成することが可能です。

React コミュニティはクライアントサイドルーティングについて、2 つの主要なライブラリを作成しています。 React Router と Reach Router です。

* React Router は、複雑なルーティングを必要とするアプリケーションに適しており、 Reach Router よりもエッジケースに対応することができます。しかし、 React Router はサイズが大きいライブラリになります。
* Reach Router は、より単純なアプリケーションに適しており、ユーザーがページ間を移動するときにフォーカスを自動的に管理します。

クライアントサイドのルーティングでは、フォーカス管理が不可欠です。これがないと、キーボードユーザーはフォーカスの問題に陥り、スクリーンリーダーを使用するユーザーは新しいページに移動したことに気づかない可能性があります。 Reach Router はアクセシビリティに優れているため、ルーティングを導入し始めるには良いライブラリです。

ただし、一つだけ注意点があります。これらのプロジェクトは 近い将来、統合される 予定があるということです。この統合が行われた場合、 React Router が(Reach のフォーカス管理機能が追加され)存続するプロジェクトとなる予定です。

* 前のページ  (en-US)
* Overview: Client-side JavaScript frameworks
* 次のページ  (en-US)


CSS のパフォーマンス最適化 - ウェブ開発を学ぶ

CSS のパフォーマンス最適化
===============

* 前のページ
* Overview: Performance
* 次のページ

スタイル設定されていないページを描画し、スタイルが解釈できたら再描画するというのは、ユーザーにとって使い勝手が悪いものです。このため、CSS は、ブラウザーがその CSS が現在必要でないことを知っていない限り、描画ブロックされます。ブラウザーは、CSS をダウンロードし、CSS オブジェクトモデルを構築した時点で、ページを描画することができます。ブラウザは固有のレンダリングパスに従います。描画はレイアウトの後にのみ行われ、レイアウトはレンダーツリーが作成された後に行われ、そのためには DOM と CSSOM のツリーの両方が必要です。CSSOM 構築を最適化するには、不要なスタイルを削除し、ミニファイ、圧縮、キャッシュを行い、ページ読み込み時に不要な CSS は追加ファイルに分割して CSS の描画ブロックを縮小する必要があります。

### 描画ブロックの最適化

CSS では、メディアクエリーによって、具体的な条件に合わせてスタイル設定を行うことができます。メディアクエリーはレスポンシブウェブデザインにとって重要であり、重要なレンダリングパスを最適化することを支援します。ブラウザーはこれらのスタイルをすべて解釈するまでレンダリングをブロックしますが、印刷スタイルシートのように使用しないことがわかっているスタイルについてはレンダリングをブロックしません。メディアクエリーに基づいて CSS を複数のファイルに分割することで、使用しない CSS をダウンロードする際の描画ブロックを防ぐことができます。ブロックされない CSS リンクを作成するには、印刷スタイルのようなすぐに使用しないスタイルを別個のファイルに移動し、HTML マークアップに `<link>` を追加し、この場合、印刷スタイルであることを示すメディアクエリーを追加してください。

```html
<!-- styles.css の読み込みと解釈は描画ブロック -->
<link rel="stylesheet" href="styles.css" />

<!-- print.css の読み込みと解釈は描画ブロックされない -->
<link rel="stylesheet" href="print.css" media="print" />

<!-- mobile.css の読み込みと解釈は、広い画面では描画ブロックされない -->
<link
 rel="stylesheet"
 href="mobile.css"
 media="screen and (max-width: 480px)" />
```

既定では、ブラウザーは指定されたスタイルシートが描画ブロックされることを想定しています。スタイルシートが適用されるタイミングは、メディアクエリーを使って `media` 属性を追加してブラウザーに指示します。ブラウザーはスタイルシートを見ると、特定のシナリオにのみ適用する必要があることを認識し、スタイルシートをダウンロードしますが、描画はブロックしません。CSS を複数のファイルに区切ることで、描画をブロックするメインのファイル（この場合は "styles.css"）をより小さくし、描画がブロックされる時間を短縮しています。

### GPU でのアニメーション

ブラウザーは CSS アニメーションを処理するように最適化されており、再フロー（つまり再描画）を発生させないプロパティのアニメーションはとてもうまく処理します。パフォーマンスを向上させるために、アニメーションさせるノードをメインスレッドから GPU に移すことができます。合成をもたらすプロパティには、3D 座標変換（`transform: translateZ()` や `rotate3d()` など）、アニメーション座標変換、`opacity`、`position: fixed`、`will-change`、`filter` などがあります。また、`<video>`、`<canvas>`、 `<iframe>` など、いくつかの要素がレイヤーになることもあります。要素をレイヤーとして昇格させることは、合成とも呼ばれますが、座標変換プロパティのアニメーションを GPU で行うことで、特にモバイルでのパフォーマンスが向上します。

### `will-change` プロパティ

CSS の `will-change` プロパティは、要素がどのように変化することが予想されるかをブラウザーに示唆します。ブラウザーは、要素が実際に変更される前に最適化を設定することがあります。この種の最適化は、実際に必要とされる前に高価な可能性のある作業を行うことで、ページのレスポンスを向上させることができます。

**メモ:** `will-change`は、既存のパフォーマンス問題に対処するための最後の手段として使用することを意図しています。パフォーマンス上の問題を予測するために使用するべきではありません。

```css
.element {
  will-change: opacity, transform;
}
```

### `font-display` プロパティ

@font-face ルールに適用される font-display プロパティは、フォントファイルがどのようにブラウザーで読み込まれて表示されているのか、フォントの読み込み中、または読み込みが失敗した時に代替フォントでテキストを表示できるようにするかを定義します。これにより、空白の画面を表示することなくテキストを表示することができ、パフォーマンスを向上させることができます。

```css
@font-face {
  font-family: someFont;
  src: url(/path/to/fonts/someFont.woff) format("woff");
  font-weight: 400;
  font-style: normal;
  font-display: fallback;
}
```

### `contain` プロパティ

`contain` は CSS のプロパティで、作成者がある要素とその内容が、できるだけ、文書ツリーの残りの部分から独立指せることを示します。これにより、ブラウザーはページ全体ではなく、DOM の限られた領域に対してレイアウト、スタイル、描画、サイズ、またはそれらの任意の組み合わせを再計算することができるようになります。

まとめ
---

* 前のページ
* Overview: Performance
* 次のページ
関連情報
----

* CSS アニメーションのパフォーマンス (en-US)


ウェブパフォーマンスの「なぜ」 - ウェブ開発を学ぶ

ウェブパフォーマンスの「なぜ」
===============

* Overview: Performance
* 次のページ

ウェブパフォーマンスは、遅い処理を速く*見せる*ことも含めて、ウェブサイトを速くすることがすべてです。この記事では、なぜウェブパフォーマンスがサイト訪問者にとって、またビジネスの目標にとって重要なのかを紹介しています。

|  |  |
| --- | --- |
| 前提条件: |
 基本的なコンピューターリテラシー、
 基本的なソフトウェアのインストール、
 クライアント側のウェブ技術の基本的な知識
  |
| 目標: | ユーザー体験を良くするために、なぜウェブパフォーマンスが重要なのか、その基礎知識を身につけること。 |

ウェブパフォーマンスとは、サイトのコンテンツの**読み込み**や**描画**の速さ、ユーザーの操作への反応の速さを指します。パフォーマンスの悪いサイトは、表示に時間がかかり、入力への反応が遅くなります。パフォーマンスの悪いサイトは、サイトの離脱率を高めます。パフォーマンスが悪いと、最悪の場合、コンテンツに完全にアクセスできなくなります。ウェブパフォーマンスの良い目標は、ユーザーがパフォーマンスに気づかないことです。サイトパフォーマンスのパフォーマンスに対する個人の認識は主観的なものですが、読み込みと描画は測定できます。パフォーマンスが良いことは、ほとんどのサイト訪問者には明らかではないかもしれませんが、ほとんどの人は停滞しているサイトをすぐに認識するでしょう。それが私たちが気にする理由です。

なぜパフォーマンスを気にするのか
----------------

ウェブパフォーマンスとそれに関連するベストプラクティスは、ウェブサイトの訪問者が良い体験をするために不可欠です。ある意味では、ウェブパフォーマンスはウェブアクセシビリティの一部と考えることができます。アクセシビリティと同様にパフォーマンスでは、サイト訪問者がサイトにアクセスするために使用している端末と端末の接続速度を考慮します。

例として、この記事を書いている時点で 400 以上の HTTP リクエストがあった、ファイルサイズが 22.6MB を超える CNN.com の読み込み時の体験を考えてみましょう。

* 光ファイバーネットワークに接続されたデスクトップコンピューターでこれを読み込むことを想像してみてください。これは比較的高速で、ファイルサイズはほとんど関係ないと思われます。
* 公共交通機関で通勤しながら、 9 年間使用してきた iPad でテザリングしたモバイルデータ通信を使って同じサイトを読み込むことを想像してみてください。同じサイトの読み込みに時間がかかり、携帯電話の電波状況によっては使えなくなる可能性があります。読み込みが終わる前に諦めてしまうかもしれません。
* 利用エリアが限られているか、圏外になっているインドの農村部で、 35 ドルのファーウェイ製端末で同じサイトを読み込むことを想像してみてください。サイトの読み込みには非常に時間がかかり、ブロッキングスクリプトがタイミングアウトする可能性があり、読み込みが行われたとしても CPU に悪影響を及ぼしてブラウザーがクラッシュしてしまいます。
 22.6 MB のサイトはを 3G ネットワーク上で読み込みむには最大 83 秒かかり、`DOMContentLoaded` (サイトのベースとなる HTML 構造の意味) は 31.86 秒でした。

また、大きな問題はダウンロードにかかる時間だけではありません。多くの国ではいまだに、メガバイト単位で課金されるインターネット接続が使われています。例として挙げた 22.6MB の CNN.com をダウンロードするには、平均的なインド人の日給の約 11 % の費用がかかることになります。北西アフリカのモバイル端末からだと、平均的な給料の 2 日分になるかもしれません。このサイトをアメリカのキャリアの国際ローミングプランで読み込んだとしたら？誰もが泣きたくなるようなコストになります。（"how much your site costs to download" を参照。）

### コンバージョン率を改善する

サイトのダウンロードと描画時間を短縮することで、コンバージョン率とユーザー維持率が向上します。

**コンバージョン率**とは、サイト訪問者が測定された、または希望するアクションを実行する率のことです。例えば、購入する、記事を読む、ニュースレターを購読するなどです。コンバージョン率として測定されるアクションは、ウェブサイトのビジネス目標によって異なります。

パフォーマンスはコンバージョンに影響を与えます。サイト訪問者は、サイトが 2 秒以内に読み込まれることを期待していますが、モバイルではそれ以下になることもあります (一般的にはもっと時間がかかる)。同じサイト訪問者でも、遅いサイトを 3 秒で放棄し始めます。

サイトの読み込み速度は 1 つの要因です。サイトがユーザーの操作に反応するのが遅かったり、不愉快に見えたりすると、サイト訪問者は興味を失い、信頼を失います。

ここでは、パフォーマンス向上の実例をいくつか紹介します。

* Tokopedia は、 3G 接続で描画時間を 14 秒から 2 秒に短縮し、訪問者数が 19% 増、総セッション数が 35% 増、新規ユーザー数が 7% 増、アクティブユーザー数が 17% 増、ユーザーあたりのセッション数が 16% 増となりました。
* Pinterest のページをパフォーマンス向上のために再構築した結果、待ち時間が 40% 減少し、 SEO トラフィックが 15% 増加し、サインアップへのコンバージョン率が 15% 増加しました。

サイト訪問者を惹きつけ、維持するためには、アクセスしやすいサイトを作成し、優れたユーザー体験を提供する必要があります。ウェブサイトを構築するには、HTML、CSS、JavaScript が必要であり、通常は画像や動画などのバイナリファイルタイプも含まれます。サイトを構築する際の決定やツールの選択は、完成した作品のパフォーマンスに大きく影響します。

良いパフォーマンスは資産です。パフォーマンスが悪ければ負債となります。サイトの速度は、バウンス率、コンバージョン、収益、ユーザー満足度、検索エンジンランキングに直接影響します。パフォーマンスの高いサイトは、訪問者の維持率とユーザーの満足度を高めることが示されています。遅いコンテンツはサイトの放棄につながることが示されており、訪問者の中には二度と戻ってこない人もいます。クライアントとサーバーの間を通過するデータ量を減らすことで、すべての関係者のコストを削減します。 HTML/CSS/JavaScript とメディアファイルのサイズを減らすことで、ロード時間とサイトの消費電力の両方を削減できます (パフォーマンス予算 (en-US)を参照)。

パフォーマンスのトラッキングは重要です。ネットワーク速度や端末の機能など、複数の要因がパフォーマンスに影響を与えます。また、ビジネスの目的が違えば、サイトやサポートしている組織の目標に応じて、異なる指標の方がより関連性が高いことを意味する場合もあります。サイトのパフォーマンスがどのように認識されるかは、ユーザー体験です。

まとめ
---

ウェブパフォーマンスは、アクセシビリティだけでなく、組織やビジネスの目標を達成するための他のウェブサイトの測定基準にとっても重要です。ウェブサイトのパフォーマンスの良し悪しは、ほとんどのサイトの全体的な有効性と同様に、ユーザー体験と強力に相関しています。これが、ウェブパフォーマンスに注意を払うべき理由です。

* Overview: Performance
* 次のページ


パフォーマンスの測定 - ウェブ開発を学ぶ

パフォーマンスの測定
==========

* 前のページ
* Overview: Performance
* 次のページ

パフォーマンスの測定は、アプリケーション、サイト、ウェブサービスを評価することを助ける重要な指標を提供します。

たとえば、パフォーマンスの指標を使うことで、競合と比較してアプリケーションをどのように動作させるか決めたり、リリースごとのパフォーマンスを比較したりできます。測定対象として選択する指標はユーザー、サイト、そしてビジネスのゴールに関連するものであるべきです。それらは一貫した手法で収集、測定され、非技術系の関係者にも理解でき、利用可能なフォーマットで分析される必要があります。

この記事ではサイトのパフォーマンス測定と最適化に利用できるウェブパフォーマンスの指標を紹介します。

|  |  |
| --- | --- |
| 前提条件: |
 基本的なコンピューターリテラシー、
 基本的なソフトウェアのインストール、
 クライアント側のウェブ技術の基本的な知識
  |
| 目標: | 様々なウェブパフォーマンス API を通じて収集できる ウェブパフォーマンスの指標とデータの視覚化に利用できるツールの情報を提供すること。 |

パフォーマンス API
-----------

ウェブのコードを書くとき、自分自身でパフォーマンス測定ツールを作るために利用できるたくさんのウェブ API があります。

クライアントサイドのウェブパフォーマンスを測定するために ナビゲーションタイミング API を利用できます。前のページをアンロードするために必要な時間、ドメインのルックアップにかかる時間、ウィンドウのロードハンドラー実行にかかる時間の合計などが含まれます。この API は、下図に示すナビゲーションイベント全てに関する指標として利用できます。

![ナビゲーションタイミング API が処理できる様々なハンドラーには、次ののものがある。 ナビゲーションタイミング API metrics Prompt for unload redirect unload App cache DNS TCP Request Response Processing onLoad navigationStart redirectStart redirectEnd fetchStart domainLookupEnd domainLookupStart connectStart (secureConnectionStart) connectEnd requestStart responseStart responseEnd unloadStart unloadEnd domLoading domInteractive domContentLoaded domComplete loadEventStart loadEventEnd](/ja/docs/Learn/Performance/Measuring_performance/navigationtimingapi.jpg)

現在のページのパフォーマンスに関連する情報へのアクセスを提供する パフォーマンス API は、パフォーマンスタイムライン API、ナビゲーションタイミング API、ユーザータイミング API (en-US)、そして リソースタイミング API を含みます。これらのインターフェースにより、JavaScript のタスクが完了するまでにかかる時間の正確な測定が可能になります。

PerformanceEntry オブジェクトは、パフォーマンスタイムラインの一部です。パフォーマンスエントリーは アプリケーション内の明示的なポイントでパフォーマンスの\*`mark`\* または *`measure`* を作ること（たとえば `mark()` メソッドを呼び出すこと）で直接的に作成されます。パフォーマンスエントリーは、画像などリソースの読み込みのようなタイミングで間接的に作成されることもあります。

PerformanceObserver API はパフォーマンス測定のイベントを観察するために利用できます。さらにブラウザーのパフォーマンスタイムラインに新しいパフォーマンスエントリーが記録されるたびに通知することができます。

この記事ではこれらの API に深入りしませんが、これらの存在を知っていると便利です。パフォーマンスウェブ API を使う例についてより深く知りたい場合はナビゲーションとタイミングの記事を参照してください。

ツールと指標
------

パフォーマンスの改善を助けるために利用できるいくつかの異なるツールがあります。これらは一般的にふたつのカテゴリーに分類できます。

* PageSpeed Insights や Firefox のネットワークモニターと パフォーマンスモニターのようなパフォーマンスを測定したり、指し示したりするツール。これらのツールはウェブアプリケーションやサイトの読み込みがどれくらい速いかまたは遅いかを示します。また、ウェブアプリケーションを最適化して改善するべき領域を指し示します。
* コードを更新してウェブアプリケーションやサイトのパフォーマンスを改善するツール。たとえば、バンドルツールは HTTP リクエストの回数を減らすためにコードを単一のファイルにまとめ、ミニファイツールはファイルをより小さくするためにコードからホワイトスペースを取り除きます。

このコースでは両方のカテゴリーを取り上げます。そしてパフォーマンスの指標だけではなく、サイトのパフォーマンスが改善しているかどうかを測定するための指標についても議論します。

### 一般的なパフォーマンスレポートツール

PageSpeed Insights のようなツールではウェブサイトのパフォーマンスを測定できます。URL を入力すると数秒でパフォーマンスのレポートを入手できます。レポートはモバイルとデスクトップの両方でウェブサイトがどの程度の性能を示すかを表すスコアを含みます。これは、すでにできていることと改善が必要な部分についてのアイデアを得る良いスタート地点になります。

本記事の執筆時点で、MDN のパフォーマンスレポートのサマリーは以下のようになっています。

![Mozilla ホームページの PageSpeed Insights レポートのスクリーンショットです。](/ja/docs/Learn/Performance/Measuring_performance/pagespeed-insight-mozilla-homepage.png)

パフォーマンスレポートは、ページに何かが表示されまでにユーザーがどのくらい待たなければならないか、ページを表示するまでに何バイトのデータがダウンロードされる必要があるかなどの情報を含みます。さらに測定された値が良好と考えられるか、あるいは不良であるかも示します。

webpagetest.org は、サイトを自動的にテストして有益な指標を返すツールのもう一つの実例です。

ぜひ webpagetest.org と PageSpeed Insights の両方であなたの好きなウェブサイトを実行してみてください。そしてスコアを見てみましょう。

### ネットワークツール

多くのブラウザーが、読み込み対象のページに対してそれらがどのように動作しているか確認するために使えるツールを用意しています。たとえば、Firefox のネットワークモニターはネットワークからダウンロードされるすべてのアセットの詳細な情報を、それぞれダウンロードのどのくらいの時間がかかるかを示すグラフと合わせて表示します。

![読み込まれている資産のリストと資産ごとの読み込み時刻を示す Firefox ネットワークモニター](/ja/docs/Learn/Performance/Measuring_performance/network-monitor.png)

異なるアクションを実行したときのウェブアプリケーションやサイトのユーザーインターフェースのパフォーマンスを測定するためにパフォーマンスモニターを利用できます。これは ウェブアプリケーションやサイトを遅くしているかもしれない要素を指し示します。

![開発者ツールのパフォーマンスパネルで、#1 の記録のウォーターフォールを示す。](/ja/docs/Learn/Performance/Measuring_performance/perf-monitor.png)

結論
--

この記事ではウェブアプリケーションやサイトで利用可能なウェブパフォーマンスの指標の簡単な概要を紹介しました。次は、知覚されるパフォーマンスと、避けられないパフォーマンスへの影響をユーザーに深刻に見せない、あるいは完全に気づかれないようにするいくつかのテクニックを見ていきます。

* 前のページ
* Overview: Performance
* 次のページ


JavaScript のパフォーマンス - ウェブ開発を学ぶ

JavaScript のパフォーマンス
===================

* 前のページ
* Overview: Performance
* 次のページ

平均的なウェブサイトでダウンロードされるバイト数のうち、画像や動画がバイト単位で70％以上を占めているのに対し、JavaScript はパフォーマンスに与える悪影響が大きいと言われています。この記事では、スクリプトに起因するパフォーマンスの問題を紹介し、JavaScript をウェブパフォーマンスのために最適化するためのヒントとコツを紹介します。

|  |  |
| --- | --- |
| 前提条件: |
 基本的なコンピューターリテラシー、
 基本的なソフトウェアのインストール、
 クライアント側のウェブ技術の基本的な知識
  |
| 目標: | JavaScript がパフォーマンス最適化に与える影響について、また、JavaScript のファイルサイズだけがウェブパフォーマンスに与える影響ではないことを学ぶ。 |

画像や動画と同様に、パフォーマンスを向上させる最善の方法は、実際には必要でないものを除外することです。しかし、ダウンロードするすべてのバイトが同じ影響を与えるわけではありません。JavaScript のバイトは、ダウンロードし、解釈し、実行する必要があります。JavaScript はダウンロードのパフォーマンスに影響を与えます。そのダウンロードする際の影響を最小限にするためのヒントやトリックに応じたものを紹介します。しかし、JavaScript はメインスレッド、CPU、バッテリーを消費することもあります。そのため、UI が反応しなくなったり、ジャンキーに感じられたりすることがあります。それを処理するための概念も紹介します。

ダウンロードのインパクト
------------

ウェブアプリケーションには、たくさんの JavaScript が含まれています。多くのアプリケーションは、JavaScript フレームワーク、または複数のフレームワークで構築され、さらにいくつかの依存関係があります。A/B テスト、トラッキングピクセル、地図や対応する機能など、サードパーティーのスクリプトや API が追加されることもよくあります。この JavaScript はすべてダウンロードする必要があります。いずれは。

パフォーマンスの最適化には、次のようなことを行う必要があります。

* **必要な JavaScript の量を縮小する。** 複雑な JavaScript を必要とするいくつかの機能は、数行の JavaScript で実行することができます。他にもライブラリーを必要とする機能は開発者の使い勝手を向上させるかもしれませんが、その JavaScript はすべて必要なのでしょうか？もっと軽量なものや自前で開発できるものはないのでしょうか？ある機能は必要ないかもしれませんし、追加することで華やかさは増すかもしれませんが、性能の面でその機能のコストは見合うものでしょうか？
* **使用しないコードを削除する。**
* **JavaScript を小さなファイルに分割する。** JavaScript を重要な部分とそうでない部分にコード分割します。webpack のようなモジュールバンドルはコード分割に対応しています。
* **これらの小さなファイルを最適化する。** Minification は、ファイルの文字数を縮小し、JavaScript のバイト数や重さを軽減します。Gzipping は、さらにファイルを圧縮するもので、Minification を行わない場合でも使用する必要があります。Brotli は Gzip に似ていて、一般的に Gzip の圧縮より優れています。
レンダリングの影響
---------

ウェブアプリケーションには、たくさんの JavaScript が含まれています。多くのアプリケーションは、JavaScript フレームワーク、または複数のフレームワークで構築され、さらにいくつかの依存関係があります。A/B テスト、トラッキングピクセル、地図や対応する機能など、サードパーティーのスクリプトや API が追加されることもよくあります。

バッテリーの影響
--------

まとめ
---

メディアファイルや スクリプトを最適化することで、ウェブパフォーマンスの最適化という点ではとても有利になりますが、ウェブページに触れるものすべてがパフォーマンスに影響します。次の記事では、パフォーマンスに影響を与える可能性のある HTML の機能（パフォーマンスを向上させるために特別に作成された属性を含む）を見ていきます。

* 前のページ
* Overview: Performance
* 次のページ


マルチメディア: 動画 - ウェブ開発を学ぶ

マルチメディア: 動画
===========

* 前のページ
* Overview: Performance
* 次のページ

前回学んだように、平均的なウェブサイトでダウンロードされるバイトのうち、画像と動画のメディアは 70% 以上を占めています。画像の最適化については、すでに見ていきました。この記事では、ウェブのパフォーマンスを向上させるために動画を最適化することについて見ていきます。

|  |  |
| --- | --- |
| 前提条件: |
 基本的なコンピューターリテラシー、
 基本的なソフトウェアのインストール、
 クライアント側のウェブ技術の基本的な知識
  |
| 目標: | さまざまな動画形式とそのパフォーマンスへの影響について学び、それぞれのブラウザーのファイル種類に対応した最小の動画ファイルサイズを提供しながら、ページ全体の読み込み時間への動画の影響を縮小する方法を学びます。 |

なぜマルチメディアを最適化するのか？
------------------

平均的なウェブサイトでは、帯域幅の 25% が動画によるものです。動画を最適化することで、とても大きな帯域幅の節約になり、ウェブサイトのパフォーマンス向上に対応させることができる可能性があります。

動画配信の最適化
--------

下記の節では、最適化技術について記述しています。

* すべての動画を圧縮する
* `<source>` の順を最適化する
* 自動再生の設定
* ミュートされた動画から音声を削除する
* 動画の先読みを最適化する
* ストリーミングを検討する
### すべての動画を圧縮する

ほとんどの動画圧縮作業は、動画内の隣接するフレームを比較し、両フレームで同一である細部を削除しようとするものです。動画を圧縮して、WebM、MPEG-4/H.264、Ogg/Theoraなど、複数の動画形式にエクスポートしましょう。

お使いの動画編集ソフトには、ファイルサイズを縮小する機能があると思います。そうでない場合は、FFmpeg（下記の節で説明）などのオンラインツールがあり、エンコード、デコード、変換、その他の最適化機能を実行することができます。

### `<source>` の順を最適化する

動画ソースを小さいものから大きいものへと順番に並べてください。例えば、10MB、12MB、13MB の異なる形式の動画が指定された場合、小さいものを最初に、大きいものを最後に宣言してください。

```html
<video width="400" height="300" controls="controls">
  <!-- WebM: 10 MB -->
  <source src="video.webm" type="video/webm" />
  <!-- MPEG-4/H.264: 12 MB -->
  <source src="video.mp4" type="video/mp4" />
  <!-- Ogg/Theora: 13 MB -->
  <source src="video.ogv" type="video/ogv" />
</video>
```

ブラウザーは、理解できる最初の形式をダウンロードします。目標は、大きなバージョンよりも小さなバージョンを先に提供することです。最小のバージョンでは、最も圧縮された動画がまだ良く見えることを確認します。アニメーション GIF のように、動画が（悪く）見えてしまうような圧縮アルゴリズムもあります。128KB の動画は、10MB のダウンロードよりも使い勝手が良いように思えるかもしれませんが、GIF のような粗い動画は、そのブランドやプロジェクトの印象を悪くしてしまうかもしれません。

動画や他のメディア種類のブラウザーの現在の対応については、CanIUse.comを参照してください。

### 動画の自動再生

ループする背景動画が確実に自動再生されるようにするには、video タグに `autoplay`、`mute`、`playsinline` などいくつかの属性を追加する必要があります。

```html
<video
 autoplay=""
 loop=""
 muted="true"
 playsinline=""
 src="backgroundvideo.mp4"></video>
```

ループ動画や自動再生動画では `loop` と `autoplay` に意味がありますが、モバイルブラウザーでの自動再生には `muted` 属性が必要です。

`Playsinline` はモバイル Safari に必要で、全画面モードを強制することなく動画を再生できるようにします。

### ミュートされたヒーロー動画から音声を削除する

ヒーロー動画など音声のない動画では、音声を削除するのがスマートです。

```html
<video autoplay="" loop="" muted="true" playsinline="" id="hero-video">
  <source src="banner\_video.webm" type='video/webm; codecs="vp8, vorbis"' />
  <source src="web\_banner.mp4" type="video/mp4" />
</video>
```

このヒーロー動画コード（上）は、会議のウェブサイトや企業のホームページによく見られるものです。自動再生、ループ、ミュートされる動画が記載されています。制御するものがないため、音声を聞く方法がありません。音声は空であることが多いですが、それでも存在し、帯域幅を使用しています。常にミュートされている動画と一緒に音声を提供する理由はありません。**音声を削除することで、帯域幅を 20% 節約することができます**。

ソフトウェアの選択によっては、書き出しや圧縮の際に音声を削除できるかもしれません。そうでない場合は、FFmpeg という無料のユーティリティがそれをやってくれます。これは音声を削除するための FFmpeg のコマンド文字列です。

```bash
ffmpeg -i original.mp4 -an -c:v copy audioFreeVersion.mp4
```

### 動画の先読み

preload 属性には、利用できる選択肢が3つあります。`auto`|`metadata`|`none` です。既定値は `metadata` です。これらの設定は、ページ読み込み時に動画ファイルをどれだけダウンロードするかを制御します。人気のない動画のダウンロードを延期することで、データを節約することができます。

`preload="none"` を設定すると、再生するまで動画は一切ダウンロードされません。起動は遅くなりますが、再生の可能性が低い動画では大幅なデータ削減が可能です。

より緩やかな帯域幅の節約になりますが、`preload="metadata"` を設定すると、ページ読み込み時に動画の最大 3% をダウンロードすることができます。これは、小さなファイルや中程度の大きさのファイルに対して有益なオプションです。

`auto` に設定するには、ブラウザーに動画全体を自動的にダウンロードするように指示します。この設定は、再生する可能性がとても高い場合にのみ行ってください。そうでない場合は、多くの帯域幅を浪費することになります。

### ストリーミングを検討する

動画ストリーミングでは、適切な動画サイズと帯域幅（ネットワーク速度に基づく）でエンドユーザーに配信することができます。レスポンシブ画像と同様に、適切なサイズの動画がブラウザーに配信されるため、動画の高速起動、少ないバッファリング、最適化された再生が保証されます。

まとめ
---

動画を最適化することで、ウェブサイトのパフォーマンスを大幅に向上させる可能性があります。動画ファイルは、他のウェブサイトのファイルと比較して比較的大きく、常に注意を払う必要があります。この記事では、ファイルサイズの縮小、(HTML) ダウンロード設定、ストリーミングによるウェブサイトの動画の最適化について説明します。

* 前のページ
* Overview: Performance
* 次のページ


ウェブパフォーマンスとは - ウェブ開発を学ぶ

ウェブパフォーマンスとは
============

* 前のページ
* Overview: Performance
* 次のページ

ウェブパフォーマンスとは、遅い処理を速く*見せる*ことも含めて、ウェブサイトを速くすることです。サイトがすぐに読み込まれるか、ユーザーがすぐに操作を始めることができるか、何かの読み込みに時間がかかっている場合には安心感のあるフィードバック (ローディングスピナーなど) を提供しているか。スクロールやアニメーションはスムーズか。この記事では、客観的で測定可能なウェブパフォーマンス\*について簡単に紹介し、ウェブの最適化にどのような技術、テクニック、ツールが必要なのかを見ていきます。

|  |  |
| --- | --- |
| 前提条件: |
 基本的なコンピューターリテラシー、
 基本的なソフトウェアのインストール、
 クライアント側のウェブ技術の基本的な知識
  |
| 目標: | ウェブパフォーマンスに関わる事項について基本的な理解を得ること。 |

*\* 次の記事で扱う主観的な知覚的パフォーマンスの対義語*

ウェブパフォーマンスとは何か
--------------

ウェブパフォーマンスはウェブサイトまたはウェブアプリケーションの客観的な測定結果とユーザーによって知覚される体験です。これには以下の主要な領域が含まれます。

* **全体の読み込み時間を減らすこと**: ウェブサイトの表示に必要なファイルが、ユーザーのコンピューターにダウンロードされるまでの時間です。これは、レイテンシー (en-US)、ファイルの大きさ、ファイルの数、その他の要因に影響される傾向があります。一般的な戦略としては、ファイルをできるだけ小さくしたり、 HTTP リクエストの数をできるだけ減らしたり、ファイルをより早く利用できるようにするための賢い読み込み技術 (先読みなど) を採用したりすることです。
* **サイトをできるだけ早く利用可能にすること**: これは基本的に、ユーザーが実際にすぐに使い始めることができるように、ウェブサイトの資産を適切な順序で読み込むことを意味します。ユーザーが主要な作業をしている間、他の資産はバックグラウンドでロードし続けることができます。また、実際に必要なときにだけ資産を読み込む場合もあります (これを遅延読み込みといいます)。読み込みを開始してから、サイトが利用可能な状態になるまでの時間を測定したものを time to interactive と呼びます。
* **スムーズさとインタラクティブ性**：そのアプリケーションは使っていて信頼でき、楽しいと感じられますか？スクロールはスムーズですか？ボタンはクリックできますか？ポップアップはすぐに開いてスムーズにアニメーションしますか？アプリケーションがスムーズだと感じさせるための様々なベストプラクティスがあります。たとえば、アニメーションのために JavaScript ではなく CSS を使うこと、DOM の変更により UI が要求する再描画の回数をできる限り少なくすることなどが挙げられます。
* **知覚的パフォーマンス**：ウェブサイトがユーザーにとっていかに速いように見せるかは、ウェブサイトが実際に速いがどうかよりもユーザーの体験への大きなインパクトがあります。ユーザーがパフォーマンスについてどう感じるかは重要です。あるいは、それは客観的な統計以上に重要です。しかし、それは主観的なもので、簡単に測定できるものではありません。知覚されたパフォーマンスは測定項目 (metric) ではなく、ユーザーからの見え方を表します。レイテンシーやそのほか何かの問題で操作に長い時間がかかる場合であっても、たとえば待ち時間の間にローディングスピナーを表示したり、便利なヒントやティップスを表示したり（他にはジョークや、その他適切だと思えるものであれば何でも良いです）することでユーザーのエンゲージを維持することは可能です。そういったアプローチはただ何も表示しないよりもずっと良いと言えます。何も表示されない時間は長く感じられ、その結果ユーザーはウェブサイトが壊れていると考えて利用をやめてしまう可能性もあります。
* **パフォーマンスの測定**：ウェブパフォーマンスにはアプリケーションの実際の速度と知覚的な速度を計測すること、パフォーマンスをできる限り最適化しその結果が維持されているか監視するという面があります。そこではいくつかのメトリクス（成功か失敗かを表す測定可能な指標）とそれらのメトリクスを測定するツールが必要になります。本記事の全体を通してそれらを検討します。

まとめると、たくさんの要素がパフォーマンスに影響を与えます。レイテンシー、アプリケーションのサイズ、DOM ノードの数、リクエストされるリソースの数、JavaScript の性能、CPU 負荷、その他いろいろです。それらの読み込みとレスポンスの時間を小さくすることが重要です。それから、ユーザーの体験上後で必要になる部分を同期で読み込むなどして、サイトが利用可能になる時間をできる限り早くすることでレイテンシーを感じさせないようにするといった追加の要素も重要です。

**メモ:** ウェブのパフォーマンスには、Time to load、Frames per second、Time to interactive のような客観的や測定結果とコンテンツの読み込みがどれくらい長く感じられるかといった主観的な経験の両方が含まれます。

コンテンツはどのように描画されるか
-----------------

効率的にウェブパフォーマンス、その背後にある問題やここまでに挙げた主要なトピックを理解するためにはブラウザーがどのように動作するかについていくつかの詳細を理解することが必要です。これには以下のトピックが含まれます。

* **ブラウザーはどのように動作するか**：URL を入力し、
 `Enter`
 /
 `Return`
 を打ち込んだとき、ブラウザーはウェブサイトのファイルを持っているサーバーがどこにあるかを探しだし、そのサーバーとの接続を確立し、ファイルをリクエストします。詳しい概要は「ページの生成：ブラウザーはどのように動作するか」を参照してください。
* **ソースコードの順番**：HTML の index ファイル上のソースの順番はパフォーマンスに重大な影響を及ぼす場合があります。index ファイルからリンクされた追加の資産のダウンロードは、一般的にソースコードの順番に従ってシーケンシャルに実行されます。しかし、この部分はいくつかのリソースがそのコンテンツが解析、実行されるまで追加のダウンロードをブロックすることに気づくことで最適化できるようになります。
* **クリティカルパス**：これはファイルがサーバーからダウンロードされた後にブラウザーがウェブのドキュメントを構築するプロセスのことを指します。ブラウザーは明確に定義されたステップに従って、クリティカルレンダリングパスを最適化し、そのときのユーザーのアクションに関連するコンテンツの表示に優先順位をつけて、コンテンツの描画時間を大きく改善します。より詳しい情報は、Critical rendering path (en-US) を参照してください。
* **ドキュメントオブジェクトモデル**：ドキュメントオブジェクトモデル (DOM) は HTML のコンテンツと要素をツリーのノードとして表現するツリー構造を指します。そこには HTML のすべての属性とノード間の関係が含まれます。ページがロードされた後の追加の DOM 操作（たとえば、ノードの追加、削除、移動）はパフォーマンスに影響を与えます。そのため、DOM がどのように動作し、その問題をどのように和らげるかを理解するを理解することが重要です。詳しくは Document Object Model を参照してください。
* **レイテンシー**：事前に述べましたが、簡単に言うと、レイテンシーとは、Web サイトの資産がサーバーからユーザーのコンピューターまで移動するのにかかる時間のことです。そこには TCP と HTTP の接続を確立にかかるオーバーヘッドも含まれます。そして、リクエストとレスポンスのデータ (bytes) がネットワーク間を行き来するために必要となる避けようのないレイテンシーがあります。一方で、レイテンシーを減らすためのいくつかの方法があります。（たとえば、ダウン読み込むファイルの数を減らすことで HTTP リクエストの数を減らすこと、CDN を利用してサイトのデータを世界中に効率よく展開すること、サーバーがより効率よくファイルを提供できるように HTTP/2 を利用することなどが挙げられます）このトピックに関わるすべての事柄は Understanding Latency (en-US) を参照してください。
結論
--

以上です。ウェブパフォーマンスのトピックに関するこの簡潔な要約が、あなたが全体のアイデアを理解するための助けとなり、さらに学ぶ意欲をかき立てることができたなら幸いです。この後は知覚されたパフォーマンスを取り上げ、避けられないパフォーマンスへの影響を、ユーザーにとって深刻に見えないようにする、あるいは完全に気づかれないようにする賢い方法について見ていきます。

* 前のページ
* Overview: Performance
* 次のページ


ウェブパフォーマンスの基礎 - ウェブ開発を学ぶ

ウェブパフォーマンスの基礎
=============

 あなたのウェブサイトが可能な限りのパフォーマンスを発揮すべき理由はたくさんあります。
 以下に、各トピックの詳細情報を提供するためのリンク付きのベストプラクティス、ツール、API の簡単なレビューを示します。

Best practices
--------------

* Start with learning the critical rendering path (en-US) of the browser. Knowing this will help you understand how to improve the performance of the site.
* Using resource hints such as `rel=preconnect, rel=dns-prefetch, rel=prefetch, and rel=preload`
* Keep the size of Javascript to a minimum. Only use as much Javascript as needed for the current page.
* CSS (en-US) performance factors
* Use HTTP/2 on your server (or CDN).
* Use a CDN for resources which can reduce load times significantly.
* Compress your resources using gzip, Brotli, and Zopfli.
* Image optimization (use CSS animation, or SVG if possible).
* Lazy loading parts of your application outside the viewport. If you do, have a backup plan for SEO (e.g render full page for bot traffic); for example, by using the `loading` attribute on the `<img>` element
* It is also crucial to realize what is really important to your users. It might not be absolute timing, but user perception.
Quick Wins
----------

### CSS

Web performance is all about user experience and perceived performance. As we learned in the critical rendering path (en-US) document, linking CSS with a tradional link tag with rel="stylesheet" is synchronous and blocks rendering. Optimize the rendering of your page by removing blocking CSS.

To load CSS asynchronously one can simpy set the media type to print and then change to all once loaded. The following snippet includes an onload attribute, requiring Javascript, so it is important to include a noscript tag with a traditional fallback.

```html
<link
 rel="stylesheet"
 href="/path/to/my.css"
 media="print"
 onload="this.media='all'" />
<noscript><link rel="stylesheet" href="/path/to/my.css" /></noscript>
```

The downside with this approach is the flash of unstyled text (FOUT.) The simplist way to address this is by inlining CSS that is required for any content that is rendered above the fold, or what you see in the browser viewport before scrolling. These styles will improve perceived performance as the CSS does not require a file request.

```html
<style type="text/css">
 // Insert your CSS here
</style>
```

### Javascript

Avoid Javascript blocking by using the async or defer attributes, or link javascript assets after the page's DOM elements. Javascript only block rendering for elements that appear after the script tag in the DOM tree.

### Web Fonts

EOT and TTF formats are not compressed by default. Apply compression such as GZIP or Brotli for these file types. Use WOFF and WOFF2. These formats have compression built in.

Within @font-face use font-display: swap. By using font display swap the browser will not block rendering and will use the backup system fonts that are defined. Optimiize font weight to match the web font as closely as possible.

#### Icon web fonts

If possible avoid icon web fonts and use compressed SVGs. To further optimize inline your SVG data within HTML markup to avoid HTTP requests.

Tools
-----

* Learn to use the Firefox Dev Tools to profile your site.
* Pagespeed Insights can analyze your page and give some general hints to improve performance.
* Lighthouse can give you a detailed breakdown of many aspects of your site including performance, SEO and accessibility.
* Test your page's speed using Webpagetest.org, where you can use different real device types and locations.
* Try the Chrome User Experience Report which quantifies real user metrics.
* Define a performance budget.
### APIs

* Gather user metrics using https://github.com/akamai/boomerang
* Or directly gather with window.performance.timing
### Things not to do (bad practices)

* Download everything
* Use uncompressed media files
関連情報
----

* https://github.com/filamentgroup/loadCSS


ウェブパフォーマンスのビジネスケース - ウェブ開発を学ぶ

ウェブパフォーマンスのビジネスケース
==================

* 前のページ
* Overview: Performance
* 次のページ

ここまで、ウェブパフォーマンスの重要性についてお話してきました。ウェブパフォーマンスを最適化するために何をすべきかを学びました。しかし、クライアントや経営陣にパフォーマンスに優先順位をつけて投資するように説得するにはどうすればよいのでしょうか？このセクションでは、意思決定者に投資をするように説得するための明確なビジネスケースの作成について説明します。

|  |  |
| --- | --- |
| 前提条件: |
 基本的なコンピューターリテラシー、
 クライアント側のウェブ技術の基本的な知識、
 ウェブパフォーマンス最適化の基本的な知識。
  |
| 目標: | クライアントや経営者に ウェブパフォーマンスを優先してもらい、自信を持って仕事ができるようになること。 |

パフォーマンスをビジネスの優先事項にする
--------------------

パフォーマンスを優先することで、ユーザーの使い勝手が向上し、その結果、収益が向上することは、これまでにも説明してきたとおりです。ウェブパフォーマンスを優先しない場合、事業収益が失われる可能性があることも知っています。この記事では、特定のビジネス指標がユーザーのウェブパフォーマンス体験にどのように直接関連しているか、また、ユーザーのウェブパフォーマンス体験を向上させるためにサービスデザインをどのように適用するかについて説明します。累積的な体験がコンバージョン率やリテンション率にどのような影響を与えるかを理解することの重要性を強調しています。

### パフォーマンス予算

ウェブパフォーマンス予算を設定することで、チームがサイトを維持するための軌道に乗っているかどうかを確認し、回帰を防ぐのに役立ちます。パフォーマンスバジェットとは、維持しなければならない最大の http リクエスト数、すべてのアセットを合わせた最大の合計サイズ、特定のデバイスでの最小許容 FPS などの制限を指定するために設定される制限のセットです。予算は、単一のファイル、ファイルタイプ、ページに読み込まれたすべてのファイル、特定のメトリック、または一定期間のしきい値に適用することができます。

予算を定義して推進することで、マーケティング、セールス、さらにはビデオやサードパーティスクリプト、フレームワークを追加したいと考えている他の開発者など、競合する利害関係者に対抗して、優れたユーザーエクスペリエンスを提供するためのパフォーマンス推進者を支援することができます。パフォーマンス予算 (en-US)は、開発者チームがユーザーのために最適なパフォーマンスを保護し、ビジネスが新しい市場に参入してカスタム体験を提供できるようにするのに役立ちます。

### Key Performance Indicators

目標として主要業績評価指標 (KPI) を設定することで、ビジネスの目標でもある業績目標を明確にすることができます。KPI は、ユーザーエクスペリエンスとパフォーマンスがビジネスのトップラインに与える影響を測定する上で重要なビジネス指標のセットであると同時に、パフォーマンスに優先順位をつけることのメリットを示す方法でもあります。ここでは、検討すべき KPI をいくつか紹介します。

**コンバージョン率 (CR)**

購入の完了やニュースレターへの登録など、意図した行動をとったトラフィックの割合。ビジネスサイトの表示速度が遅いと、ユーザーが意図したタスクを完了できないことがあります。これは、コンバージョン率の低下につながる可能性があります。

**Time on Site**

集計したユーザーがサイトに費やす平均時間。サイトのパフォーマンスが低下すると、ユーザーはサイトを早期に放棄する可能性が高くなり、サイトの計測にかかる時間が短くなる可能性があります。

**ネットプロモーションスコア (NPS)**

ネットプロモーションスコア (NPS) は、企業のブランド、製品、サービスに対する顧客の忠誠心を評価するための指標です。ユーザーのパフォーマンスが悪いと、ブランドの評判が悪くなります。

KPI としてコンバージョン率、サイト上の時間、および/またはネットプロモーションのスコアを設定すると、ウェブパフォーマンスの努力に財務および他のビジネス目標の価値を与え、努力の価値を証明するための指標を使用して、購入を後押しするのに役立ちます。

* 前のページ
* Overview: Performance


知覚的パフォーマンス - ウェブ開発を学ぶ

知覚的パフォーマンス
==========

* 前のページ
* Overview: Performance
* 次のページ

**知覚的パフォーマンス** は、ユーザーから見てウェブサイトがどれくらい速く感じられるかを表します。ユーザーがパフォーマンスをどのように知覚するかは、具体的な統計値と同じくらい、あるいはどんな具体的な統計値よりも重要ですが、それは主観的で簡単に計測できるものではありません。知覚的パフォーマンスはユーザーの視点であり、計測される値ではありません。

この記事は、ユーザーの知覚と、主観的な要素を計測するために使える具体的なツールに目を通し、知覚的パフォーマンスの簡潔な紹介を提供します。

|  |  |
| --- | --- |
| 前提条件: |
 基本的なコンピューターリテラシー、
 基本的なソフトウェアのインストール、
 クライアントサイドのウェブ技術の基本的な知識
  |
| 目的: | ウェブパフォーマンスに対するユーザーの知覚について基本的な理解を獲得すること。 |

概要
--

ページの読み込みやユーザーとの対話がいかにすばやく（スムーズに）行われるかという認識は、リソースを読み込むのに必要な実際の時間以上に重要です。物理的にサイトを速く実行することはできないかもしれませんが、ユーザーにとってどれだけ速く感じられるかを改善することは十分に可能です。

知覚的なパフォーマンスを向上させるための一般的なルールは、通常、処理が完全に完了するまで（何か情報を提供するまで）ユーザーを待たせるよりも、すばやくレスポンスを提供し、定期的に状況を更新したほうが良いというものです。例 えば、ページを読み込むとき、画像や他のリソースをすべて待つよりも、テキストが到着した時点で表示する方が良いでしょう。たとえコンテンツが完全にダウンロードされていなくても、ユーザーは何かが起こっていることを確認でき、コンテンツを操作し始めることができる。

**メモ:** 何かが起こるのを受動的に待っているユーザーよりも、積極的に関与したり、気を引いたり、楽しませたりしているユーザーの方が、時間がすばやく経過するように見えるようです。可能な限り、タスクの完了を待っているユーザーに積極的に関わり、情報を提供しましょう。

同様に、ユーザーが長時間実行する処理を行うためにリンクをクリックすると、すぐに「読み込み中アニメーション」を表示したほうが良いでしょう。処理にかかる時刻は変わりませんが、サイトがよりレスポンスよく感じられ、ユーザーは何か有益な作業に取り組んでいることを認識できます。

パフォーマンス指標
---------

ユーザーが「どう感じるか」を評価するために、サイトで実行することができる単一の指標やテストはありません。しかし、「役立つ指標」となりうる指標はいくつもあります。

ファーストペイント (First paint)

最初の描画処理が始まるまでの時間です。この変更は目に見えないかもしれないことに注意してください。単純な背景色の更新であったり、もっと目立たないものであったりします。

FCP (First Contentful Paint)

最初の重要なレンダリング（テキスト、前景または背景画像、キャンバス、SVG など）までの時間。このコンテンツは必ずしも有益なものではないことに注意してください。

FMP (First Meaningful Paint)

有益なコンテンツが画面に描画されるまでの時間です。

LCP (Largest Contentful Paint)

ビューポートで表示される最大のコンテンツ要素のレンダリング時間。

スピードインデックス (SI)

可視画面上のピクセルが描かれるまでの平均時間を測定します。

TTI (Time to interactive)

ユーザーと対話できるユーザーインターフェイスが完成するまでの時間（読み込んだプロセスの最後のロングタスクが完了するまでの時間）。

パフォーマンスの改善
----------

知覚的パフォーマンスを改善するヒントとコツを以下に示します。

### 最初の読み込みの最小化

知覚的パフォーマンスを向上させるには、元ページの読み込みを最小限に抑えることです。言い換えれば、ユーザーがすぐに対話するコンテンツを最初にダウンロードし、残りは「バックグラウンドで」ダウンロードします。ダウンロードするコンテンツの総量は実際に増えるかもしれませんが、ユーザーはとても小さな量しか待っていないので、ダウンロードはより速く感じられます。

対話型機能をコンテンツから分離し、初回読み込み時に表示されるテキスト、スタイル設定、画像を読み込みます。初回のページ読み込み時に使用されない、または表示されない画像やスクリプトは、後回しにするか、遅延読み込みを行います。さらに、読み込む資産を最適化する必要があります。画像や動画は、最適な形式で、圧縮して、適切なサイズで提供する必要があります。

### コンテンツのジャンプとリフローの防止

画像やサードバーティーの広告のような、コンテンツを押し下げたり他の場所にジャンプさせたりするアセットは、ページがまだ読み込み中であるように感じさせ、知覚的パフォーマンスを悪化させます。ユーザーの操作に起因することなくリフローするコンテンツは、特に悪いと言えます。他と比べて読み込みが遅く、かつ他のコンテンツが画面に描画された後に要素が読み込まれるアセットは、レイアウト上にそれらのためのスペースを残すよう事前に計画しましょう。そうすることでコンテンツは、とくにサイトが操作可能になった後で、ジャンプやリサイズしなくなります。

### フォントファイルの遅延をの防止

フォント選びは重要です。適切なフォントを選択することで、ユーザー体験を大きく向上させることができます。知覚的なパフォーマンスの観点からすると、「最適でないフォントのインポート」により、テキストがスタイル設定されたとき、他にもフォントを代替する際にちらつきが発生することがあります。

同じサイズとウェイトの代替フォントを用意しておきましょう。そうすることでフォントの読み込みによるページの変化に気付かれにくくなります。

### 操作可能な要素は操作可能に

目に見える操作可能な要素は常に操作可能で反応できるようにしましょう。入力の要素が目に見える場合、ユーザーは遅延なしにそれらと操作できるべきです。ユーザーは反応に 50 ミリ秒より長い時間がかかる場合、それが遅れていると感じます。コンテンツの再描画が 16.67 ミリ秒（または 60 fps）より遅いか、不規則な間隔で再描画されるとページが壊れているように感じます。

CSS で入力用のモーダルを表示したり、可能な場合は JS で先行入力・自動補完を追加するなど、先行入力やプログレッシブエンハンスメントを使いましょう。

### タスクの開始をより操作可能にする

`keyup` を待つのではなく、`keydown` でコンテンツをリクエストすることで、コンテンツの読み込まれる負荷を 200ms 削減することができます。`keyup` イベントに、面白いが控えめな 200ms のトランジションを追加することで、さらに 200ms の読み込む時間を短縮することができます。400ms の時間を節約することはできませんが、ユーザーはコンテンツを待つまで、もとい、コンテンツを待っているように感じることはないでしょう。

まとめ
---

ユーザーが有用なコンテンツを待つ時間を短縮し、レスポンシブで魅力的なサイトを維持することで、ユーザーは、リソースの読み込みにかかる実際の時間が変わらなくても、サイトのパフォーマンスが向上しているように感じることができるのです。

* 前のページ
* Overview: Performance
* 次のページ


マルチメディア: 画像 - ウェブ開発を学ぶ

マルチメディア: 画像
===========

* 前のページ
* Overview: Performance
* 次のページ

画像や動画といったメディアは、平均的なウェブサイトでダウンロード量の 70% 以上を占めています。ダウンロードのパフォーマンスという観点からは、メディアを減らし、ファイルサイズを縮小することは、低いハードルであると言えます。この記事では、ウェブパフォーマンスを向上させるために画像や動画を最適化することについて見ていきます。

|  |  |
| --- | --- |
| 前提条件: |
 基本的なコンピューターリテラシー、
 基本的なソフトウェアのインストール、
 クライアント側のウェブ技術の基本的な知識
  |
| 目標: | さまざまな画像形式とそのパフォーマンスへの影響、そして画像がページ全体の読み込む時刻に与える影響を縮小する方法について学ぶ。 |

**メモ:** これは、ウェブ上でのマルチメディア配信を最適化するための高レベルな入門書であり、一般的な原則とテクニックに応じたものです。より詳細なガイドについては、 https://web.dev/learn/images を参照してください。

なぜマルチメディアを最適化するのか
-----------------

平均的なウェブサイトでは、帯域幅の 51% が画像、続く 25% が動画であり、マルチメディアコンテンツに対応し最適化することが重要であると言ってもよいでしょう。

データ使用量に配慮する必要があります。多くの人は、上限付きのデータプラン、あるいは文字通りメガバイト単位で支払う従量制のデータプランを利用しています。これは新興市場の問題でもありません。2018 年現在、イギリスの 24% がまだ従量制課金を使用しています。

また、多くのモバイル端末では RAM に制限があるため、メモリーにも配慮する必要があります。画像がダウンロードされると、メモリーに格納される必要があることを覚えておくことが重要です。

画像配信の最適化
--------

帯域幅を最も消費するにもかかわらず、画像のダウンロードが知覚的パフォーマンスに与える影響は、多くの人が予想するよりはるかに小さいです（主に、ページのテキストコンテンツはすぐにダウンロードされ、ユーザーは到着時に画像のレンダリングを見ることができるからです）。しかし、使い勝手を良くするためには、訪問者ができるだけ早く見ることができることが重要であることに変わりはありません。

### 読み込み戦略

多くのウェブサイトにおける最大の改善点のひとつは、画像を見える直前に遅延読み込みすることで、訪問者がスクロールして見るかどうかにかかわらず、最初のページ読み込み時にすべてダウンロードしないようにすることです。多くの JavaScript ライブラリー、たとえば lazysizes などで、これを実装することができます。また、ブラウザーベンダーは、現在実験段階であるネイティブの `lazyload` 属性に取り組んでいます。

画像のサブセットを読み込むだけでなく、画像そのものの形式も見ていく必要があります。

* 最適なファイル形式を読み込んでいますか？
* 画像はしっかり圧縮してありますか？
* 正しいサイズを読み込んでいますか？

#### 最も適した形式

最適なファイル形式は、通常、画像の性格によって異なります。

**メモ:** 画像の種類に関する一般的な情報は、画像ファイルの種類と形式ガイドを参照してください。

SVG 形式は、色が少なく、写真のようにリアルでない画像に適しています。この場合、ソースがベクターグラフィック形式で利用できることが必要です。そのような画像がビットマップとしてしか存在しない場合は、PNG が予備のフォーマットとして選ばれます。この種類のモチーフの例としては、ロゴ、イラスト、図表、アイコンなどがあります（メモ: SVG はアイコンフォントよりもはるかに優れています！）。どちらの形式も透過に対応しています。

PNG は 3 種類の出力の組み合わせで保存することができます。

* 24 ビットカラー＋8 ビット透過率 - サイズを犠牲にして、完全な色精度と滑らかな透過率を提供します。この組み合わせは避け、WebP（下記参照）にした方がよいでしょう。
* 8 ビットカラー＋8 ビット透過率 - 255 色を超えることはできないが、滑らかな透過率を維持することができます。サイズはあまり大きくありません。これらは、おそらく使いたい PNG です。
* 8 ビット色＋1 ビット透過率 - 255 色を超えることはできず、ただピクセルごとに非透過または完全透過のどちらかだけを提供するため、透過率の境界線が硬くギザギザに見えます。サイズは小さいが、視覚的な忠実さが代償となります。

SVGを最適化するための良いオンラインツールとしては、SVGOMG があります。PNG の場合は、ImageOptim online や Squoosh があります。

透過のない写真モチーフの場合、選べる形式の範囲はかなり広くなります。安全性を重視するならば、圧縮率の高い**プログレッシブ JPEG** をお勧めします。プログレッシブ JPEG は、通常の JPEG とは異なり、プログレッシブにレンダリングします（そのため、この名前がついています）。つまり、画像が上から下まで完全な解像度で読み込まれたり、ダウンロードが完了したりしてから表示されるのではなく、ユーザーには低解像度のバージョンが表示され、ダウンロードが進むにつれて鮮明になっていく様子が見えます。このような場合に適した圧縮ソフトは MozJPEG で、例えばオンライン画像最適化ツール Squoosh で使用することができます。品質設定は 75% で、適切な結果が得られるはずです。

他にも、圧縮に関して JPEG より能力を上回る形式がありますが、すべてのブラウザーで利用できるわけではありません。

* WebP — 画像とアニメーション画像の両方に最適な選択肢です。WebP は PNG や JPEG よりもはるかに優れた圧縮率を持ち、より高い色深度、アニメーションフレーム、透過率などに対応しています（ただし、プログレッシブ表示には対応していません）。macOS デスクトップ Big Sur の Safari 14 以前を除く、主要なブラウザーで対応しています。

**メモ:** Apple が Safari 14 で WebP の対応を発表しているにもかかわらず、 Safari のバージョン 16.0 より前では、 macOS の 11/Big Sur より前のデスクトップ版では正常に `.webp 画像が表示されなせん、 iOS 14 の Safari では` .webp` 画像が正しく表示されます。
* AVIF — 高性能でロイヤリティフリーの画像形式であるため、画像とアニメーション画像の両方に適しています（WebP よりもさらに効率的ですが、対応はそれほど広くありません）。これで Chrome、Opera、Firefox で対応しています。以前の画像形式を AVIF に変換するオンラインツールも参照してください。
* **JPEG2000** — かつては JPEG の後継とされていましたが、Safari でのみ対応しています。プログレッシブ表示にも対応していません。

JPEG-XR と JPEG2000 の対応も狭く、デコードするコストも考慮すると、JPEG の対抗馬は WebP しかありません。そのため、画像も WebP で提供することができます。これは、`<picture>` 要素で type 属性を備えた `<source>` 要素により補助することで実現することができます。

もし、この作業がすべて複雑で、チームにとって負担が大きいと感じるのであれば、画像 CDN として使用できるオンラインサービスもあります。このサービスは、画像をリクエストされた機器や ブラウザーの種類に応じて、その場で正しい画像形式を自動配信してくれます。Cloudinary や Image Engine が代表的なものです。

しすて最後に、ページにアニメーション画像を掲載するために、Safari では `<img>` と `<picture>` 要素に動画ファイルを使用することができることをご存知でしょうか？他にも現代のブラウザーでは、**アニメーション WebP** を追加することができます。

```html
<picture>
  <source type="video/mp4" src="giphy.mp4" />
  <source type="image/webp" src="giphy.webp" />
  <img src="giphy.gif" alt="A GIF animation" />
</picture>
```

#### 最適なサイズでの提供

画像配信では、「ひとつのサイズですべてをカバーする」手法は最良の結果をもたらしません。つまり、小さな画面にはより小さな解像度の画像を、大きな画面にはその逆の画像を配信したいものです。また、高 DPI 画面（例えば "Retina"）の機器には、より高解像度の画像を提供したいものです。そのため、中間画像のバリエーションをたくさん作成するだけでなく、正しいファイルを正しいブラウザーに提供する方法も必要です。そこで、`<picture>` と `<source>` 要素に media や sizes 属性を付けてアップグレードする必要があるのです。これらの属性をすべて組み合わせる方法についての詳しい記事はこちらにあります。

高解像度画面に関して、興味深い効果が 2 つあります。

* 高 DPI 画面では、人間は圧縮による劣化を感じにくくなるため、このような画面向けの画像では、通常よりも圧縮率を上げることができます。
* 2x を超える DPI の解像度の上昇を見抜ける人はとても少ないため、2x を超える解像度の画像を提供する必要はないということです。

#### ダウンロードする画像の優先順位（順番）の制御

重要度の高い画像を、重要度の低い画像よりも早く取得することで、知覚的パフォーマンスを向上させることができます。

最初に確認することは、コンテンツ画像に `<img>` 要素または `<picture>` 要素を使用しているか、背景画像を CSS の `background-image` で定義しているかということです。`<img>` 要素で参照する画像は、背景画像より高い読み込み優先度が割り当てられます。

2 つ目は、優先度ヒントの採用により、画像タグに `fetchPriority` 属性を追加することで、さらに優先度を制御できるようになることです。画像に優先度ヒントを使用する例としては、最初の画像が後続の画像よりも高い優先度を持つカルーセルが挙げられます。

### レンダリング戦略: 画像を読み込むときのジャンクの防止

画像は非同期で読み込まれ、最初の描画の後も読み込まれ続けるため、読み込む前にサイズを定義しておかないと、ページコンテンツに再フローを発生させてしまうことがあります。例 えば、画像の読み込みによってテキストがページ下に押し出されるような場合です。このため、`width` と `height` 属性を設定し、ブラウザーがレイアウトにそれらのための空間を確保できるようにすることが重要です。

画像の `width` と `height` 属性を HTML の `<img>` 要素に明記すると、画像が読み込まれる前にブラウザーがその画像のアスペクト比を計算することができます。このアスペクト比は、画像を表示するために必要な空間を確保するために使用され、画像がダウンロードされ画面に描画される際のレイアウトのずれを縮小したり、防止したりすることができます。レイアウトのずれを縮小することは、使い勝手や ウェブパフォーマンスを向上させるための重要な要素です。

ブラウザーは、HTML が解釈されるとコンテンツのレンダリングを開始しますが、多くの場合、画像を含むすべての資産がダウンロードされる前にレンダリングを開始します。サイズを記載することで、ブラウザーは、ページを最初にレンダリングする際に画像が読み込まれる際に、各画像を配置するための正しいサイズのプレースホルダーボックスを確保することができます。

![2 つのスクリーンショットで、最初のものは画像はなく空間が確保されており、2 つ目は確保された空間に画像が読み込まれた状態です。](/ja/docs/Learn/Performance/Multimedia/ar-guide.jpg)

`width` と `height` 属性がないと、プレースホルダーの空間が作成されないため、ページがレンダリングされた後に画像が読み込まれると、ジャンクつまりレイアウトのずれが目立つようになります。ページの再フローや再描画は、パフォーマンスやユーザビリティの課題です。

レスポンシブデザインにおいて、コンテナーが画像より狭い場合、画像がコンテナーからはみ出さないようにするために、以下の CSS を使用するのが一般的です。

```css
img {
  max-width: 100%;
  height: auto;
}
```

レスポンシブレイアウトには便利ですが、幅と高さの情報が記載されていない場合、ジャンクの原因となります。`<img>` 要素が解釈されたときに高さの情報がない場合、画像を読み込む前に、この CSS は高さを 0 に設定します。ページが画面の内側へ最初に描画された後に画像が読み込まれると、新たに決めた高さを確保するために、ページは再フローや再描画を行い、レイアウトが変化します。

ブラウザーには、実際の画像が読み込まれる前に、画像のサイズを調整する仕組みがあります。 `<img>`、`<video>`、`<input type="button">` 要素に `width` と `height` 属性が設定されている場合、その縦横比は読み込む前に計算され、提供された寸法をブラウザーが利用できるようになります。

アスペクト比は次に高さの計算に用いられ、正しいサイズが `<img>` 要素に適用されます。つまり、画像が読み込まれる際に前述のジャンクは発生しないか、指定されている寸法が完全に正確でない場合でも、最小限に抑えられます。

アスペクト比は、画像の読み込み時にのみ空間を確保するために使用します。画像が読み込まれると、属性によるアスペクト比ではなく、読み込まれた画像の固有のアスペクト比が使用されます。これにより、属性の寸法が正確でない場合でも、確実に正しいアスペクト比で表示されます。

過去 10 年来、開発者は `width` と `height` 属性を HTML の `<img>` の画像では省略することが最善の手法として推奨されてきましたが、アスペクト比の割り当てのため、これら 2 つの属性を指定することが開発者の最善の手法と考えられています。

背景画像については、 `background-color` 値を設定することが重要で、そうすれば画像がダウンロードされる前に、その上に重なるコンテンツが読めるようになります。

まとめ
---

この章では、画像の最適化について見ていきました。これで、平均的なウェブサイトの平均帯域幅の合計の半分を最適化する方法について、全般的に理解したことになります。これは、ユーザーの帯域幅を消費し、ページ読み込みを遅くするメディアの種類の 1 つに過ぎません。次に、帯域幅消費の 20% を占める動画の最適化について見ていきましょう。

* 前のページ
* Overview: Performance
* 次のページ


HTML のパフォーマンス機能 - ウェブ開発を学ぶ

HTML のパフォーマンス機能
===============

* 前のページ
* Overview: Performance
* 次のページ

HTML は既定で高速でアクセシビリティに優れています。開発者としての私たちの仕事は、HTML コードを作成・編集する際に、この 2 つのプロパティを確実に保持することです。例えば、`<video>` の埋め込みファイルのサイズが大きすぎる場合や、ウェブページがモバイル端末に最適化されていない場合など、複雑な問題が発生することがあります。このモジュールでは、ウェブページの品質を劇的に向上させることができる、主要な HTML パフォーマンス機能を説明します。

|  |  |
| --- | --- |
| 前提条件: |
 基本的なコンピューターリテラシー、
 基本的なソフトウェアのインストール、
 クライアント側のウェブ技術の基本的な知識
  |
| 目標: | HTML 要素や属性がウェブのパフォーマンス最適化に与える影響について学ぶ。 |

パフォーマンスに影響を与える要素と属性
-------------------

* `<picture>` 要素
* `<video>` 要素
* `<source>` 要素
* `<img> srcset` 属性
    + レスポンシブ画像
* `rel="preload"` によるコンテンツの先読み
* (https://w3c.github.io/preload/)
* `async` / `defer` 属性
* `<iframe>`
* `<object>`
* `<script>`
* `rel` 属性
まとめ
---

* 前のページ
* Overview: Performance
* 次のページ
関連情報
----

* `<picture>` 要素
* `<video>` 要素
* `<source>` 要素
* `<img> srcset` 属性
    + レスポンシブ画像
* `rel="preload"` によるコンテンツの先読み
* (https://w3c.github.io/preload/)


JavaScript によるフォームの送信 - ウェブ開発を学ぶ

JavaScript によるフォームの送信
=====================

HTML フォームは HTTP リクエストを宣言的に送信できます。しかし、フォームは 、例えば `XMLHttpRequest` のように JavaScript 経由で送信する HTTP リクエストを準備することもできます。この記事ではその方法を探ります。

フォームは必ずしもフォームであるとは限らない
----------------------

プログレッシブウェブアプリや、シングルページアプリ、フレームワークベースのアプリが現れたことで、HTML フォームを、レスポンスデータを受け取ったときに、新しい文書を読み込むことなくデータ送信するのに使用することが次第に一般的になってきました。最初になぜいろいろなアプローチが必要となるのかを話しましょう。

### グローバルインターフェイスの制御を取得

次の記事で述べる標準の HTML フォーム送信では、データが送信された URL がロードされます。つまり、ブラウザーウィンドウは全ページロードで移動します。ページ全体の読み込みを回避すると、ちらつきのような視覚上の問題や、ネットワークの遅延を避けて、よりスムーズな操作を提供できます。

最近の多くの UI は、HTML フォームを使用してユーザーからの入力を収集します。ユーザーがデータを送信しようとすると、アプリケーションはバックグラウンドでデータを非同期的に制御して送信し、変更が必要な UI の部分のみを更新します。

任意のデータを非同期に送信することは、**"Asynchronous JavaScript And XML"** を表す頭字語である AJAX として知られています。

### その違いは?

`XMLHttpRequest` (XHR) DOM オブジェクトで HTTP リクエストを作成して送信し、結果を取得することができます。歴史的には、`XMLHttpRequest` は交換フォーマットとして XML を取得して送信するように設計されていました。しかし、JSON は XML に取って代わっています。しかし、XML も JSON もフォームデータリクエストのエンコーディングには適合しません。フォームデータ (`application/x-www-form-urlencoded`) は、キーと値のペアの URL エンコードされたリストで構成されています。バイナリーデータを送信するために、HTTP リクエストは `multipart/form-data` に再形成されます\*\*。\*\*

**メモ:** Fetch API は最近 XHR の代わりによく使われます — これは XHR のモダンで更新されたバージョンであり、同様に動作しますが利点もあります。この記事で見る大半の XHR コードは Fetch で置き換えられます。

フロントエンド (ブラウザーで実行されるコード) とバックエンド (サーバーで実行されるコード) を制御すれば、JSON/XML を送信して必要に応じて処理することができます。

しかし、サードパーティのサービスを利用したい場合、サービスが要求する書式でデータ送信する必要があります。

ではどのようにしてそのようなデータを送信するのでしょうか?以下に必要となるさまざまなテクニックがあります。

フォームデータの送信
----------

フォームデータを送信するには 3 つの方法があります。

* 手動で `XMLHttpRequest` を構築する。
* スタンドアロンの `FormData` オブジェクトを使用する。
* `FormData` を `<form>` 要素に結び付けて使用する。

詳しく見てみましょう。

### 手動での XMLHttpRequest の作成

`XMLHttpRequest` は、HTTP リクエストを作成する最も安全で信頼性の高い方法です。 `XMLHttpRequest` を使用してフォームデータを送信するには、URL エンコードしたデータを準備し、フォームデータリクエストの詳細に従ってください。

例を見てみましょう。

```html
<button>Click Me!</button>
```

JavaScript はこうです。

```js
const btn = document.querySelector("button");

function sendData(data) {
  console.log("Sending data");

  const XHR = new XMLHttpRequest();

  const urlEncodedDataPairs = [];

  // data オブジェクトを、URL エンコードしたキーと値のペアの配列に変換します
  for (const [name, value] of Object.entries(data)) {
    urlEncodedDataPairs.push(
      `${encodeURIComponent(name)}=${encodeURIComponent(value)}`,
    );
  }

  // キーと値のペアをひとつの文字列に連結して、ウェブブラウザーのフォーム送信方式に
  // 合うよう、エンコードされた空白をプラス記号に置き換えます。
  const urlEncodedData = urlEncodedDataPairs.join("&").replace(/%20/g, "+");

  // データが正常に送信された場合に行うことを定義します
  XHR.addEventListener("load", (event) => {
    alert("Yeah! Data sent and response loaded.");
  });

  // エラーが発生した場合に行うことを定義します
  XHR.addEventListener("error", (event) => {
    alert("Oops! Something went wrong.");
  });

  // リクエストをセットアップします
  XHR.open("POST", "https://example.com/cors.php");

  // フォームデータの POST リクエストを扱うために必要な HTTP ヘッダを追加します
  XHR.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

  // 最後に、データを送信します
  XHR.send(urlEncodedData);
}

btn.addEventListener("click", () => {
  sendData({ test: "ok" });
});
```

そして、結果は以下のとおりです。

**メモ:** この `XMLHttpRequest` の使用は、第三者のウェブサイトにデータを送信したい場合にも、同一オリジンポリシーの対象となります。オリジン間リクエストの場合は、 CORS と HTTP のアクセス制御が必要です。

### XMLHttpRequest と FormData オブジェクトの使用

HTTP リクエストを手作業で作成するのは大変なことです。幸いなことに、最近の XMLHttpRequest 仕様書では `FormData` オブジェクトを使ってフォームデータリクエストを処理する便利で簡単な方法が提供されています。

`FormData` オブジェクトは、送信用のフォームデータを作成したり、送信方法を管理するフォーム要素内のデータを取得するために使用できます。

このオブジェクトの使い方は FormData オブジェクトの使用で詳述されていますが、2 つの例があります。

#### 独立した FormData オブジェクトを使用する

```html
<button>Click Me!</button>
```

HTML のサンプルはおわかりでしょう。JavaScript はこうです。

```js
const btn = document.querySelector("button");

function sendData(data) {
  const XHR = new XMLHttpRequest();
  const FD = new FormData();

  // データを FormData オブジェクトに投入します
  for (const [name, value] of Object.entries(data)) {
    FD.append(name, value);
  }

  // データが正常に送信された場合に行うことを定義します
  XHR.addEventListener("load", (event) => {
    alert("Yeah! Data sent and response loaded.");
  });

  // エラーが発生した場合に行うことを定義します
  XHR.addEventListener("error", (event) => {
    alert("Oops! Something went wrong.");
  });

  // リクエストをセットアップします
  XHR.open("POST", "https://example.com/cors.php");

  // FormData オブジェクトを送信するだけです。HTTP ヘッダは自動的に設定されます
  XHR.send(FD);
}

btn.addEventListener("click", () => {
  sendData({ test: "ok" });
});
```

そして、結果は以下のとおりです。

#### form 要素に紐づけた FormData の使用

`FormData` オブジェクトを `<form>` 要素に紐づけることもできます。これにより、フォームに含まれるデータを表す `FormData` をすばやく得ることができます。

HTML の部分はかなり典型的です。

```html
<form id="myForm">
  <label for="myName">Send me your name:</label>
  <input id="myName" name="name" value="John" />
  <input type="submit" value="Send Me!" />
</form>
```

しかし、JavaScript がフォームを乗っ取ります。

```js
window.addEventListener("load", () => {
  function sendData() {
    const XHR = new XMLHttpRequest();

    // FormData オブジェクトと form 要素を紐づけます
    const FD = new FormData(form);

    // データが正常に送信された場合に行うことを定義します
    XHR.addEventListener("load", (event) => {
      alert(event.target.responseText);
    });

    // エラーが発生した場合に行うことを定義します
    XHR.addEventListener("error", (event) => {
      alert("Oops! Something went wrong.");
    });

    // リクエストをセットアップします
    XHR.open("POST", "https://example.com/cors.php");

    // 送信したデータは、ユーザーがフォームで提供したものです
    XHR.send(FD);
  }

  // form 要素を取得
  const form = document.getElementById("myForm");

  // 'submit' イベントのハンドラーを追加
  form.addEventListener("submit", (event) => {
    event.preventDefault();

    sendData();
  });
});
```

そして、結果は以下のとおりです:

フォームの `elements` プロパティを使用してフォーム内のすべてのデータ要素のリストを取得し、それらを一度に 1 つずつ手動で管理することで、このプロセスにさらに関わることができます。詳細については、フォームコントロールへのアクセスの例を参照してください。

バイナリーデータを扱う
-----------

`<input type="file">` ウィジェットを含むフォームで `FormData` オブジェクトを使用すると、データは自動的に処理されます。しかし、バイナリーデータを手動で送るには、追加でやるべきことがあります。

バイナリーデータのソースが多数あります。たとえば、`FileReader`、`Canvas`、WebRTC などです。残念ながら、一部の従来のブラウザーではバイナリーデータにアクセスできないか、または複雑な回避策が必要です。 `FileReader` API について詳しく知りたい場合は、ウェブアプリケーションからのファイルの使用を読んでください。

`FormData` をサポートするバイナリーデータを送信するのは簡単です。`append()` メソッドを使用すれば完了です。手動でやらなければならないならば、それはトリッキーです。

以下の例ではバイナリーデータへのアクセスに `FileReader` API を使用しており、また手作業でマルチパートのフォームデータを作成しています:

```html
<form id="theForm">
  <p>
    <label for="theText">text data:</label>
    <input id="theText" name="myText" value="Some text data" type="text" />
  </p>
  <p>
    <label for="theFile">file data:</label>
    <input id="theFile" name="myFile" type="file" />
  </p>
  <button>Send Me!</button>
</form>
```

ご覧のとおり、 HTML は標準の `<form>` です。不思議なところは何もありません。「魔法」は JavaScript にあります。

```js
// DOM ノードにアクセスしたいため、
// ページをロードしたときにスクリプトを初期化します。
window.addEventListener("load", () => {
  // この変数は、フォームデータを格納するために使用します。
  const text = document.getElementById("theText");
  const file = {
    dom: document.getElementById("theFile"),
    binary: null,
  };

  // ファイルコンテンツへのアクセスに FileReader API を使用します。
  const reader = new FileReader();

  // FileReader API は非同期であるため、ファイルの読み取りが完了したときに
  // その結果を保存しなければなりません。
  reader.addEventListener("load", () => {
    file.binary = reader.result;
  });

  // ページを読み込んだとき、すでに選択されているファイルがあればそれを読み取ります。
  if (file.dom.files[0]) {
    reader.readAsBinaryString(file.dom.files[0]);
  }

  // 一方、ユーザーがファイルを選択したらそれを読み取ります。
  file.dom.addEventListener("change", () => {
    if (reader.readyState === FileReader.LOADING) {
      reader.abort();
    }

    reader.readAsBinaryString(file.dom.files[0]);
  });

  // sendData 関数がメインの関数です。
  function sendData() {
    // 始めに、ファイルが選択されている場合はファイルの読み取りを待たなければなりません。
    // そうでない場合は、関数の実行を遅延させます。
    if (!file.binary && file.dom.files.length > 0) {
      setTimeout(sendData, 10);
      return;
    }

    // マルチパートのフォームデータリクエストを構築するため、
    // XMLHttpRequest のインスタンスが必要です。
    const XHR = new XMLHttpRequest();

    // リクエストの各パートを定義するためのセパレータが必要です。
    const boundary = "blob";

    // 文字列としてリクエストの本体を格納します。
    let data = "";

    // そして、ユーザーがファイルを選択したときに
    if (file.dom.files[0]) {
      // リクエストの本体に新たなパートを作ります
      data += `--${boundary}\r\n`;

      // フォームデータを記述します
      data +=
        "content-disposition: form-data; " +
        // フォームデータの名前を定義します
        `name="${file.dom.name}"; ` +
        // 実際のファイル名を与えます
        `filename="${file.dom.files[0].name}"\r\n`;
      // ファイルの MIME タイプを与えます
      data += `Content-Type: ${file.dom.files[0].type}\r\n`;

      // メタデータとデータの間に空行を置きます
      data += "\r\n";

      // リクエストの本体にバイナリーデータを置きます
      data += file.binary + "\r\n";
    }

    // テキストデータの場合はシンプルです。
    // リクエストの本体に新たなパートを作ります
    data += `--${boundary}\r\n`;

    // フォームデータであることと、データの名前を示します。
    data += `content-disposition: form-data; name="${text.name}"\r\n`;
    // メタデータとデータの間に空行を置きます
    data += "\r\n";

    // リクエストの本体にテキストデータを置きます。
    data += text.value + "\r\n";

    // 完了したら、リクエストの本体を "閉じます"。
    data += `--${boundary}--`;

    // データが正常に送信された場合に行うことを定義します
    XHR.addEventListener("load", (event) => {
      alert("Yeah! Data sent and response loaded.");
    });

    // エラーが発生した場合に行うことを定義します
    XHR.addEventListener("error", (event) => {
      alert("Oops! Something went wrong.");
    });

    // リクエストをセットアップします
    XHR.open("POST", "https://example.com/cors.php");

    // マルチパートのフォームデータの POST リクエストを扱うために必要な HTTP ヘッダーを追加します。
    XHR.setRequestHeader(
      "Content-Type",
      `multipart/form-data; boundary=${boundary}`,
    );

    // データの送信
    XHR.send(data);
  }

  // フォーム要素を取得
  const form = document.getElementById("theForm");

  // 'submit' イベントのハンドラーを追加
  form.addEventListener("submit", (event) => {
    event.preventDefault();
    sendData();
  });
});
```

そして、結果は以下のとおりです。

まとめ
---

ブラウザーや扱うデータタイプによっては、JavaScript を介してフォームデータを送信するのが簡単な場合と難しい場合があります。`FormData` オブジェクトが一般的な答えであり、レガシーブラウザーでポリフィルを使用することをためらってはいけません。

関連情報
----

### 学習コース

* 初めてのフォーム
* フォームの構築方法
* 基本的なネイティブフォームコントロール
* HTML5 の入力型
* その他のフォームコントロール
* UI 擬似クラス
* フォームへのスタイル設定
* クライアントサイドのフォーム検証
* フォームデータの送信
### 上級トピック

* JavaScript によるフォームの送信
* カスタムフォームコントロールの作成方法
* 古いブラウザーでの HTML フォーム
* フォームへの高度なスタイル設定
* フォームコントロール向けの CSS プロパティの互換性一覧表


HTML5 の入力型 - ウェブ開発を学ぶ

HTML5 の入力型
==========

* 前のページ
* Overview: Forms
* 次のページ

前の記事では `<input>` 要素を見てきて、 HTML の初期から利用できる `type` 属性の値をカバーしてきました。ここでは最近のフォームコントロールの機能、特定のデータを集めるのに HTML5 で追加された、新しい入力型を詳しく見ていきましょう。

|  |  |
| --- | --- |
| 前提条件: |
 コンピューターリテラシーの基本と、
 HTML の理解。
  |
| 目的: | ネイティブフォームコントロールで利用できる新しい入力型の理解と、 HTML を用いた実装方法。 |

**メモ:** この記事のたいていの機能はブラウザー間で広くを対応されています。例外は注記しておきます。ブラウザーサポートについての詳細は、HTML フォーム要素のリファレンス、特に <input> 型リファレンスを見てください。

HTML フォームコントロールの見た目はデザイナーの仕様により全く異なるため、ウェブ開発者はときどき独自のフォームコントロールを作成します。これは上級のチュートリアル — カスタムフォームウィジェットの作成方法 — で扱います。

メールアドレスフィールド
------------

このフィールド型は `type`属性の `email` の値でセットされます:

```html
<input type="email" id="email" name="email" />
```

この `type` が使われたとき、ユーザーは有効なメールアドレスをフィールドに入力することが必須です。その他のコンテンツでは、ブラウザーによってフォーム送信時にエラーが表示されます。この動作は下記のスクリーンショットで見ることができます。

!["Please enter an email address." というメッセージを表示している無効なメール入力欄](/ja/docs/Learn/Forms/HTML5_input_types/email_address_invalid.png)

`email` 入力型と `multiple` 属性を組み合わせて、複数のメールアドレスが同じ入力に（カンマ区切りで）入力させることもできます。

```html
<input type="email" id="email" name="email" multiple />
```

いくつかの端末 — 特にスマートフォンのような動的キーボードつきのタッチ端末 — では、 `@` キーを含むメールアドレス入力に適した別の仮想キーパッドが現れることもあります。Android 版 Firefox のキーボードの例として下記のスクリーンショットを見てください:

![既定でアット記号が付いている、 Android 版 Firefox のメールアドレス入力キーボード](/ja/docs/Learn/Forms/HTML5_input_types/fx-android-email-type-keyboard.jpg)

**メモ:** 基本的なテキスト入力型の例は basic input examples にあります（ソースコード も見てください）。

これは新しい入力型を使う良い理由であり、こうした端末のユーザーの使い勝手を向上させます。

### クライアント側の検証

上で見てきたように、他の新しい `input` 型と同様に、`email` は組み込みの*クライアント側の*エラー検証 — データがサーバーに送られる前にブラウザーで実行されるもの — があります。これはユーザーが正確に入力するのに役立ち、時間を短縮できます — データが正しくないことをサーバーとのラウンドトリップを待つことなくすぐに知ることは便利です。

しかしこれは完全なセキュリティ対策と*考えるべきではありません*! アプリは送信データのセキュリティ確認をクライアント側と同様に*サーバー側*でも行うべきで、なぜならクライアント側の検証は簡単にオフにできるため悪意のあるユーザーは簡単にサーバーに不正なデータを送信できるためです。起こりうることについてはウェブサイトセキュリティを読んで下さい。サーバー側の検証を実装するのはこのモジュールの範囲を超えていますが、記憶しておくべきです。

既定の制約では `a@b` は有効なメールアドレスです。これは既定では `email` 入力型はイントラネットのメールアドレスを許可しているためです。異なる検証動作を実装するには、`pattern` 属性を用いたり、エラーメッセージをカスタムできます。この機能の使い方は後の クライアントサイド検証の記事で話します。

**メモ:** 入力データがメールアドレスでない場合、`:invalid` 擬似クラスがマッチして、`validityState.typeMismatch` プロパティは `true` を返します。

検索フィールド
-------

検索フィールドは、ページやアプリの検索ボックス作成に使われるものです。このフィールド型は `search` の値を `type` 属性のに使用することで設定されます。

```html
<input type="search" id="search" name="search" />
```

`text` フィールドと `search` フィールドの主な違いは、ブラウザーの見た目のスタイル設定方法です。よく、`search` フィールドは角丸で描画されます。また時折、値がクリックされたときに値をクリアする "Ⓧ" も表示されます。その他、動的キーボードのある端末では、キーボードの Enter キーが "**検索**"、あるいは虫眼鏡アイコンで表示されることもあります。

下記のスクリーンショットでは macOS での Firefox 71, Safari 13, Chrome 79 と Windoes10 での Edge 18 と Chrome 79 での文字が入った検索フィールドを表示しています。注意として、クリアのアイコンはフィールドに値が入った場合のみ表示され、Safari を除いてフィールドにフォーカスが当たった場合のみ表示されます。

![様々なプラットフォームの検索フィールドのスクリーンショット](/ja/docs/Learn/Forms/HTML5_input_types/search_focus.png)

もう 1 つの注目すべき機能として、`search` フィールドの値は同一サイトの複数ページにまたがって、自動保存してオートコンプリートすることができます。これはたいていのモダンブラウザーでは自動的に起こる傾向があります

電話番号フィールド
---------

電話番号を入力するための特殊なフィールドは、 `tel` の値を `type` 属性に使うと作成することができます。

```html
<input type="tel" id="tel" name="tel" />
```

動的キーボードつきのタッチ端末でアクセスしたとき、たいていの端末では `type="tel"` が出てくると数字のキーパッドを表示します。つまりこの型は、テンキーが役立つときはいつでも有用であり、電話番号だけに使用する必要はありません。

下記は Android 用 Firefox キーボードの例です。

![Android 用 Firefox の電話番号キーボードの例で、既定でアスタリスクが表示されています。](/ja/docs/Learn/Forms/HTML5_input_types/fx-android-tel-type-keyboard.jpg)

世界中にはいろいろな電話番号の書式があるため、このフィールドはユーザーが入力した値に制約を一切つけません（つまり、文字が入っていることもありえます）。

前に触れた通り、 `pattern` 属性が制約を強化するのに使われます。これはクライアントサイド検証で学びます。

URL フィールド
---------

URL を入力するための特殊な型のフィールドは、 `url` の値を`type` 属性に使うと作成することができます。

```html
<input type="url" id="url" name="url" />
```

これはフィールドに特別な検証制約を追加します。ブラウザーは (`http:`のような) プロトコルがない場合や、URL の形式が良くない場合にエラーを報告します。動的キーボードのある端末ではよく、コロン、ピリオド、スラッシュの複数やすべてをデフォルトキーとして表示します。

例は下記のものを見てください（Android 用 Firefox の例）。

![Android 用 Firefox の URL キーボードの例で、既定でスラッシュが表示されています。](/ja/docs/Learn/Forms/HTML5_input_types/fx-android-url-type-keyboard.jpg)

**メモ:** URL が正しい形式であっても、それが必ずしも実際存在する場所を参照しているとは限りません。

数値フィールド
-------

数値入力用のコントロールは、 `<input>` `type` に `number` を指定して作成することができます。このコントロールはテキストフィールドのような見た目ですが、浮動小数値のみを許可し、通常は数値を増減するためのスピナー形式のボタンがあります。動的キーボードつきの端末では、一般的に数値キーボードが表示されます。

下記のスクリーンショット (Android 用 Firefox より) に例があります。

![Firefox for Android email keyboard, with ampersand displayed by default.](/ja/docs/Learn/Forms/HTML5_input_types/fx-android-number-type-keyboard.jpg)

`number` の入力型では、`min` と `max` 属性をセットすることで最小値と最大値の制約をつけることができます。

スピナーボタンを押すことで増減させる増分を接とするのに `step` 属性を使うこともできます。既定では、 number 入力型は数値が整数値の場合のみ検証します。浮動小数を許可するには、 `step="any"` を指定します。省略された場合、`step` 値は既定で `1` となり、つまりすべての数値が有効です。

いくつか例を見てみましょう。次の最初の例では値が `1` と `10` の間に制限され、増減ボタンで値が `2` ずつ変更される数値コントロールを作成しています。

```html
<input type="number" name="age" id="age" min="1" max="10" step="2" />
```

2 つ目の例では値が `0` と `1` の間に制限され、増減ボタンで値が `0.01` ずつ変更される数値コントロールを作成しています。

```html
<input type="number" name="change" id="pennies" min="0" max="1" step="0.01" />
```

`number` 入力型は有効な値の範囲に制限されているときに意味を持ちます。例えば、ある人の年齢や身長です。範囲が大きすぎて増分が意味をなさない場合 (例えば USA の郵便番号は、`00001` から `99999` の範囲です)、`tel` 型がより良い選択となることもあります。これは数値のスピナー UI 機能に対して、数値キーパッドを提供します。

スライダーコントロール
-----------

数字を選ぶもう１つの方法は**スライダー**です。家造りのようなサイトで資産の価格をフィルターするのによく見ることでしょう。これを示す例をライブで見てみましょう。

使用からすると、スライダーはテキストフィールドより不正確です。このため、*正確な*値が必ずしも重要でない数値の選択に使われます。

スライダーは `<input>` に `type` 属性を `range` にセットして作成します。スライダーはマウスやタッチや、キーパッドの矢印で移動できます。

スライダーを適切に設定するのは重要です。そのためには、それぞれ最小、最大、増分値を設定する `min`, `max`, `step` 属性を設定するのを強くお奨めします。

上の例の背後にあるコードを見て、どのように実現されるかを見てみましょう。まずは基本となる HTML です。

```html
<label for="price">Choose a maximum house price: </label>
<input
 type="range"
 name="price"
 id="price"
 min="50000"
 max="500000"
 step="100"
 value="250000" />
<output class="price-output" for="price"></output>
```

この例では、値が `50000` と `500000` までの範囲で、100 ずつ増減するスライダーを作成しています。既定の値は `value` 属性を使って `250000` としています。

スライダーについての問題は、現在の値がいくつなのかのフィードバックが一切ないことです。これは、現在の値を入れている `<output>` 要素を導入する理由です (この要素は次の記事でも見ていきます)。入力値や、あらゆる要素内の計算結果を表示できますが、`<output>` は特別です — `<label>`のように — `for` 属性を取って要素や出力値の元となる要素と関連付けることができます。

実際に現在の値を表示して、変更時に更新するには、JavaScript を使う必要がありますが、比較的に簡単です。

```js
const price = document.querySelector("#price");
const output = document.querySelector(".price-output");

output.textContent = price.value;

price.addEventListener("input", () => {
  output.textContent = price.value;
});
```

ここでは `range` 入力と `output` を 2 つの変数に保存しています。次に `output` の `textContent` を入力の `value` ですぐにセットします。最後に、イベントリスナーをセットして、range スライダーが移動するといつも、`output` の `textContent` を新しい値に更新します。

**メモ:** CSS Tricks に、このテーマに応じた素晴らしいチュートリアルがあります。 The Output Element です。

日付と時刻ピッカー
---------

日付と時刻の値を収集することは、ウェブ開発者にとってずっと悪夢でした。良い使い勝手を実現するには、カレンダーを選択する UI を提供することが重要です。これにより、ユーザーはネイティブのカレンダーアプリケーションに切り替えることなく日付を選択でき、解釈しにくいさまざまな形式で日付を入力できる可能性があります。前千世紀の最後の 1 分は、例えば 1999/12/31 23:59 や 12/31/99T11:59PM のように、様々な方法で入力される可能性があります。

HTML の日付コントロールは、カレンダーウィジェットを提供して統一されたデータを作成し、この種類のデータを扱うことができます。

日付と時刻コントロールは `<input>` 要素と、日付か時間かその両方かを集めたいのかにあわせて適当な `type` 属性を使って作成できます。対応していないブラウザーにおいて、 `<select>` 要素で代替する場合の実行例は次の通りです。

利用できるいろいろな型を簡単に見ていきましょう。注意としては、この型の使用法はとても複雑で、特にブラウザーの対応考えたに場合そうです（下記を見てください）。完全な詳細情報は、それぞれの型のリファレンスページと、そこにある詳細な例を見てください。

### `datetime-local`

`<input type="datetime-local">` は特定のタイムゾーン情報のない日付と時刻を表示して選択するウィジェットを作成します。

```html
<input type="datetime-local" name="datetime" id="datetime" />
```

### `month`

`<input type="month">` は年と月を表示して選択するウィジェットを作成します。

```html
<input type="month" name="month" id="month" />
```

### `time`

`<input type="time">` は時刻の値を表示して選択するウィジェットを作成します。時刻は 12 時間のフォーマットで表示されますが、*返値*は 24 時間フォーマットです。

```html
<input type="time" name="time" id="time" />
```

### `week`

`<input type="week">` は本年の週の番号を表示して選択するウィジェットを作成します。

週は月曜始まりで日曜日で終わります。それに加えて、その年の最初の週はその年の最初の木曜日を含みます—これはその年の最初の日を含まないことも、前年の最後の数日を含むこともあります。

```html
<input type="week" name="week" id="week" />
```

### date/time 値の制限

日付をと時刻のコントロールはすべて、`min` と `max` 属性で制約をつけることができて、さらに `step` 属性 (この値は入力型によって変わります)で追加の制約も可能です。

```html
<label for="myDate">When are you available this summer?</label>
<input
 type="date"
 name="myDate"
 min="2013-06-01"
 max="2013-08-31"
 step="7"
 id="myDate" />
```

色選択コントロール
---------

色も扱いが難しいです。色の表現がたくさんあります。 RGB 値（10 進数や 16 進数）、HSL 値、キーワードなどです。

`color` コントロールは `<input>` 要素を、 `type` 属性に `color`をつけて作成できます。

```html
<input type="color" name="color" id="color" />
```

対応しているいる場合、色コントロールは OS の既定の色選択機能を呼び出して選択できるようにする傾向があります。下記のスクリーンショットは macOS の Firefox の例です。

![macOS 版 Firefox の色選択のスクリーンショットです。](/ja/docs/Learn/Forms/HTML5_input_types/fx-macos-color.jpg)

次のライブサンプルも試してみてください。

返値は常に小文字で 6 桁の 16 進数の色です。

スキルテスト
------

この記事の最後に到着しましたが、最も大事な情報を覚えていますか？次に進む前に、この情報を保持しているか検証するテストがあります — Test your skills: HTML5 controls (en-US) を見てください。

まとめ
---

ここで HTML5 フォーム入力型の旅が終了です。動作が特殊なため簡単に分類できないその他のコントロール型も少しあって、それを知るのも大事です。次の記事で扱います。

* 前のページ
* Overview: Forms
* 次のページ


その他のフォームコントロール - ウェブ開発を学ぶ

その他のフォームコントロール
==============

* 前のページ
* Overview: Forms
* 次のページ

ここでは、 `<input>` 以外のフォーム要素の機能を、ドロップダウンリストや複数行のテキストフィールドなどの他の操作型から、 `<output>` 要素（前回の記事で実際に使用しました）やプログレスバーなどの他の便利なフォーム機能まで、詳しく見ていきましょう。

|  |  |
| --- | --- |
| 前提条件: |
 基本的なコンピューターリテラシーと、基本的な
 HTML の理解。
  |
| 目的: | `<input>` 以外のフォーム機能と、それを HTML を使用して実装する方法を理解する。 |

複数行のテキストフィールド
-------------

複数行のテキストフィールドは、 `<textarea>` 要素を `<input>` 要素の代わりに指定します。

```html
<textarea cols="30" rows="8"></textarea>
```

これは次のように表示されます。

`<textarea>` と通常の単一行のテキストフィールドとの主な違いは、ユーザーが送信データの中に改行を (リターンを押すことで) 入れることができることです。

`<textarea>` は閉じタグを取ることができ、既定のテキストを開始タグと終了タグの間に置いてください。これに対し、 `<input>` は閉じタグのない空要素です。 `value` 属性の中に既定の値が入ります。

注意として、`<textarea>` 要素（その他の HTML 要素、CSS、JavaScript を含む）には何でも入れられるものの、この性質により、プレーンテキストコンテンツのように描画されます（フォームコントロール以外で `contenteditable` を使うと、プレーンテキストの代わりに HTML/「リッチ」コンテンツの API を使用できます）。

視覚的には、入力されたテキストは折り返され、フォームコントロールは既定でサイズ変更可能です。最近のブラウザーではドラッグハンドルを提供しており、これをドラッグすることでテキストエリアのサイズを大きくしたり小さくしたりすることができます。

下記のスクリーンショットは macOS での Firefox 71 と Safari 13 、Windows10 での Edge 18, Yandex 14, Firefox 71, Chrome 79 における、それぞれ既定、フォーカス中、無効状態の `<textarea>` 要素を示しています。

![Mac OSX の Firefox 71 と Safari 13、 Windows 10 の Edge 18、Yandex 14、Firefox、Chrome で、既定、フォーカス中、無効状態の 'textarea' 要素を示しています。](/ja/docs/Learn/Forms/Other_form_controls/textarea_basic.png)

**メモ:** 多少面白いテキストエリアの使用例は、このシリーズの最初の記事の例 が見つかります (ソースコードも見てください)。

### 複数行レンダリングの制御

`<textarea>` では、複数行にまたがってレンダリングするのを制御する 3 つの属性を受け付けます:

`cols`

このテキストコントロールの幅（桁数）を、平均的な文字幅で指定します。これは `<textarea>` をリサイズすることで変更でき、また CSS で上書きもできるため、有効な開始時の幅です。何も指定されていない場合、既定値は 20 です。

`rows`

このコントロールの行数を指定します。これは `<textarea>`をリサイズすることで変更でき、また CSS で上書きもできるため、有効な開始時の高さです。何も指定されていない場合、既定値は 2 です。

`wrap`

コントロールがどのようにテキストを折り返すかを指定します。値は `soft` （既定値）、この値では送信されるテキストは改行されないが、ブラウザーで表示されるテキストは折り返される、 `hard` （この値を使うには `cols` 属性を指定する必要がある）、この値では送信テキストとレンダリングされるテキストの両方が折り返される、`off`、この値では折り返しを行わない、を取ります。

### テキストエリアのリサイズの制御

`<textarea>` をリサイズできるかは CSS の `resize` プロパティで制御されます。とりうる値は次の通りです。

* `both`: 既定値 — 水平、垂直ともリサイズ許可
* `horizontal`: 水平のみリサイズ許可
* `vertical`: 垂直のみリサイズ許可
* `none`: リサイズ許可しない
* `block` と `inline`: `block` や `inline` 方向のみにリサイズできる実験的な値（これはテキストの方向性によって変わります。詳しくは Handling different text directions を見てください）。

これがどのように動作するのかのデモは、`resize` リファレンスページの最初にあるインタラクティブな例で遊んでみてください。

ドロップダウンコントロール
-------------

ドロップダウンコントロールは、ユーザーインターフェイスのスペースをあまり取らずに、ユーザーがさまざまなオプションから選択できるようにするためのシンプルな方法です。HTML には、**選択ボックス**と**自動補完ボックス**という 2 つの形式のドロップダウンコンテンツがあります。どちらの場合も相互作用は同じです。コントロールを有効にすると、ブラウザーにはユーザーが選択できる値のリストが表示されます。

**メモ:** すべてのドロップダウンボックスの例は、GitHub の drop-down-content.htmlにあります (ライブでもご覧ください)。

### 選択ボックス

単純な選択ボックスは、1 つ以上の `<option>` 要素を子要素として持つ `<select>` 要素で作成され、それぞれが可能な値のうちの 1 つを指定します。

#### 基本的な例

```html
<select id="simple" name="simple">
  <option>バナナ</option>
  <option selected>さくらんぼ</option>
  <option>レモン</option>
</select>
```

 必要に応じて、希望する `<option>` 要素の `selected` 属性を用いて、選択ボックスの既定値を設定することができます。
 このオプションは、ページが読み込まれたときにあらかじめ選択されています。

#### optgroup の使用

`<option>` 要素は、 `<optgroup>` 要素の中に入れ子にすることができ、視覚的に関連する値のグループを作成することができます。

```html
<select id="groups" name="groups">
  <optgroup label="果物">
    <option>バナナ</option>
    <option selected>さくらんぼ</option>
    <option>レモン</option>
  </optgroup>
  <optgroup label="野菜">
    <option>人参</option>
    <option>茄子</option>
    <option>馬鈴薯</option>
  </optgroup>
</select>
```

`<optgroup>` 要素では、 `label` 属性の値が入れ子になったオプションの値の前に表示されます。ブラウザーは通常、それらをオプションから視覚的に離して（すなわち太字にしたり、入れ子レベルを変えたりして）表示しますので、実際のオプションと混同される可能性は低くなります。

#### value 属性の使用

`<option>` 要素に明示的な value 属性が設定されている場合、そのオプションが選択された状態でフォームが送信された時にその値が送信されます。上の例のように value 属性を省略した場合は、 `<option>` 要素の内容が値として使われます。そのため、 value 属性は必要ありませんが、選択ボックスに視覚的に表示されている値とは異なる値を短くしたり、サーバーに送信したい理由があるかもしれません。

例えば、

```html
<select id="simple" name="simple">
  <option value="banana">大きく美しい黄色いバナナ</option>
  <option value="cherry">ふくよかでジューシーなさくらんぼ</option>
  <option value="lemon">鋭くて力強いレモン</option>
</select>
```

既定では、選択ボックスの高さは、単一の値を表示するのに十分です。オプションの `size` 属性は、選択ボックスにフォーカスがない場合に表示されるオプションの数を制御します。

### 複数選択の選択ボックス

既定では、選択ボックスは、ユーザーに単一の値を選択させるだけです。 `<select>` 要素に `multiple` 属性を追加することで、オペレーティングシステムが提供するデフォルトのメカニズム（例えば、 `Cmd`/`Ctrl` を押しながらデスクトップ上で複数の値をクリックするなど）を使用して、ユーザーが複数の値を選択できるようにすることができます。

```html
<select id="multi" name="multi" multiple size="2">
  <optgroup label="野菜">
    <option>バナナ</option>
    <option selected>さくらんぼ</option>
    <option>レモン</option>
  </optgroup>
  <optgroup label="野菜">
    <option>人参</option>
    <option>茄子</option>
    <option>馬鈴薯</option>
  </optgroup>
</select>
```

**メモ:** 複数選択可能な選択ボックスの場合、選択ボックスはドロップダウンコンテンツとして値を表示しないことに気づくでしょう - 代わりに、すべての値がリストに一度に表示され、オプションの `size`属性はウィジェットの高さを決定します。

**メモ:** `<select>` 要素に対応しているすべてのブラウザーは、 `multiple`/select#multiple)/select#multiple) 属性にも対応しています。

### 自動補完のボックス

表示する値を指定する `<option>` 子要素つきの `<datalist>` 要素を使って、フォームウィジェット用の自動補完の提案値を提供できます。 `<datalist>` には `id`が必要です。

データリストは、 `<input>` 要素（つまり`text` や `email` の入力型）の `list` 属性の値をデータリストの `id` の値を指定することで結びつけます。

データリストがフォームウィジェットに関連づけられると、オプションはユーザーが入力する自動補完テキストに使われます。典型的には、これはユーザーが入力に打ち込んだものに一致するドロップダウンボックスで表示されます。

#### 基本的な例

例を見てみましょう。

```html
<label for="myFruit">好きな果物は何ですか？</label>
<input type="text" name="myFruit" id="myFruit" list="mySuggestion" />
<datalist id="mySuggestion">
  <option>リンゴ</option>
  <option>バナナ</option>
  <option>ブラックベリー</option>
  <option>ブルーベリー</option>
  <option>レモン</option>
  <option>ライチ</option>
  <option>桃</option>
  <option>梨</option>
</datalist>
```

#### datalist の対応状況と代替手段

ほぼすべてのブラウザーが datalist に対応していますが、IEバージョン10以下のような古いブラウザーにも対応をする場合は、代替手段を提供するという仕掛けがあります。

```html
<label for="myFruit">好きな果物は何ですか？（代替手段付き）</label>
<input type="text" id="myFruit" name="fruit" list="fruitList" />

<datalist id="fruitList">
  <label for="suggestion">または果物を選択</label>
  <select id="suggestion" name="altFruit">
    <option>リンゴ</option>
    <option>バナナ</option>
    <option>ブラックベリー</option>
    <option>ブルーベリー</option>
    <option>レモン</option>
    <option>ライチ</option>
    <option>桃</option>
    <option>梨</option>
  </select>
</datalist>
```

`<datalist>` 要素に対応したブラウザーは、 `<option>` 要素以外を無視し、 datalist はこれはうまく対応していくでしょう。 `<datalist>` 要素に対応していない古いブラウザーでは、ラベルと選択ボックスが表示されます。

以下の画面ショットは、Safari 6 でレンダリングされた datalist の代替手段を示しています。

![Mac OS の Safari で datalist 要素を代替させた画面](/ja/docs/Learn/Forms/Other_form_controls/datalist-safari.png)

この代替手段を使用する場合は、`<input>` と `<select>` の両方のデータがサーバーサイドで収集されていることを確認してください。

#### より目立たない datalist の使用方法

HTML 仕様書によると、 `list` 属性と `<datalist>` 要素はユーザーの入力を必要とするあらゆる種類のウィジェットに使用することができます。このため、少し目立たないと思われるような使用法もあります。

例えば、 `range` 入力型で ``<datalist>`` に対応しているブラウザーでは、 datalist の ``<option>`` 値の範囲ごとに小さなチェックマークが範囲の上に表示されます。 `<input type="range">` のリファレンスページでこの例を見ることができます。

また、 `<datalist>` と `<input type="color">` に対応しているブラウザーは、フルカラーパレットを利用できるようにしつつ、カスタマイズしたパレットを既定で表示することができます。

この場合、ブラウザーによって挙動が異なるため、このような使用はプログレッシブエンハンスメントとして考え、グレイスフルデグラデーションを保証するようにしましょう。

その他のフォーム機能
----------

このほかにも、これまで述べてきたような目立つものではありませんが、状況によっては有用なフォーム機能がいくつかありますので、簡単にご紹介しておきましょう。

**メモ:** この節の例は GitHub 上の other-examples.html にあります（ライブでも確認してください）。

### メーターとプログレスバー

メーターやプログレスバーは、数値を視覚的に表現するものです。

#### progress

プログレスバーは、 `max` 属性を用いて指定した最大値まで時間と共に変化する値を表します。このようなバーは、 `<progress>` 要素を使用して作成されます。

```html
<progress max="100" value="75">75/100</progress>
```

これは、ダウンロードされたファイルの総数の割合や、アンケートで記入された質問の数など、進捗状況の報告が必要なものを実装するためにあります。

`<progress>` 要素の内側の内容は、この要素に対応していないブラウザーや、スクリーンリーダーが発声するための代替となります。

#### meter

メーターバーは `max` と `min`t/meter#min) 値で区切られた範囲内の固定された値を表します。この値は視覚的にバーとして表示され、このバーがどのように見えるかを知るために、他のいくつかの設定された値と比較します。

* `low` と `high` の値は範囲を 3 つに分割します。
    + 範囲の下位の部分は `min` と `low` 値の間であり、端も含みます。
    + 範囲の中位の部分は `low` と `high` 値の間であり、端を含みません。
    + 範囲の上位の部分は `high` と `max` 値の間であり、端も含みます。
* `optimum` 値は `<meter>` 要素の最適な値を定義します。 `low` および `high` 値と組み合わせて、どの範囲の値を推奨するかを定義します。
    + `optimum` の値が範囲の下位の部分にある場合、範囲の下位の部分を推奨部分、中位の部分を平均部分、上位の部分を最悪の部分と見なします。
    + `optimum` の値が範囲の中位の部分にある場合、範囲の下位の部分を平均部分、中位の部分を推奨部分、上の部分を同じく平均部分と見なします。
    + `optimum` の値が範囲の上位の部分にある場合、範囲の下位の部分を最悪の部分、中位の部分を平均部分、上位の部分を推奨部分と見なします。

すべてのブラウザーは、 `<meter>` 要素を実装するために、メーターバーの色を変更するためにこれらの値を使用します。

* 現在の値が範囲の推奨部分にある場合は、バーが緑色になります。
* 現在の値が範囲の平均部分にある場合は、バーが黄色になります。
* 現在の値が範囲の最悪の部分にある場合、バーが赤くなります。

このようなバーは `<meter>` 要素を使用して作成されます。これは、例えば、ディスク上で使用されている総容量を示すバーで、それがいっぱいになりそうなときには赤色に変わるような、あらゆる種類のメーターを実装するためのものです。

```html
<meter min="0" max="100" value="75" low="33" high="66" optimum="50">75</meter>
```

`<meter>` 要素の中の内容は、その要素に対応していないブラウザーと支援技術が発声するための代替です。

HTMLElement("progress")}} と `<meter>` の対応はかなり良好です - Internet Explorer は対応していませんが、他のブラウザーは十分に対応しています。

スキルをテストしよう!
-----------

この記事の終わりまで到達しましたが、最も重要な情報を覚えていますか？次に移る前に、この情報を保持しているか検証するテストがあります — Test your skills: Other controls (en-US) を見てください。

まとめ
---

最も後のいくつかの記事で見てきたように、利用できるフォーム要素にはいろいろな種類がたくさんあります。一見してすべてを詳しく覚えておく必要はなく、詳細について調べたいだけ、記事に戻ることができます。

いろいろなフォームコントロールの背後にある HTML をざっと理解したので、それらのスタイル設定について見ていきましょう。

* 前のページ
* Overview: Forms
* 次のページ