画像からのHTML生成におけるAIモデルの差とSkills有無の差を検証
日に日に進化を遂げるAIエージェントですが、今回は画像からのHTML生成を対象に、モデル毎の差とSkills有無の差を検証しました。
Figma MCPは使用せず、デザインカンプのスクリーンショットを元にしたHTML生成の検証です。AIモデルのAgent機能を使用し、画像からどれだけ正確にHTMLを生成できるかを試してみました。
実案件においてはデザインカンプに機密情報が含まれることもあります。実際に現場で使用する際にはクライアントに確認を取りながら、またセキュリティに留意しながら進めることが求められます。
各モデルの比較
今回はCursorのAIモデル選択機能を使用し、下記のモデルを比較対象としました。いずれもコーディング業務の様々な場面で使用されることが多い人気のAIモデルです。
- Composer 2
- GPT-5.4
- Sonnet 4.3
条件
HTML生成の条件は次の通りです。
- エディタ:Cursor(Version: 3.1.14)
- プラン:Pro
- 生成内容:HTMLのみ(CSSなし)
- モード:Agent
- プロンプト:添付画像からコンポーネント(c-card)のHTMLを出力してください。CSSの生成は不要です。画像はダミー画像でお願いします。
- 添付画像:下記画像
あえて詳細な指示は与えず、プロンプトは簡易的なものにしています。RulesやSkillsは設定していません。プロンプトに添付する画像は下記のコンポーネントです。

