HTML

提供:senooken JP Wiki
2024年11月19日 (火) 17:09時点におけるSenooken (トーク | 投稿記録)による版 (→‎Selector)

About

HTML (Hyper Text Markup Language) はウェブ用の文書を記述するためのマークアップ言語だ。文章を構成する要素 (見出しや段落など) にマークアップを施す (明示的に印をつける) ことで文書を表現する。HTMLは手作業で記述されることもあるが、プログラムから生成されることもある。

HTMLは単なるテキストだけではなく、画像や動画などのメディア、テキスト入力欄・ボタンなどのフォーム、JavaScriptによるプログラムなどを埋め込むことができるため、プログラムのGUIとしても使用される。ウェブブラウザーから表示した時のSNSやWikiの画面はHTMLで表現されている。

HTMLの見え方はスタイルシートという仕組みで決まる。これにより例えば見出しは大きな文字で、段落の前後は1行あけて、リンクは青い文字で表示される。スタイルシートを記述するための代表的な言語はCSSだ。一般的に、HTMLの制作者が自分でCSSを用意してHTMLと紐づけてウェブサイトの外観をデザインする。

Standard

HTMLの現行の標準仕様は「WHATWGのHTML Standard」および「ISO/IEC 15445:2000」だ。一般的なウェブ開発では前者が使用される。

HTMLの構文は仕様通りに記述されるべきだが、ウェブブラウザーはエラー修正機能を持ち、誤ったHTMLをなるべく正しく表示しようとする。そのためHTMLの誤りには気づきにくいが、有耶無耶にするとトラブル解決や互換性の面で問題の元になりかねない。

XHTML

通常のHTMLはXMLに似ているが厳密にはXMLではない。XHTMLを使用すれば完全なXMLの構文でHTML文書を記述できる。GNU socialの画面はXHTMLで表現されている。

PHPなどのプログラムでHTMLを生成する場合、XHTML構文を使用するか、通常のHTML構文を使用するかを区別する必要がある。また、JavaScriptでDOMを操作する場合も現在の文書がHTMLかXHTMLかで挙動に差が発生するため注意が必要だ。

HTMLとXHTMLとの主な差異は次の通りだ。

  • XML宣言がある
  • 要素名は小文字でなければならない
  • 開始タグ/終了タグの省略ができない
  • 通常のHTMLで終了タグの無い <img> 要素などは <img /> の様に閉じる必要がある

Form

About

Ref: <form>: フォーム要素 - HTML: ハイパーテキストマークアップ言語 | MDN

form関係の要素はWebアプリで非常に重要。

form要素外のinputとの連携。

基本的にform要素内に配置されたinputなどのフォーム関係要素の情報が同じform要素ないのtype=submitのボタンで送信される。

form要素外部に配置したform関係要素を送信に含めたい場合、form要素にidを指定しておき、外部のform関係要素のform属性で指定する。

<body>
    <form id="form1" method="POST" action="test.php">
        <input type="text" name="text1" id="text1" />
        <input type="submit" value="submit" />
    </form>
    <input type="text" name="text2" id="text2" form="form1" />
</body>

submitのボタンがform要素外部にある際も、form属性で指定すれば連携できる。

  • form: フォーム連携要素の処理、サーバーへのデータ送信用 (HTML Standard)。
  • fieldset: フォーム要素のグループ化用の要素 (The legend element)。
  • legend: fieldsetのラベル。

fieldsetが一番外側で、その中にformやinputがあるイメージ。

Attribute

重要な属性が何個かある。

  • action: 送信先のURL。
  • enctype: method="post"の場合のMIME。application/x-www-form-urlencoded=デフォルト。基本はこれで問題ない。multipart/form-data=画像やファイル類の場合。text/plain=デバッグに便利。
  • method: 送信時のHTTPメソッド。get=デフォルト。URLクエリー (?と&区切り)。post=フォームデータをリクエスト本体に設定。dialog=dialog要素内で有効。
  • novalidate: 論理値。フォーム送信時の検証を無視。

Autocomplete

Ref: HTML 属性: autocomplete - HTML: ハイパーテキストマークアップ言語 | MDN

input系要素の場合、autocomplete属性でWebブラウザーで自動入力できる。入力の手間を省くのに重要。

