关于 instagram-carousel
instagram-carousel 是一项生成 Instagram 轮播图 HTML 预览与导出素材的技能,面向制作社交媒体内容的创作者。它指导品牌风格、幻灯片序列和交互预览,并要求先审核预览获批后再导出单页 PNG。
主要功能
- 01生成可独立使用的轮播 HTML
- 02支持多种幻灯片序列
- 03按品牌色与字体设置视觉样式
- 04支持图片嵌入和滑动预览
- 05审核通过后导出单页 PNG
适用场景
- 01制作 Instagram 教程轮播
- 02设计产品功能介绍轮播
- 03制作清单或比较类内容
- 04将审核后的幻灯片导出为 PNG
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ marcolang/ marketing-skills --skill instagram-carousel安装后在 Claude Code 中输入/instagram-carousel确认已加载。
附带文件.claude/settings.json
详细介绍
Instagram 轮播图生成器
生成完全自包含、可滑动的 HTML 轮播图,每张幻灯片都设计为可导出为单张 1080×1350px 的 Instagram PNG 图片。
步骤 1:收集品牌详情
生成前,询问用户以下信息(如果尚未提供):
- 品牌名称 — 显示在首张和末张幻灯片上
- Instagram 用户名 — 显示在 IG 帧标题中
- 品牌主色 — 十六进制代码,或由用户描述并让 Claude 选择
- Logo — SVG 路径、品牌首字母,或跳过
- 字体偏好 — 参见下方的排版表,或指定 Google Fonts
- 语气 — 专业、随意、活泼、大胆、极简等
- 图片 — 头像、截图、产品图片等
- 幻灯片语言 — 默认:葡萄牙语(巴西),除非另有指定
- 轮播图格式 — 标准格式(7 张幻灯片)或其他顺序(参见序列部分)
如果用户提供了网站 URL 或品牌素材,请据此提取配色和风格。
如果用户只说“给我做一个关于 X 的轮播图”,却没有提供品牌详情,请先询问,不要自行假设默认值。
处理用户提供的图片
本节从首次生成 HTML 时就适用,不只适用于导出期间。
用户提供图片文件路径时(例如 /home/user/gestante.png、/mnt/user-data/uploads/foto.jpg):
⚠️ 关键规则
- 绝不要使用相对路径(
gestante.png)——除 HTML 所在的确切文件夹外,在其他所有浏览器环境中都会失效。 - 绝不要使用
background: url(filepath)——这会导致生成 1.5MB 以上的 base64 内联字符串,令浏览器解析器崩溃。 - 始终将图片嵌入为 base64
data:URI——在预览、导出和任何环境中都能正常工作。 - 始终通过 Python 生成 HTML(使用
Path.write_text())——Shell heredoc 会插入$和反引号,破坏 base64 字符串。
分步说明:嵌入图片
# 1. Check the actual file format (extension may lie)
file /path/to/image.png
import base64
from pathlib import Path
# 2. Read and encode
img_path = Path("/path/to/image.png")
# Use "image/jpeg" if `file` command says JPEG, else "image/png"
mime = "image/jpeg" # or "image/png"
b64 = base64.b64encode(img_path.read_bytes()).decode()
data_uri = f"data:{mime};base64,{b64}"
# 3. Inject into HTML template as a Python variable — never via shell
html = f"""
<div style="position:relative;width:100%;height:100%;">
<img src="{data_uri}"
style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;">
<div style="position:absolute;inset:0;background:rgba(255,255,255,0.35);z-index:1;"></div>
</div>
"""
Path("/home/claude/carousel.html").write_text(html, encoding="utf-8")
将图片用作幻灯片背景(最常见的用法)
<img src="{data_uri}"
style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;">
<div style="position:absolute;inset:0;background:rgba(255,255,255,0.35);z-index:1;"></div>
对于深色幻灯片,请改用 rgba(0,0,0,0.45) 作为叠加层。
应避免的常见图片错误
| 错误 | 后果 | 修复方法 |
|---|---|---|
<img src="gestante.png"> | 图片损坏——相对路径仅在 HTML 和图片位于同一文件夹时有效 | 始终使用 base64 data: URI |
内联使用带有 1.5MB base64 的 background: url('data:...') | 浏览器解析器崩溃,1.3M token 上下文 | 使用带有 object-fit:cover 的 <img> 标签 |
通过 Shell echo 或 heredoc 生成 HTML | base64 中的 $ 和反引号会被插入,破坏字符串 | 始终使用 Python Path.write_text() |
认定 .png 扩展名就代表 PNG 格式 | 文件可能实际是 JPEG;错误的 MIME 类型会导致渲染失败 | 运行 file 命令检测实际格式 |
步骤 2:推导完整配色系统
根据用户提供的单一品牌主色,生成包含 6 个 token 的完整调色板:
BRAND_PRIMARY = {user's color} // Main accent — progress bar, icons, tags
BRAND_LIGHT = {primary lightened ~20%} // Secondary accent — tags on dark, pills
BRAND_DARK = {primary darkened ~30%} // CTA text, gradient anchor
LIGHT_BG = {warm or cool off-white} // Light slide background (never pure #fff)
LIGHT_BORDER = {slightly darker than LIGHT_BG} // Dividers on light slides
DARK_BG = {near-black with brand tint} // Dark slide background
颜色推导规则:
- LIGHT_BG:与主色协调的浅色灰白色(暖色 → 暖奶油色,冷色 → 冷灰白)
- DARK_BG:带有细微品牌色调的近黑色(暖色 → #1A1918,冷色 → #0F172A)
- LIGHT_BORDER:始终比 LIGHT_BG 深约一个色阶
- 品牌渐变:
linear-gradient(165deg, BRAND_DARK 0%, BRAND_PRIMARY 50%, BRAND_LIGHT 100%)
第 3 步:设置字体排版
根据用户的字体偏好,从 Google Fonts 中选择一种标题字体和一种正文字体。
| 风格 | 标题字体 | 正文字体 |
|---|---|---|
| 编辑风 / 高端 | Playfair Display | DM Sans |
| 现代 / 简洁 | Plus Jakarta Sans (700) | Plus Jakarta Sans (400) |
| 温暖 / 平易近人 | Lora | Nunito Sans |
| 技术感 / 锐利 | Space Grotesk | Space Grotesk |
| 大胆 / 富有表现力 | Fraunces | Outfit |
| 经典 / 值得信赖 | Libre Baskerville | Work Sans |
| 圆润 / 友好 | Bricolage Grotesque | Bricolage Grotesque |
字号比例(所有品牌统一固定):
- 标题:28–34px,字重 600,字间距 -0.3 至 -0.5px,行高 1.1–1.15
- 正文:14px,字重 400,行高 1.5–1.55
- 标签 / 标记:10px,字重 600,字间距 2px,大写
- 步骤编号:标题字体,26px,字重 300
- 小字:11–12px
在所有幻灯片中,通过 CSS 类 .serif(标题字体)和 .sans(正文字体)应用这些样式。
幻灯片 1 — 吸睛开场规则
第一张幻灯片必须在 1 秒内吸引用户停下滚动。优先采用以下形式:
| 开场形式 | 示例 |
|---|---|
| 有争议的观点 | "你用错 AI 了" |
| 数字 + 优势 | "7 款能取代你的设计师的工具" |
| 扎心的问题 | "为什么你的轮播帖一个收藏都没有?" |
| 具体成果 | "这篇帖子在 3 天内带来了 4,200 名粉丝" |
| 反转预期 | "设计投入越多 = 触达越少" |
规则:
- 标题绝不能以品牌名称开头
- 尽可能在第 1 张幻灯片中展示视觉证据(截图、成果、真实数字)
- 开场必须承诺提供后续幻灯片会兑现的价值
幻灯片序列
标准序列(7 张 — 默认)
| # | 类型 | 背景 | 目的 |
|---|---|---|---|
| 1 | 主视觉 | LIGHT_BG | 吸睛开场 — 醒目的陈述、Logo 组合、可选水印 |
| 2 | 问题 | DARK_BG | 痛点 — 哪些地方出了问题、令人沮丧或已经过时 |
| 3 | 解决方案 | 品牌渐变 | 答案 — 解决问题的方法,可选引用 / 提示词框 |
| 4 | 功能 | LIGHT_BG | 你能获得什么 — 带图标的功能列表 |
| 5 | 详情 | DARK_BG | 深入介绍 — 自定义选项、规格、差异化优势 |
| 6 | 操作指南 | LIGHT_BG | 步骤 — 编号工作流或流程 |
| 7 | 行动号召 | 品牌渐变 | 行动号召 — Logo、标语、CTA 按钮。不要添加箭头。进度条显示完整进度。 |
清单序列(5–10 张)
| # | 类型 | 背景 |
|---|---|---|
| 1 | 主视觉 | LIGHT_BG |
| 2–N | 条目 N | LIGHT/DARK 交替 |
| 最后一张 | 行动号召 | 品牌渐变 |
适用于:"X 款工具"、"X 个错误"、"X 条建议"
教程序列(7 张)
| # | 类型 | 背景 |
|---|---|---|
| 1 | 主视觉 | LIGHT_BG |
| 2 | 背景 / 原因 | DARK_BG |
| 3–5 | 步骤 1、2、3 | 交替 |
| 6 | 预期结果 | DARK_BG |
| 7 | 行动号召 | 品牌渐变 |
对比序列(5 张)
| # | 类型 | 背景 |
|---|---|---|
| 1 | 主视觉(说明对比内容) | LIGHT_BG |
| 2 | 选项 A | LIGHT_BG |
| 3 | 选项 B | DARK_BG |
| 4 | 结论 | 品牌渐变 |
| 5 | 行动号召 | DARK_BG |
所有序列的通用规则:
- 以吸睛开场开始 — 第一张幻灯片必须吸引用户停下滚动
- 以品牌渐变背景的行动号召结束 — 不要添加滑动箭头,进度条显示 100%
- 交替使用浅色和深色背景,营造视觉节奏
- 根据主题调整序列 — 并非每个轮播帖都需要包含所有幻灯片
幻灯片架构
格式
- 宽高比:4:5(Instagram 轮播帖标准)
- 每张幻灯片都是独立的 — 所有 UI 元素都直接嵌入图片
- 交替使用 LIGHT_BG 和 DARK_BG 背景,营造视觉节奏
每张幻灯片都必须包含的元素
1. 进度条(每张幻灯片底部)
显示轮播中的位置,并随用户滑动逐渐填充。
- 位置:绝对定位于底部,宽度占满,水平内边距为 28px,底部内边距为 20px
- 轨道:高度为 3px,圆角
- 填充宽度:
((slideIndex + 1) / totalSlides) * 100% - 浅色幻灯片:轨道为
rgba(0,0,0,0.08),填充为BRAND_PRIMARY,计数器为rgba(0,0,0,0.3) - 深色幻灯片:轨道为
rgba(255,255,255,0.12),填充为#fff,计数器为rgba(255,255,255,0.4) - 进度条旁的计数标签:格式为“1/7”,字号为 11px,字重为 500
function progressBar(index, total, isLightSlide) {
const pct = ((index + 1) / total) * 100;
const trackColor = isLightSlide ? 'rgba(0,0,0,0.08)' : 'rgba(255,255,255,0.12)';
const fillColor = isLightSlide ? BRAND_PRIMARY : '#fff'; // use actual BRAND_PRIMARY value
const labelColor = isLightSlide ? 'rgba(0,0,0,0.3)' : 'rgba(255,255,255,0.4)';
return `<div style="position:absolute;bottom:0;left:0;right:0;padding:16px 28px 20px;z-index:10;display:flex;align-items:center;gap:10px;">
<div style="flex:1;height:3px;background:${trackColor};border-radius:2px;overflow:hidden;">
<div style="height:100%;width:${pct}%;background:${fillColor};border-radius:2px;"></div>
</div>
<span style="font-size:11px;color:${labelColor};font-weight:500;">${index + 1}/${total}</span>
</div>`;
}
⚠️ 重要: 渲染前务必将 BRAND_PRIMARY 替换为实际的十六进制值。HTML 输出中不得将其保留为变量名。
2. 滑动箭头(右侧边缘——除最后一张外的每张幻灯片)
低调的箭头符号,引导用户继续滑动。最后一张幻灯片上移除。
- 位置:绝对定位于右侧,高度占满,宽度为 48px
- 背景:从透明到淡色的渐变
- 箭头:24×24 SVG,圆角描边
- 浅色幻灯片:背景为
rgba(0,0,0,0.06),描边为rgba(0,0,0,0.25) - 深色幻灯片:背景为
rgba(255,255,255,0.08),描边为rgba(255,255,255,0.35)
function swipeArrow(isLightSlide) {
const bg = isLightSlide ? 'rgba(0,0,0,0.06)' : 'rgba(255,255,255,0.08)';
const stroke = isLightSlide ? 'rgba(0,0,0,0.25)' : 'rgba(255,255,255,0.35)';
return `<div style="position:absolute;right:0;top:0;bottom:0;width:48px;z-index:9;display:flex;align-items:center;justify-content:center;background:linear-gradient(to right,transparent,${bg});">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M9 6l6 6-6 6" stroke="${stroke}" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>`;
}
可复用组件
删除线胶囊标签
<span style="font-size:11px;padding:5px 12px;border:1px solid rgba(255,255,255,0.1);border-radius:20px;color:#6B6560;text-decoration:line-through;">{Old tool}</span>
标签胶囊
<span style="font-size:11px;padding:5px 12px;background:rgba(255,255,255,0.06);border-radius:20px;color:{BRAND_LIGHT};">{Label}</span>
提示词 / 引言框
<div style="padding:16px;background:rgba(0,0,0,0.15);border-radius:12px;border:1px solid rgba(255,255,255,0.08);">
<p class="sans" style="font-size:13px;color:rgba(255,255,255,0.5);margin-bottom:6px;">{Label}</p>
<p class="serif" style="font-size:15px;color:#fff;font-style:italic;line-height:1.4;">"{Quote text}"</p>
</div>
特性列表
<div style="display:flex;align-items:flex-start;gap:14px;padding:10px 0;border-bottom:1px solid {LIGHT_BORDER};">
<span style="color:{BRAND_PRIMARY};font-size:15px;width:18px;text-align:center;">{icon}</span>
<div>
<span class="sans" style="font-size:14px;font-weight:600;color:{DARK_BG};">{Label}</span>
<span class="sans" style="font-size:12px;color:#8A8580;">{Description}</span>
</div>
</div>
编号步骤
<div style="display:flex;align-items:flex-start;gap:16px;padding:14px 0;border-bottom:1px solid {LIGHT_BORDER};">
<span class="serif" style="font-size:26px;font-weight:300;color:{BRAND_PRIMARY};min-width:34px;line-height:1;">01</span>
<div>
<span class="sans" style="font-size:14px;font-weight:600;color:{DARK_BG};">{Step title}</span>
<span class="sans" style="font-size:12px;color:#8A8580;">{Step description}</span>
</div>
</div>
色板
<div style="width:32px;height:32px;border-radius:8px;background:{color};border:1px solid rgba(255,255,255,0.08);"></div>
CTA 按钮(仅限最后一张幻灯片)
<div style="display:inline-flex;align-items:center;gap:8px;padding:12px 28px;background:{LIGHT_BG};color:{BRAND_DARK};font-family:'{BODY_FONT}',sans-serif;font-weight:600;font-size:14px;border-radius:28px;">
{CTA text}
</div>
标签 / 类别标签
<span class="sans" style="display:inline-block;font-size:10px;font-weight:600;letter-spacing:2px;color:{color};margin-bottom:16px;">{TAG TEXT}</span>
- 浅色幻灯片:
BRAND_PRIMARY - 深色幻灯片:
BRAND_LIGHT - 品牌渐变幻灯片:
rgba(255,255,255,0.6)
Logo 组合(第一张和最后一张幻灯片)
- 如果是 Logo 图标:直径 40px 的圆形(背景为
BRAND_PRIMARY)+ 居中的图标 + 旁边的品牌名称 - 如果是首字母:直径 40px 的圆形,内含白色首字母
- 品牌名称:字号为 13px,字重为 600,字母间距为 0.5px
布局规则
- 内容内边距:标准值为
0 36px - 带进度条且内容底部对齐的幻灯片:使用
0 36px 52px,为进度条留出空间 - 主视觉 / CTA 幻灯片:
justify-content: center - 内容较多的幻灯片:
justify-content: flex-end - 内容不得与进度条重叠——使用
padding-bottom: 52px
Instagram 画框(预览包装器)
在聊天中展示时,请使用 Instagram 风格的画框包装:
- **页眉:**头像(
BRAND_PRIMARY圆形背景 + Logo)+ 用户名 + 副标题 - **视口:**4:5 宽高比,可滑动 / 拖动的轨道,包含所有幻灯片
- **圆点:**视口下方的小圆点指示器
- **操作:**心形、评论、分享、收藏 SVG 图标
- **说明文字:**用户名 + 简短描述 + “2 HOURS AGO” 时间戳
预览中需包含基于指针的滑动 / 拖动交互。幻灯片仍是可独立导出的图片。
重要:.ig-frame 的宽度必须正好为 420px。轮播视口尺寸为 420×525px。切勿更改此宽度——导出依赖此设置。
审核流程
务必遵循此流程。未经批准,绝不可直接导出。
- 先生成 HTML 预览——绝不可直接跳到导出
- 展示预览并询问:“导出前哪些幻灯片需要调整?”
- 仅修改用户指出的幻灯片——除非设计方向发生根本变化,否则不要重新生成整个轮播
- 只有在用户明确确认批准后(例如“可以导出”“已批准”“好的”)才能继续导出
将幻灯片导出为适用于 Instagram 的 PNG 图片
用户批准轮播预览后,将每张幻灯片单独导出为 1080×1350px PNG。
关键导出规则
-
使用 Python 生成 HTML——绝不可使用带变量插值的 shell 脚本。务必使用
Path.write_text()或open().write()。 -
将图片嵌入为 base64——所有用户上传的图片都必须进行 base64 编码,并作为
data:image/jpeg;base64,...URI。使用file命令检查实际文件格式——.png扩展名的文件可能实际包含 JPEG 数据。 -
保持 420px 的布局宽度——使用 Playwright 的
device_scale_factor将输出放大至 1080px,而不更改布局视口。
安装 Playwright(仅在需要时)
运行导出脚本前,先检查是否已安装,仅在缺少时安装:
python3 -c "import playwright" 2>/dev/null || pip3 install playwright
python3 -c "from playwright.sync_api import sync_playwright; sync_playwright().__enter__().chromium" 2>/dev/null || python3 -m playwright install chromium
导出脚本
import asyncio
from pathlib import Path
from playwright.async_api import async_playwright
INPUT_HTML = Path("/path/to/carousel.html")
OUTPUT_DIR = Path("/path/to/output/slides")
OUTPUT_DIR.mkdir(exist_ok=True)
TOTAL_SLIDES = 7 # Update to match your carousel
VIEW_W = 420
VIEW_H = 525
SCALE = 1080 / 420 # = 2.5714...
async def export_slides():
async with async_playwright() as p:
browser = await p.chromium.launch()
page = await browser.new_page(
viewport={"width": VIEW_W, "height": VIEW_H},
device_scale_factor=SCALE,
)
html_content = INPUT_HTML.read_text(encoding="utf-8")
await page.set_content(html_content, wait_until="networkidle")
await page.wait_for_timeout(3000) # Wait for Google Fonts to load
# Hide IG frame chrome, show only the slide viewport
await page.evaluate("""() => {
document.querySelectorAll('.ig-header,.ig-dots,.ig-actions,.ig-caption')
.forEach(el => el.style.display='none');
const frame = document.querySelector('.ig-frame');
frame.style.cssText = 'width:420px;height:525px;max-width:none;border-radius:0;box-shadow:none;overflow:hidden;margin:0;';
const viewport = document.querySelector('.carousel-viewport');
viewport.style.cssText = 'width:420px;height:525px;aspect-ratio:unset;overflow:hidden;cursor:default;';
document.body.style.cssText = 'padding:0;margin:0;display:block;overflow:hidden;';
}""")
await page.wait_for_timeout(500)
for i in range(TOTAL_SLIDES):
await page.evaluate("""(idx) => {
const track = document.querySelector('.carousel-track');
track.style.transition = 'none';
track.style.transform = 'translateX(' + (-idx * 420) + 'px)';
}""", i)
await page.wait_for_timeout(400)
await page.screenshot(
path=str(OUTPUT_DIR / f"slide_{i+1}.png"),
clip={"x": 0, "y": 0, "width": VIEW_W, "height": VIEW_H}
)
print(f"Exported slide {i+1}/{TOTAL_SLIDES}")
await browser.close()
asyncio.run(export_slides())
原理说明
device_scale_factor=2.5714以高 DPI 渲染——一个 420px 的元素在输出中会变成 1080px。布局仍保持 420px。clip仅截取轮播视口,不包含浏览器边框。wait_for_timeout(3000)为 Google Fonts 留出加载时间。track.style.transition = 'none'禁用滑动动画,让幻灯片立即切换。
应避免的常见导出错误
| 错误 | 问题 | 修复方法 |
|---|---|---|
| 将视口设为 1080×1350 | 布局会重新排版——字体变得很小,间距也会错乱 | 保持视口为 420×525,使用 device_scale_factor |
| 使用 Shell 脚本生成 HTML | $ 符号和反引号会被插值 | 始终使用 Python 生成 HTML |
| 未等待字体加载 | 标题会以系统备用字体渲染 | 页面加载后调用 wait_for_timeout(3000) |
| 未隐藏 IG 边框元素 | 导出内容会包含页眉、圆点和说明文字 | 隐藏 .ig-header,.ig-dots,.ig-actions,.ig-caption |
更改 .ig-frame 的宽度 | 整体布局会发生偏移 | 始终保持宽度为精确的 420px |
在 CSS 中将 BRAND_PRIMARY 保留为变量名 | 颜色会显示为无效或不可见 | 始终将实际的十六进制值插入 HTML |
设计原则
- 每张幻灯片都可直接导出——箭头和进度条都是幻灯片图像的一部分
- 明暗交替——在滑动浏览时营造视觉节奏
- 标题与正文的字体搭配——标题使用展示字体以增强冲击力,正文使用易读字体
- 源自品牌的配色方案——所有颜色都源于一种主色,保持整体协调
- 渐进式呈现——进度条逐渐填充,箭头引导用户继续浏览
- 最后一张幻灯片特别设计——不显示箭头,进度条填满,并提供明确的 CTA
- 组件保持一致——所有幻灯片使用相同的标签样式、列表样式和间距
- 内容留白避开界面元素——正文不会与进度条或箭头重叠
- 开篇先抓住注意力——第 1 张幻灯片旨在让用户停下滑动,而不是介绍品牌
- 快速迭代——展示预览,针对具体幻灯片进行修复,不要从头重做