日直地獄

小学校では事件が起きる

自動生成アイキャッチをカスタムする機能で遊ぼう!

はてなブログで、自動生成アイキャッチをカスタムする機能がリリースされましたね。
staff.hatenablog.com
はてなブログのインターンによる機能開発であり、ディレクターとして開発に関わっていたわけですが(関係性の明示)、なかなか面白い、というか上等で実用的なおもちゃという感じでいじってると時間が溶ける。プレビューがキビキビ反映されるのはとても気持ちいいですね。
さて変数とHTMLとCSSがかけると様々なことが可能になります。実際に見てみましょう。

タイトルを設定していない記事でいい感じにする

例えば、自分のブログの場合、日記にはタイトルをつけずに、人に読まれたいブログっぽい記事にはタイトルをつける、という風習がある。この場合に{Title}変数を使ってしまうと、タイトル部分に何も出なくなって体裁が悪い。なので、CSSでtitleの要素の中身が空の場合に、特定の要素を出す、というコードを入れる。
HTML

    <div class="content">
      <span class="entry-title">{Title}</span>
      <div class="empty-title"><span>{PostedYear}年{PostedMonth}月{PostedDate}日</span><div class="category">{FirstCategory}</div></div>
    </div>

CSS

    .content .empty-title {
       display:none;
    }
    .content:has(.entry-title:empty) .empty-title {
      display: block;
      text-align: center;
    }

とすると空タイトルの場合にもいい感じになる。

タイトル有り
タイトルなし

SVGで背景をつける

仕様上、画像はbase64化したimgタグでしか対応できない。またHTMLのサイズの上限もあるので、SVGを使うのが良いはず。SVGはコードをSVG要素として埋め込んでもいいし、base64化してbackground-imageとして指定してもいい。SVGのコードはChatGPTに生成させられるのは便利だと思う。

雑に質問している様子
適用したらこんな感じ

カテゴリに応じてデザインを変更する

これはデフォルトのテンプレートでもカテゴリに応じた処理が記載されていますね。自分のブログだと「連絡帳」カテゴリのときだけ連絡帳っぽいデザインにしたりできる。実例はありません

もう全部ChatGPTに作ってもらう

全くHTMLは弄りたくない!と思ったときにChatGPTに作らせるという作戦もあるかもしれません。雑に試してみましょう。ちなみに私のLLM使いこなしレベルは1です。

質問:
今から1200x630のブログのog:image画像を生成したいです。HTMLで指定すると画像になる仕組みを用意しているので、そのHTMLを作成する、というのが今回の目的です。
使える変数は、ブログのタイトルが{BlogTitle}、記事のタイトルが{Title}、投稿年が{PostedYear}、投稿月が{PostedMonth}、投稿日が{PostedDate}、最初のカテゴリが{FirstCategory}となります。
ふわっとした可愛い色合いの丸が浮かぶ背景でお願いします。

結果、以下のようなアイキャッチのHTMLが生成されました。ちなみに丸にはアニメーションの指定がされています。画像だって言ってんじゃん。なお、最初に生成されたHTMLではタイトルが長い場合のオーバーフローの処理が行われていなかったので処理を入れるように言ったりもしてます。この辺はなかなか難しいですね。

生成されたHTMLを見る

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>OG Image</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            width: 1200px;
            height: 630px;
            background: linear-gradient(135deg, #a29bfe, #81ecec); /* ふわっとした可愛い色合いのグラデーション */
            color: #2d3436; /* 明るい文字色 */
            font-family: 'Arial', sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
            text-align: center;
            position: relative;
            overflow: hidden;
        }
        .title {
            font-size: 48px;
            font-weight: bold;
            margin-bottom: 10px;
            color: #ffffff; /* タイトル文字色 */
            max-width: 90%; /* 最大幅を設定 */
            white-space: nowrap; /* 改行しない */
            overflow: hidden; /* はみ出した部分を隠す */
            text-overflow: ellipsis; /* 省略記号を表示 */
        }
        .subtitle {
            font-size: 36px;
            margin-bottom: 20px;
            color: #ffffff; /* サブタイトル文字色 */
            max-width: 90%; /* 最大幅を設定 */
            white-space: nowrap; /* 改行しない */
            overflow: hidden; /* はみ出した部分を隠す */
            text-overflow: ellipsis; /* 省略記号を表示 */
        }
        .info {
            font-size: 24px;
            margin-top: 10px;
            color: #ffffff; /* 情報文字色 */
            opacity: 0.8;
            max-width: 90%; /* 最大幅を設定 */
            white-space: nowrap; /* 改行しない */
            overflow: hidden; /* はみ出した部分を隠す */
            text-overflow: ellipsis; /* 省略記号を表示 */
        }
        .bubbles {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            pointer-events: none;
            overflow: hidden;
        }
        .bubble {
            position: absolute;
            border-radius: 50%;
            background: rgba(255, 255, 255, 0.5);
            animation: float 10s infinite;
        }
        @keyframes float {
            0% { transform: translateY(0); }
            100% { transform: translateY(-100vh); }
        }
        .bubble:nth-child(1) {
            width: 100px;
            height: 100px;
            top: 20%;
            left: 10%;
            animation-duration: 12s;
            animation-delay: 0s;
        }
        .bubble:nth-child(2) {
            width: 80px;
            height: 80px;
            top: 50%;
            left: 30%;
            animation-duration: 10s;
            animation-delay: 2s;
        }
        .bubble:nth-child(3) {
            width: 120px;
            height: 120px;
            top: 70%;
            left: 60%;
            animation-duration: 15s;
            animation-delay: 4s;
        }
        .bubble:nth-child(4) {
            width: 90px;
            height: 90px;
            top: 30%;
            left: 80%;
            animation-duration: 13s;
            animation-delay: 6s;
        }
    </style>
</head>
<body>
    <div class="bubbles">
        <div class="bubble"></div>
        <div class="bubble"></div>
        <div class="bubble"></div>
        <div class="bubble"></div>
    </div>
    <div class="title">{BlogTitle}</div>
    <div class="subtitle">{Title}</div>
    <div class="info">{PostedYear}年 {PostedMonth}月 {PostedDate}日 | カテゴリ: {FirstCategory}</div>
</body>
</html>


他の人の事例が知りたい

知りたいです。