autocomplete属性の値で、Webブラウザーに自動入力の種類などを示唆できる。「HTML Standard」に指定可能な値がある。

いくつかよく使いそうなものを記載しておく。

  • email
  • url
  • username
  • off
  • on

Webブラウザーがオートコンプリートで認識してくれる項目がけっこう限定されている (Chrome でフォームに自動入力する - パソコン - Google Chrome ヘルプ)。

WebブラウザーがやってくれていないやつはJavaScriptでやっていることがある。

[Settings]-[Autofill and passwords] で管理されている。基本的に以下のデータが対象 (オートコンプリート属性入門 〜Chromeで設定できる項目を試してみた〜 - asoview! Tech Blog)。

  • username
  • password
  • 住所
  • 決済方法
  • email

その他の情報。

自動補完の条件がある。他のドメインにsubmitする場合はそのままだと対象外。また、autocomplete=usernameすると、ログイン時の入力補完の支援を受けられる。ややトリッキー。自動補完してほしいところはこれを指定しておくとひとまず楽ではある。

datalist

Ref: datalistタグ&inputのlist属性の使い方と注意点 [無料ホームページ作成クラウドサービス まめわざ]

autocompleteに近いものとしてdatalistがある。こちらはinput+selectのようなことができる。いわゆるコンボボックス的なことが簡単にできる。

    <input id="MaMiShare.host" list="MaMiList" type="email" inputmode="email"
      autocomplete="on" autocorrect="off" autocapitalize="off"
      formnovalidate='formnovaildate' placeholder="mstdn.jp misskey.io"
      style="background-color:rgb(158,194,63)" />
    <datalist id="MaMiList">
      <option value="fedibird.com"></option>
      <option value="gp.tsukimi.club"></option>
      <option value="mastodon.social"></option>
    </datalist>

数値入力

数値入力系のフォーム作成。ポイントがいくつかある。input[type=number]は一見するとこれがふさわしく見える。が、いろいろ問題がある。たとえば、e.+-が入力できる。

数字以外も入力できるが、イベントではこれらは空になる。文字数制限などで困る。type=textで実装したほうが都合がよいだろう。

<input type="text" inputmode="numeric" pattern="\d*">

他の方法で頑張ったほうがいい。

type="tel"だとイベントで値をとれる。

readonly/disabled

input要素の入力禁止の属性がreadonlyとdisabledの2種類ある。

readonly disabled
submit x -
focus x -

値の送信可否が非常に重要な違い。見た目だけで、送信する必要がないならば、disabledでOK。

name属性

query送信

html - How to append querystrings to a URL on submit of a form? - Stack Overflow

フォームパラメーターをURLクエリー (?name1=1&name2=2) 形式で送信したいことがある。

<form action="http://echo.iambroken.com/" method="get">
    <input name="one">
    <input name="two">
    <input type="submit">
</form>

method="get"にすると、クエリー形式になる。

ただし、既存のクエリー文字列を全部置換してしまう。既存はhiddenで残しておくとよい。

<input type="hidden" name="q" value="123">

[]配列参照

フォーム送信時に、サーバーサイドで配列として参照させることができる。nameの末尾を[]にすると配列扱い。キーを指定することもできる。省略すると0始まりの配列扱い。

これはHTML側ではなくて、サーバーサイド側の解釈の仕様。

PHPだと上記で定義されている。が、PHP以外の言語も同様の実装で、デファクトスタンダード的な扱い。

配列参照にすべきものと、そうでないフォームがある。

  • input[type=checkbox]
  • select

基本はcheckboxとselectのみ。逆に、これら以外は配列にしない。input[type=radio]は、送信する際は結局1個の値になる。特定したければ、[value=]のセレクターを使えばいい。

リレーションとの命名規則

https://chatgpt.com/c/673ad9c5-5d48-800b-a937-b8ff4fade246

複数テーブルとリレーションしたデータをフォームに表示したり、扱いたい場合、連動するform関係要素のname属性の命名規則に悩む。nameには_以外の記号が使えず、プレフィクスで分割などができないから。

該当テーブル名の配列にするとうまく取り扱える。

<input type="text" name="title" value="{{ old('title', $post->title) }}">
<select name="category_id">
     @foreach($categories as $category)
         <option value="{{ $category->id }}" {{ old('category_id', $post->category_id) == $category->id ? 'selected' : '' }}>
             {{ $category->name }}
        </option>
    @endforeach
