12
7

Claude.aiのArtifactsのプレビューは一体どういう仕組なの?

Posted at

Claude.aiの「Artifacts」、皆さん使ってますか?

HTMLの生成をお願いすると、上手にHTMLを生成してくれます。

さらに、HTMLのプレビューまで切り替えられます。

これは一体どういうテクノロジーでできているのでしょうか??

開発者ツールで確認

ブラウザの開発者ツールを使って、プレビュー部分がどうやってできているか見てみます。
すると、iFrameが見つかりました。

iFrameの「srcdoc」属性にHTMLがセットされていることがわかりました。

iFrameの仕様を確認

MDNドキュメントで、iFrameの仕様を確認します。

srcdoc属性の説明は以下のとおりです。

埋め込むインライン HTML で、 src 属性を上書きします。ブラウザーが srcdoc 属性に対応していない場合は、 src 属性の URL で代替されます。

srcdocにHTMLを埋め込むことができそうです。

やってみた

最低限のHTMLを書いてみました。Bodyの中はiFrameのみです。srcdocに太字にした文字をセットしてみました。

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <title>Page Title</title>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
    <link rel='stylesheet' type='text/css' media='screen' href='main.css'>
</head>
<body>
    <iframe srcdoc="<html><b>Hello, World!</b></html>"></iframe>
</body>
</html>

期待したとおりに出ましたね。

Claudeが作ってくれたHTMLを貼り付けてみましょう

HTML
<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'>
    <meta http-equiv='X-UA-Compatible' content='IE=edge'>
    <title>Page Title</title>
    <meta name='viewport' content='width=device-width, initial-scale=1'>
    <link rel='stylesheet' type='text/css' media='screen' href='main.css'>
</head>
<body>
    <iframe width="600" height="400" srcdoc="<!DOCTYPE html>
        <html lang=&quot;ja&quot;>
        <head>
            <meta charset=&quot;UTF-8&quot;>
            <meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;>
            <title>ログイン</title>
            <style>
                body {
                    font-family: Arial, sans-serif;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    height: 100vh;
                    margin: 0;
                    background-color: #f0f0f0;
                }
                .login-container {
                    background-color: white;
                    padding: 2em;
                    border-radius: 5px;
                    box-shadow: 0 0 10px rgba(0,0,0,0.1);
                }
                h2 {
                    text-align: center;
                    color: #333;
                }
                form {
                    display: flex;
                    flex-direction: column;
                }
                label {
                    margin-top: 1em;
                }
                input {
                    padding: 0.5em;
                    margin-top: 0.5em;
                }
                button {
                    margin-top: 1em;
                    padding: 0.5em;
                    background-color: #007bff;
                    color: white;
                    border: none;
                    border-radius: 3px;
                    cursor: pointer;
                }
                button:hover {
                    background-color: #0056b3;
                }
            </style>
        </head>
        <body>
            <div class=&quot;login-container&quot;>
                <h2>ログイン</h2>
                <form action=&quot;#&quot; method=&quot;post&quot;>
                    <label for=&quot;username&quot;>ユーザー名:</label>
                    <input type=&quot;text&quot; id=&quot;username&quot; name=&quot;username&quot; required>
                    
                    <label for=&quot;password&quot;>パスワード:</label>
                    <input type=&quot;password&quot; id=&quot;password&quot; name=&quot;password&quot; required>
                    
                    <button type=&quot;submit&quot;>ログイン</button>
                </form>
            </div>
        </body>
        </html>"></iframe>
</body>
</html>

お~~~~


一見難しそうなブロック崩しも、同じ理屈でできています。

自作iFrameに移植👇️👇️👇️

おまけ

Reactでこんなのを作ると、リアルタイムで反映されて楽しいです。

import { useState } from "react"

function App() {

  const [text, setText] = useState("")

  return (
    <>
      <textarea value={text} onChange={e => setText(e.target.value)} style={{ width: "800px", height: "600px" }}></textarea>
      <iframe srcDoc={text} style={{ width: "800px", height: "600px" }} ></iframe>
    </>
  )
}

export default App

12
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
7