【HTML】<picture>タグを<p>で囲んではいけないのはなぜ?
解決したいこと
テキスト画像を配置する際、
<picture>
を<p>
で囲んではいけない理由が分かりません。
※下部に追記事項があります。
❌NG
<p>
<picture>
<source media="(min-width: 769px)" srcset="/img/img-pc.webp" width="800" height="400">
<img src="/img/img-sp.webp" width="400" height="200" loading="lazy" alt="画像">
</picture>
</p>
⭕️OK
<div>
<picture>
<source media="(min-width: 769px)" srcset="/img/img-pc.webp" width="800" height="400">
<img src="/img/img-sp.webp" width="400" height="200" loading="lazy" alt="画像">
</picture>
</div>
納得できない点
- コンテンツカテゴリ的に、
p
の下にpicture
は置けるはずなのになぜ? -
source
が原因なのであれば、div
でpicture
を囲む形もNGになるのでは? -
picture
はブロック要素と同じ扱いをされる、みたいなことを言われたが、ブロック要素ではないよな?
コンテンツカテゴリ | 配置できる場所 | 配置できる子要素 | |
---|---|---|---|
p |
フローコンテンツ | フローコンテンツを配置可能な場所 | フレージングコンテンツ(インライン要素) |
div |
フローコンテンツ | フローコンテンツを配置可能な場所 | フローコンテンツ(ブロック/インライン要素) |
picture |
フローコンテンツ、フレージングコンテンツ、組み込みコンテンツ | 組み込みコンテンツを配置可能な場所 | 0個以上のsource要素を配置し、最後にimg要素を配置 |
source |
なし |
audio 、video 、picture
|
なし(空要素) |
各要素のコンテンツカテゴリは、上記の通りだと思います。
p
はフレージングコンテンツを内包できます。
それなのに、フレージングコンテンツに属しているpicture
を配置できない理由が分かりません。
コンテンツカテゴリに属さないsource
が子孫要素にいるのが問題なのでしょうか。
こんな形ほぼ見ることはないと思いますが、
<p>
<picture>
<img src="/img/img-sp.webp" width="400" height="200" loading="lazy" alt="画像">
</picture>
</p>
の形ならOKなのでしょうか。
しかし、div
もフローコンテンツかインライン要素しか中に入れることができないはずです。
なぜdiv
で囲む形は許されるのかも、納得できません!
また、picture
がブロック要素と同じような扱いをされるというのは、どういうことなのでしょうか。
chatGPTに聞いても理解することができませんでした。
どなたか解説していただけますと幸いです。
参考にしたサイト
-
HTML Living Standard
https://html.spec.whatwg.org/multipage/embedded-content.html#the-source-element -
MDN
<p>
https://developer.mozilla.org/ja/docs/Web/HTML/Reference/Elements/p
2025/06/09 追記
- pで囲んではいけないという情報の元出は?
現時点では、私も明確なweb情報は見つけられていません。
業務のFBでもらった意見なのですが、
「ブロックレベル要素を入れることができない」、というところからこの問題が生じました。
https://www.w3.org/TR/html401/struct/text.html#h-9.3.1
pictureはブロックレベルの要素じゃなくない?と思い、調べてみたのですが記事は見つからず…。
chatGPTに聞いて出てきた答えが、以下になります。
これは、HTMLパーサの「p 要素の自動終了ルール(implicit end tag)」によるものです。
✅ ポイント
picture は確かに phrasing content に該当します。
しかし、<picture> 内に含まれる <source> 要素は phrasing content に該当しません。
<p> の中に phrasing content 以外が含まれた時点で、ブラウザは <p> を自動的に閉じる仕様になっています。
FBを受けた私も、FBを出した方も、???となっているので、
納得できる解を見つけるために質問してみた、という流れになります。
そもそも、FB時点の情報がおかしい、という可能性もあるのでしょうか…
✏️2025/07/15 追記
気になっている点を整理しました!
- 画像化した文章を設置
- 画面幅によって出しわけをしたい
上記を反映するために、
<p>
<picture>
<source media="(max-width: 768px)" srcset="small.jpg">
<source media="(max-width: 1024px)" srcset="medium.jpg">
<img src="large.jpg" alt="テキストテキストテキスト">
</picture>
</p>
というコードを書きたかったのですが、これはHTML構文的にNGとchatGPTに言われました。
<p>
は フレージングコンテンツのみを子孫に持てます。
<picture>
はフレージングコンテンツに属するので 一見OKに見えます。
ですが、中にある<source>
は どのコンテンツカテゴリにも属していません(= フレージングコンテンツではない)。
そのため、<p>
の中に<source>
が間接的に含まれることで、構文違反になります。
〜〜〜
この場合、<source>
が<p>
の子孫に入ってしまうことで、HTMLパーサーが<p>
を強制的に閉じてしまい、意図した構造にならない。
ここで言われている、
-
p
の中に入っているものが全てフレージングコンテンツでないといけない。 - HTMLパーサーが強制的に閉じられる。
という部分の根拠を自力で見つけることができず、困っています。
何か有力な情報がありましたら教えていただけますと幸いです。