</select>

外部キーを使うだけの場合はシンプルで上記のような感じ。

<input type="text" name="post[title]" value="{{ old('post.title', $post->title) }}">
<select name="post[category_id]">
     @foreach($categories as $category)
         <option value="{{ $category->id }}" {{ old('post.category_id', $post->category_id) == $category->id ? 'selected' : '' }}>
             {{ $category->name }}
        </option>
    @endforeach
</select>

配列にするとよさそう。上記の例は以下のようになる。

$request->input('post'); 
// 結果:
// [
//     'title' => 'Example Title',
//     'category_id' => 1
// ]

これを片方だけテーブル名の配列にして、allで取得する想定だときれいにおさまる。

PHPで上記の命名規則にするには以下のような関数で整形する。

    /**
     * Eloquentのモデルでリレーションで外部テーブルのカラム取得用に、name属性をname=table1[table2][name]形式かname=name形式に整形する。
     *
     * @param string[] $names [table1, table2, name] 形式の配列。外部からincludeしたリレーションのモデルメソッドに対応する接頭辞付きname属性の配列。
     * @param bool $foreign 外部キーの場合true。外部キーはincludeする側のテーブルカラムにあるからprefixをつけたくないのでこれをtrueにする。
     * @return string table1[table2][name]形式か$prefixが空の場合nameを返す。
     */
    public static function getPrefixedName(array $prefix, string $name, bool $foreign = false): string
    {
        $names = array_merge($prefix, [$name]);
        $offset = ($foreign && $prefix) ? 1 : 0;
        return array_reduce(array_slice($names, 1+$offset), function($c, $e){return $c.'['.$e.']';}, $names[$offset]);
    }

テストコード。

class GASHelperTest extends TestCase
{
    private $class = GASHelper::class;

    public function testGetPrefixedName()
    {
        $this->assertEquals($this->class::getPrefixedName([], 'name'), 'name');
        $this->assertEquals($this->class::getPrefixedName([], 'name', true), 'name');
        $this->assertEquals($this->class::getPrefixedName(['table1'], 'name'), 'table1[name]');
        $this->assertEquals($this->class::getPrefixedName(['table1', 'table2'], 'name'), 'table1[table2][name]');
        $this->assertEquals($this->class::getPrefixedName(['table1'], 'name', true), 'name');
        $this->assertEquals($this->class::getPrefixedName(['table1', 'table2'], 'name', true), 'table2[name]');
    }
}

CSS

CSS — Styling the web

CSS - ウェブ開発を学ぶ | MDN

CSS building blocks

CSS の値と単位

大きく数値、長さ、パーセント値の3種類がある。

  • 数値
  • 長さ
    • 絶対長さ
    • 相対長さ: em/rem, vh/vwなど。emは親要素、remはルート要素のフォントサイズが基準。lh=要素そのものの行の高さ。rlh=ルート要素 (通常html要素) の行の高さの相対値。vh/vwは拡大倍率。vh/vwは拡大倍率。1vhは1%。
  • パーセント値

Viewport (ビューポート) - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDN: Webブラウザーの用語としては、閲覧中文書の内、ウィンドウの中で現在見えている部分を指す。

lvh/svh/dvh

CSSの新しい単位(lvh, svh, dvh)がすべてのブラウザでサポート、100vhがビューポートの高さいっぱいにならない問題を解決 | コリス

【図解】CSSのvhとsvhとlvhとdvhは何が違う?(100vhを指定してもスマホでははみ出る問題も解決) | レンちゃんとペンタ

  • Large Viewport: アドレスバーで隠れる可能性がある。
  • Small Viewport: アドレスバーで隠れない部分。
  • Dynamic Viewport: アドレスバーで隠れない部分。

vhはデフォルトのビューポートサイズ。たいていLarge Viewportと同じ。svh<=vh<=lvhの範囲。

HTMLへの適用方法

CSS の構造 - ウェブ開発を学ぶ | MDN

CSSのHTMLへの適用方法が大きく3種類ある。

  1. 外部スタイルシート: head要素内のlink要素での参照     <link rel="stylesheet" href="styles.css" />
  2. 内部スタイルシート: head要素内のstyle要素内
  3. インラインスタイル: html要素のstyle属性 (非推奨)。