よくあるサービス内容を紹介するカードコンポーネントで、次の6つの要素で構成されています。
| 要素 | 要素の種類 | 筆者が期待するタグ |
|---|---|---|
| アイキャッチ画像 | 画像 | <img> |
| 英語ラベル | テキスト | <p>または<span> |
| 日本語タイトル | 見出し | <h2> <h3> 等の見出しタグ |
| キャッチコピー | テキスト | <p> |
| 説明文 | テキスト | <p> |
| アイコン付きボタン | リンク | <a> |
それほど複雑な内容のコンポーネントではありませんが、画像、タイトル、ボタンといった基本的な要素は入っており、今回の検証に最適なコンポーネントです。
Composer 2
まずは Composer 2 で生成した結果です。
<article class="c-card"> <img class="c-card__image" src="https://placehold.co/640x360/e8e8e8/666666?text=Dummy" alt="" width="640" height="360" loading="lazy" decoding="async"> <div class="c-card__body"> <p class="c-card__category">IT SERVICE MANAGEMENT</p> <h2 class="c-card__title">ヘルプデスクの運用支援</h2> <p class="c-card__lead">問い合わせ窓口の一本化で、情シス部門と利用部門の両立をサポート</p> <p class="c-card__description">受付設計、ナレッジ整備、一次対応品質のモニタリングまでを一括で支援し、解決時間の短縮と属人化の抑制を進めます。</p> <div class="c-card__actions"> <a href="#" class="c-card__button"> <span class="c-card__buttonLabel">Learn more</span> <span class="c-card__buttonIcon" aria-hidden="true">→</span> </a> </div> </div></article>かなり精度が高い結果のように見えます。
特にルート要素にarticleタグを使用していたり、画像要素にwidthやloadingなどの各種属性を設定している点に驚きました。以下の点が少し気になりました。
- 画像要素にラッパー要素がない(必須ではない)
c-card__buttonLabelのようにクラス名がキャメルケースになっている
GPT-5.4
続いて GPT-5.4 で生成した結果です。
<article class="c-card"> <a class="c-card__link" href="#"> <figure class="c-card__image"> <img src="https://placehold.jp/536x328.png" alt="ヘルプデスクの運用支援のイメージ" width="536" height="328"> </figure> <div class="c-card__body"> <p class="c-card__category">IT SERVICE MANAGEMENT</p> <h2 class="c-card__title">ヘルプデスクの運用支援</h2> <p class="c-card__lead">問い合わせ窓口の一本化で、情シス部門と利用部門の両立をサポート</p> <p class="c-card__text"> 受付設計、ナレッジ整備、一次対応品質のモニタリングまでを一括で支援し、解決時間の短縮と属人化の抑制を進めます。 </p> <span class="c-card__button"> <span class="c-card__button-label">Learn more</span> <span class="c-card__button-icon" aria-hidden="true">→</span> </span> </div> </a></article>こちらもarticleタグが使用されており、またクラス名はc-card__button-labelのようにケバブケースとなっています。以下の点が気になりました。
- 全体の要素を
aタグでラップしている - 画像要素に
loadingやdecodingなどの属性がない
Sonnet 4.3
続いて Sonnet 4.3 で生成した結果です。
<div class="c-card"> <figure class="c-card__img"> <img src="https://placehold.co/600x400" alt="ヘルプデスクの運用支援"> </figure> <div class="c-card__body"> <p class="c-card__label">IT SERVICE MANAGEMENT</p> <h2 class="c-card__title">ヘルプデスクの運用支援</h2> <p class="c-card__lead">問い合わせ窓口の一本化で、情シス部門と利用部門の両立をサポート</p> <p class="c-card__text">受付設計、ナレッジ整備、一次対応品質のモニタリングまでを一括で支援し、解決時間の短縮と属人化の抑制を進めます。</p> <a href="#" class="c-card__btn"> <span>Learn more</span> <span class="c-card__btn-arrow">→</span> </a> </div></div>こちらは全体のラッパー要素にdivタグを使用しています。以下の点が気になりました。
- 画像要素に
widthやloadingなどの属性がない - ボタンのアイコン要素に
aria-hidden="true"の設定がない
総評
いずれのAIモデルにおいても、HTMLの生成にかかる時間は数十秒でした。また、画像の中にあるテキストは全て正しくHTMLに反映されていました。
各モデルの出力の差分を表にしてみました。
| 項目 | Composer 2 | GPT-5.4 | Sonnet 4.3 |
|---|---|---|---|
| ルート要素 | <article> | <article> | <div> |
カード全体を<a>で包む | なし ✅ | あり ❌ | なし ✅ |
| 画像ラッパー | なし(imgを直接配置) | <figure> | <figure> |
imgのloading/decoding属性 | あり ✅ | なし ❌ | なし ❌ |
imgのwidth/height属性 | あり ✅ | あり ✅ | なし ❌ |
| ボタンの要素 | <a> ✅ | <span> ❌ | <a> ✅ |
| ボタン内テキストのクラス名 | c-card__buttonLabel(キャメル) | c-card__button-label ✅ | クラスなし |
| ボタンラッパー | c-card__actionsでラップ | ラップなし | ラップなし |
| 総合評価 | ○ | △ | △ |
RulesやSkillsを設定しない今回の検証では、Composer 2 が最も精度が高い結果となりました。
特に画像要素に各種属性を設定している点、ルート要素にarticleタグを使用している点、ボタンにラッパー要素を使用している点が実案件レベルだと感じました。
Skillsを設定していない場合、補完に差が生まれるためか、各モデルでHTMLの出力結果に差があることが確認できました。比較した中で Composer 2 が最も精度が高いことは少し意外でした。
次章ではSkillsを設定した場合に、各種モデルで出力結果がどのように変化するかを検証してみます。
Skills設定後の比較
以下の内容でSKILL.mdを作成しました。
.cursor/skills/html-from-image/SKILL.md
---name: html-from-imagedescription: デザインカンプのスクリーンショット・画像からHTMLを生成するタスクに使用する。画像コーディング、デザイン実装、カンプ起こし、HTML生成と言われたときに参照する。---
# 画像からHTML生成ルール
## セマンティクス
- HTML Living Standardに従い適切にタグを選択する- 要素のまとまりと判断できる箇所は適切にグルーピングを行う- 自己完結したコンテンツ単体(カード等)には`<article>`を使用する- 関連コンテンツのグループ化には`<section>`を使用する(見出しを含む場合)- 意味的な役割のない箇所には`<div>`を使用する
## 画像
- `width`と`height`は必ず設定する- 特に指定がない限り`loading="lazy"` `decoding="async"`を設定する- 装飾画像の場合`alt`属性は空にする。装飾画像でない場合は`alt`属性を適切に設定する- 挿入する画像の指定がない限り`img`要素のsrc属性には`https://placehold.co/幅x高さ`を設定する
## クラス名
- 指示されたコンポーネント名がある場合はそれをルート要素のクラスに設定する- 指示されたコンポーネント名がない場合は適切なクラス名をルート要素に設定する- BlockとElementの間は`__`で繋ぐ(例: `c-card__button`)- Elementが入れ子になっている場合は`-`で繋ぐ(例: `c-card__button-icon`)
## テキスト
- スクリーンショットから読み取れないテキストはダミーテキストを挿入する
## アイコン
- アイコンはSVGをインラインで記述する- 装飾目的のSVGには`aria-hidden="true"`を付与する
## リンク
- カード全体を`<a>`で包まない- リンク・ボタンはカード内の該当要素に個別に設定する
## 出力
- HTMLのみを出力する- コードブロック(``` )で囲まない- 説明文・コメントは含めないそれほど細かい指示は与えていませんが、最低限守って欲しいことを記述しています。
なお今回は常時適用ではなく、特定のタスクに対してのみルールを適用したいため、RulesではなくSkillsを設定しています。CursorのRulesとSkillsの違いについては下記の記事が参考になりました。 【Cursor】Skillsとルールの違いって何?
条件
前項の条件からプロンプトのみ変更しています。
- エディタ:Cursor(Version: 3.1.14)
- プラン:Pro
- 生成内容:HTMLのみ(CSSなし)
- モード:Agent
- プロンプト:添付画像からコンポーネント(c-card)のHTMLを出力してください。
- 添付画像:同じものを使用
CSSの生成は不要なこと、画像はダミー画像にすることはSkillsの指示で補えるため、プロンプトをより簡易的にしています。
html-from-imageのdescriptionに、「画像コーディング、デザイン実装、カンプ起こし、HTML生成」のキーワードを記述しているため、このプロンプトでhtml-from-imageのSkillsが適用される仕組みです。
Composer 2
まずは Composer 2 で生成した結果です。
<article class="c-card"> <div class="c-card__media"> <img class="c-card__image" src="https://placehold.co/640x360/e8e8e8/666666" alt="オフィスで複数モニターを用いて業務する様子" width="640" height="360" loading="lazy" decoding="async"> </div> <div class="c-card__body"> <p class="c-card__label">IT SERVICE MANAGEMENT</p> <h2 class="c-card__title">ヘルプデスクの運用支援</h2> <p class="c-card__lead">問い合わせ窓口の一本化で、情シス部門と利用部門の両立をサポート</p> <p class="c-card__text">受付設計、ナレッジ整備、一次対応品質のモニタリングまでを一括で支援し、解決時間の短縮と属人化の抑制を進めます。</p> <div class="c-card__actions"> <a class="c-card__button" href="#"> <span class="c-card__button-text">Learn more</span> <span class="c-card__button-icon"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" aria-hidden="true" focusable="false"> <rect width="20" height="20" fill="#fff" /> <path d="M8 6l4 4-4 4" fill="none" stroke="#000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" /> </svg> </span> </a> </div> </div></article>特に気になる点はありませんでした。強いて言えばインラインSVGの形状が添付画像のものとは少し異なりました。ただ後ほどダウンロードした画像を埋め込むので、そこまで気にする必要はないかと思います。
GPT-5.4
続いて GPT-5.4 で生成した結果です。
<article class="c-card"> <figure class="c-card__media"> <img class="c-card__image" src="https://placehold.co/519x332" alt="オフィスでPC作業をするスタッフ" width="519" height="332" loading="lazy" decoding="async"> </figure> <div class="c-card__body"> <p class="c-card__eyebrow">IT SERVICE MANAGEMENT</p> <h2 class="c-card__title">ヘルプデスクの運用支援</h2> <p class="c-card__lead">問い合わせ窓口の一本化で、情シス部門と利用部門の両立をサポート</p> <p class="c-card__description">受付設計、ナレッジ整備、一次対応品質のモニタリングまでを一括で支援し、解決時間の短縮と属人化の抑制を進めます。</p> <a class="c-card__button" href="#"> <span class="c-card__button-label">Learn more</span> <span class="c-card__button-icon" aria-hidden="true"> <svg width="36" height="12" viewBox="0 0 36 12" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M1 6H33" stroke="currentColor" stroke-width="2" /> <path d="M28 1L33 6L28 11" stroke="currentColor" stroke-width="2" /> </svg> </span> </a> </div></article>英語ラベルのクラス名がc-card__eyebrowとなっている点が少し気になりました。
調べてみると eyebrow はUIデザイン用語として広く使われている名前で、見出しの上にある小さなラベルテキストを指す業界用語のようです。一般的なBEM命名とはやや異なりますが、特に問題はなさそうです。
Sonnet 4.3
続いて Sonnet 4.3 で生成した結果です。
<article class="c-card"> <div class="c-card__image"> <img src="https://placehold.co/560x320" width="560" height="320" alt="オフィスでPCを操作するITエンジニアたち" loading="lazy" decoding="async"> </div> <div class="c-card__body"> <p class="c-card__label">IT SERVICE MANAGEMENT</p> <h2 class="c-card__title">ヘルプデスクの運用支援</h2> <p class="c-card__lead">問い合わせ窓口の一本化で、情シス部門と利用部門の両立をサポート</p> <p class="c-card__text">受付設計、ナレッジ整備、一次対応品質のモニタリングまでを一括で支援し、解決時間の短縮と属人化の抑制を進めます。</p> <a class="c-card__button" href="#"> <span class="c-card__button-text">Learn more</span> <span class="c-card__button-icon" aria-hidden="true"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path d="M5 12h14M12 5l7 7-7 7" /> </svg> </span> </a> </div></article>こちらもインラインSVGの形状が添付画像のものとは異なること以外、気になる点はありませんでした。
総評
各モデルの出力の差分を表にしてみました。
| 項目 | Composer 2 | GPT-5.4 | Sonnet 4.3 |
|---|---|---|---|
| ルート要素 | <article> | <article> | <article> |
カード全体を<a>で包む | なし ✅ | なし ✅ | なし ✅ |
| 画像ラッパー | <div> | <figure> | <div> |
imgのloading/decoding属性 | あり ✅ | あり ✅ | あり ✅ |
imgのwidth/height属性 | あり ✅ | あり ✅ | あり ✅ |
| ボタンの要素 | <a> ✅ | <a> ✅ | <a> ✅ |
| ボタン内テキストのクラス名 | c-card__button-text ✅ | c-card__button-label ✅ | c-card__button-text ✅ |
| ボタンラッパー | c-card__actionsでラップ | ラップなし | ラップなし |
| 総合評価 | ○ | ○ | ○ |
各モデル間で、以下のような違いがありました。
- 画像ラッパー:
<div>と<figure> - ボタンラッパー:ラップありとラップなし
- クラス名:
c-card__button-textとc-card__button-labelなど
ただこれらはいずれも正解があるものではなく、好み次第です。Skillsを設定することにより、各モデルでの出力の精度をある程度担保できたと感じました。
クラス名については、Skillsによく使う単語をあらかじめ定義しておくことで、より安定した出力を得ることができるでしょう。
なお今回の検証は一発勝負の出力結果であり、同じAIモデルで同じプロンプトを実行しても、タイミングによっては結果が異なる可能性があります。また今回とは違った画像ではどうなるかも検証する必要がありそうです。
まとめ
「画像からのHTML生成」において、今回の検証から下記の結果を得られました。
- Skillsを設定しない場合、Composer 2 が最も精度が高い結果となりました。
- Skillsを設定した場合、各モデルでの出力の精度をある程度担保できることが確認できました。
モデル選びも重要ですが、Skillsのようなルール定義を整備することで、モデルの差を吸収し安定した出力が得られることがわかりました。Skills整備への投資は高い費用対効果があると感じました。
いずれにしてもCursorで画像からHTMLを生成する際には、Composer 2 を選択しておいて問題ないということもわかりました。Composer 2の方が他のモデルより安価なため、料金面でも有利です。
今回は修正コストの低いHTMLでの検証でした。今後はCSS生成の精度についても検証してみたいと思います。
なお、本記事で使用したAIはいずれも2026年4月時点のものです。今後更に各AIモデルが進化を遂げることが予想されるため、必ずしも本記事の結果が今後も通用するとは限りません。