text-indent

Ref: CSS text-indentなコンテンツ内にinline-blockな要素がると崩れる - かもメモ.

text-indentが設定されているとinline-blockが崩れることがある。

inline-blockの要素に対して「text-indent: 0 又は、display: inline;」で解決するらしい。display:inlineで自分の場合解決した。

Selector

CSS セレクター - CSS: カスケーディングスタイルシート | MDN

CSSの適用範囲を指定する。document.querySelectorなどでも使用する。非常に重要。

スペースに意味があるので注意する。

エスケープ

セレクター内の[]などの特所文字は\でエスケープ必要。

document.querySelector('[name="楽楽販売_オーナーマスタ\\[販売店コード\\]"]');

結合子とセパレーター

組み合わせると、対象の下、左右を指定できる。後ろは選べるが、前は選べない。

  • + 次兄弟結合子next-sibling combinator: 直後の要素 (1個)。
  • > 子結合子child combinator: 直接の子要素 (1階層)。
  • || 列結合子 column combinator (実験的): 2のセレクターの間。
  • ~ 後続兄弟結合子subsequent-sibling combinator: 以後の要素 (全部)。
  • " " 子孫結合子descendant : 以後の子要素 (全階層)。
  • | Namespace separator: 左の名前空間に属する右にマッチ。

前は選べないが、:has()などと併用すると、前に近いものは選べる。

JSなしでタブ切り替えデザインを実装できるの、、、!? #CSS - Qiita

属性セレクター

Ref: CSSで複数の属性セレクタを指定する #CSS - Qiita.

div[data-color="red"][data-size="small"]

[属性名="属性値"]の書式。.クラス名は[class="クラス名"]の省略記法?

スペースを開けずに複数列挙することで複数指定できる。その場合、AND指定になる。

テキスト選択は不能

Is there a CSS selector for elements containing certain text? - Stack Overflow

要素のtextContentで選択したいことがあった。

CSS3の:containsでできるかもしれないが、これは未実装。空の場合だけ、:emptyが使える。

フォームのCSS required

<style>
input[required='required']::after {
	content: '*';
}
input[required='required'] {
	color: red;
}
input[required='required'] {
	background-color: red;
}

/* input[required='required'] {
    background-image: radial-gradient(#F00 15%, transparent 16%), radial-gradient(#F00 15%, transparent 16%);
    background-size: 1em 1em;
    background-position: right top;
    background-repeat: no-repeat;
} */
</style>

例えば、radioボタンの場合、ラベル側を修飾したい。.requiredのクラス属性を指定しておいたほうがいいだろう。

<label class="required">Name:</label>
<input type="text">

<style>
  .required:after {
    content:" *";
    color: red;
  }
</style>

他に以下のようなCSSで<label><input /></label>だとラベルを修飾できる。

	label:has(:required):after {
		content: " *";
		color: red;
	}

Tab menu

JavaScript使用可否で実装方法が異なる。JSを使う場合、リストのclickで表示、非表示用のクラスを脱着してやる。

JavaScript使わない場合、input[type=radio]のcheckedで表示させる形で実装する。

			<section class="tab-wrap">
				<label class="tab-label">ボタン1<input type="radio" name="tab" class="tab-switch" checked="chekced" /></label>
				<div class="tab-content">コンテンツ1</div>
				<label class="tab-label">ボタン2<input type="radio" name="tab" class="tab-switch" /></label>
				<div class="tab-content">コンテンツ2</div>
				<label class="tab-label">ボタン3<input type="radio" name="tab" class="tab-switch" /></label>
				<div class="tab-content">コンテンツ3</div>
			</section>
	.tab-wrap {
		display: flex;
		flex-wrap: wrap;
		.tab-switch {display: none;}
		.tab-label {
			color: White;
			background: LightGray;
			margin-right: 5px;
			padding: 3px 12px;
			order: -1;
		}
		.tab-content {
			width: 100%;
			display: none;
			padding: 10px 20px;
			background-color: #eee;
			border: 1px solid #ccc;
		}
		.tab-label:has(:checked) {
			background: rgb(231, 85, 1);
			+.tab-content {
				display: block;
			}
		}
	}

Table

行・列見出しの固定

position: stickyで固定できるらしい。

バリエーション1: ヘッダーをoverflow: scrollな要素の上と左に固定する

<div class="sticky_table_wrapper">
  <table class="sticky_table">
  </table>
</div>
.sticky_table_wrapper {
  overflow: scroll;
  width: calc(100vw - 1rem);
  height: 75vh;
}

widthとheightはお好みで。widthはいらないか。heightはいるかも。

クリック範囲拡大

ラジオボタンやa要素など。クリックしたいとき。そのままだとクリック範囲が狭い。

基本的にはlabelやaのスタイルでwith:100%;height:100%;を指定する。

Bootstrap

Introduction

元々Twitter社が公開した社内CSSフレームワーク。

[はじめに · Bootstrap v5.3] に記載のある [レイアウト (Grid)]/[コンポーネント (Button)] が具体的な使い方になる。リンク先のGrid/buttonが基本。

【超入門】初心者向け Bootstrapの基本的な使い方 - RAKUS Developers Blog | ラクス エンジニアブログ

なぜ使われているかは以下の特徴が由来。

  • レスポンシブWebデザイン対応
  • 導入のしやすさ、汎用性
  • 多数のコンポーネント

本来デザインは熟練が必要だが、Bootstrapを使うことで、Bootstrapの作法に従ったスタイル設計で、比較的簡単に一定レベルのデザインを実現できる。

Layout

Grid

グリッドシステム · Bootstrap v5.3

グリッドシステムは、12カラムの組み合わせで構築。CSS flexboxで構築されていてレスポンシブ (横幅に応じた可変)。

<div class="container text-center">
  <div class="row">
    <div class="col">
      Column
    </div>
    <div class="col">
      Column
    </div>
    <div class="col">
      Column
    </div>
  </div>
</div>

上記が基本の構成。以下が上記を構成する基本ルール。

  1. div.containerまたはdiv.container-fluid (container-fluidは画面幅いっぱい表示)
  2. 1内のdiv.row
  3. 2内のdiv.col-{breakpoint}-{columns}を複数配置。
  4. 3の{columns}の合計を12にする。
グリッド・オプション

{prefix} 相当がグリッドの階層になっている。

デバイス 画面サイズ prefix
スマホ 576px以下 xs (eXtra Small)
タブレット 576px以上~768px未満 sm (SMall)
PC(小) 768px以上 ~ 992px未満 md

(MidDle)

PC(中) 992px以上 ~ 1200px未満 lg

(LarGe)

PC(大) 1200px以上 ~ 1400px未満 xl

(eXtra Large)

PC(特大) 1400px以上 xxl

(eXtra eXtra Large)

画面サイズごとになっている。画面サイズの境界をブレークポイント (列が変わるから?) と呼んでいて、このブレークポイント単位で上記の区切りになっている。

オプションを使ったレイアウトはいくつかさらに使い方がある。

{breakpoint}と{columns}を省略すると、個数で自動で判断してくれる。

{breakpoint}-autoは、コンテンツサイズに応じて自動で幅を近しいものにしてくれる。

個人的には、{breakpoint}と{columns}を省略した形を優先して使っていきたい。

Component

Button

ボタン · Bootstrap v5.3

Other

tooltip

マウスホバーで出してくれる補足情報。いくつか実装方法がある。

title属性を設定するとそれで表示してくれる。これがシンプル。

Space

前提として、HTMLだと2個以上のスペースが1個に丸めて表示される。

スペースを維持する方法がいくつかある。一番シンプルなのはpre要素。

ベースにあるのが、white-spaceプロパティー。この値で制御される。

改行文字 空白と

タブ文字

テキストの

折り返し

行末の空白 行末の

その他の空白区切り

normal まとめる まとめる 折り返す 除去 ぶら下げる
nowrap まとめる まとめる 折り返さない 除去 ぶら下げる
pre そのまま そのまま 折り返さない そのまま 折り返さない
pre-wrap そのまま そのまま 折り返す ぶら下げる ぶら下げる
pre-line そのまま まとめる 折り返す 除去 ぶら下げる
break-spaces そのまま そのまま 折り返す 折り返す 折り返す

折り返しの有無で、pre/pre-wrapを使うのがよいと思われる。