最近关于 自动化社交图片 的讨论很多。 GitHub 创建了自己的社交图片。 一个 WordPress 插件已被 Jetpack 收购。 显然大家都很感兴趣! 像 Ryan Filler 和 Zach Leatherman 这样的开发者已经在他们的网站上实现了社交图片。 他们不得不自己编写很多代码。 但是,形势正在发生变化,一些工具可以简化这个流程。
在本教程中,我们将使用 HTML 和 CSS 创建自己的自动化社交图片,并将它们集成到一个 Eleventy 博客中(主要通过配置),并将我们的网站部署到 Netlify。
社交图片是什么?
在 HTML 的 <head>
部分,我们插入一些 Open Graph 标记
<meta property="og:title" content="The blue sky strategy" />
<meta property="og:description" content="Less clouds, more blue" />
<meta property="og:image" content="/sky-with-clouds.jpg" />
当我们在 Facebook 上分享此页面时,我们和我们的朋友会看到这个

LinkedIn、Twitter、WhatsApp、Slack、Discord、iMessage…… 所有这些网站的行为几乎相同:它们提供一个带有链接的视觉“卡片”,为它提供更多空间和上下文。
Twitter 拥有自己的标记集,即 Twitter Cards,但它们非常相似。 当 Twitter 找不到它们时,它会回退到 Open Graph。
我们的页面自然会包含标题和描述。 但是,在上面的截图中,与图片(天空和云朵)所占空间和吸引的注意力相比,它们非常小,更不用说可点击区域的大小了。 这就是社交图片的力量。 当分享链接时,很容易理解这些图片所能带来的影响。
从级别 0 到级别 3
并非所有的社交图片都是平等的。 这些不是官方术语,但让我们考虑一下这些社交图片卡片的影响力级别的编号“等级”。
级别 0
最基本的社交图片是没有任何图片。 链接可能会在内容的海洋中迷失,可点击区域很小,没有多少视觉效果。

级别 1
一种经典的技术是创建一个全站社交图片。 虽然这种解决方案似乎提供了良好的结果与工作量比率,但有人可能会争辩说,这比没有图片还要糟糕。 当然,我们可以获得一些关注,但反应可能是负面的,尤其是当人们看到许多指向该网站的链接,它们看起来都一样时。 它可能会让人感到重复和多余。

级别 2
下一级是博客和媒体网站的标准:帖子的社交图片。 每篇文章都有自己的特色图片,它们彼此不同。 对于新闻网站,这种做法是完全合理的,因为图片是对页面内容的补充。 这里潜在的缺点是,需要为每篇发布的文章寻找和创建艺术作品,这需要付出努力。
这可能会导致一些懒惰。 我们都见过一些明显是库存照片的图片。 它可能会吸引注意力,但可能不是你真正想要的注意力。

级别 3
最后一级:每页、内容丰富、有意义的社交图片。 CSS-Tricks 正在做这件事。 该团队的社交图片是品牌的。 它们共享相同的布局。 它们提到了文章标题,以及作者的姓名和个人资料图片,这是普通标题和描述无法显示的。 它们引人注目,令人难忘。

这种方法有一个显而易见的要求:自动化。 毫无疑问,要为每个可能的链接创建唯一的图片。 只想一想这需要多少工作量。 我们需要一些编程解决方案来帮助我们完成繁重的任务。
让我们开始一个博客,它拥有带有独特社交图片的博文
为了给自己一个很好的借口(以及沙盒)来构建独特的社交图片,我们将快速搭建一个博客。 当我写完并发布一篇博客文章后,我会按照一个快速的两个步骤流程进行操作
- 编写并发布文章
- 将已发布的 URL 发布到我的社交网络账户
这时,社交图片必须大放异彩。 我们希望让我们的博客尽可能被注意到。 但这不是我们的唯一目标。 这个博客应该树立我们的个人品牌。 我们希望我们的朋友、同事和粉丝在看到我们的社交帖子时能想起我们。 我们想要一些可重复、可识别、代表我们自己的东西。
创建博客是一项非常繁重的任务。 虽然自动化的社交图片很酷,但花太多时间在它们上面是不明智的。(Chris 在 2020 年底得出了 同样的结论)。 因此,为了提高效率,我们正在创建一个 Eleventy 网站。 Eleventy 是一个简单的静态网站生成器。 让我们使用一个 入门项目,而不是从头开始。 事实上,让我们选择第一个,eleventy-base-blog。

访问 eleventy-base-blog GitHub 页面 并将其用作模板

让我们创建仓库,并设置仓库名称和描述。 我们可以将其设为公开或私有,这并不重要。
接下来,我们将在本地克隆我们的仓库,安装包并运行网站
git clone [your repo URL]
cd my-demo-blog ### Or whatever you named it
npm install
npm run serve
我们的网站运行在 http://localhost:8080
上。
现在让我们部署它。 Netlify 使这成为一项非常快速的(并且免费!)任务。(哦,剧透一下:我们的社交图片自动化依赖于一个 Netlify 函数。)
所以,让我们 转到 Netlify 并创建一个账户,如果你还没有的话。 无论如何,创建一个新网站

完成允许 Netlify 访问博客仓库的过程。

Netlify 部署我们的网站

大约一分钟后,博客就会部署

一个图片模板统治一切
我们的社交图片将基于一个图片模板。 为了设计这个模板,我们将使用我们已经了解和喜欢的技术:HTML 和 CSS。 HTML 不会自动转换为图片,但有一些工具可以做到这一点,最著名的是使用 Puppeteer 的无头 Chrome。
不过,我们没有自己构建社交图片堆栈,而是使用了 Resoc 图片模板开发工具包。因此,从项目根目录,我们可以在终端运行以下命令:
npx itdk init resoc-templates/default -m title-description
此命令会在 resoc-templates/default
目录中创建一个新的图片模板。它还会在新浏览器窗口中打开。

我们可以直接使用此模板,但这只能让我们在“影响力”范围内达到第二级。我们需要做些什么才能让它达到第三级,并与 CSS-Tricks 模板相匹配呢?
- 页面标题右对齐,左侧留一些负空间。
- 底部有一个页脚,包含由我们将要在整个博客中使用的两种颜色构成的背景渐变。
- 帖子作者的姓名和个人资料图片。
如果我们回到浏览器,可以在模板查看器的“参数”面板中看到模板需要两个参数:标题和描述。这正是我们在终端运行 -m title-description
时选择的模板,就像我们设置好一切一样。但我们可以通过编辑 resoc-templates/default/resoc.manifest.json
添加更多参数。具体来说,我们可以删除第二个参数,得到:
{
"partials": {
"content": "./content.html.mustache",
"styles": "./styles.css.mustache"
},
"parameters": [
{
"name": "title",
"type": "text",
"demoValue": "A picture is worth a thousand words"
}
]
}
查看器在浏览器中反映了更改。

现在是设计图片本身的时候了,我们可以在 resoc-templates/default/content.html.mustache
中进行设计。
<div class="wrapper">
<main>
<h1>{{ title }}</h1>
</main>
<footer>
<img src="profil-pic.jpg" />
<h2>Philippe Bernard</h2>
</footer>
</div>
这只是一般的 HTML 代码。好吧,除了 {{ title }}
。这是 Mustache,Resoc 用于将参数值注入模板的模板引擎。我们甚至可以输入一些文本到“标题”字段中,看看它是否起作用。

查看预览,我们会注意到缺少一个图片,profil-pic.jpg
。将你最好的个人资料图片复制到 resoc-templates/default/profil-pic.jpg
。

现在是编写 resoc-templates/default/styles.css.mustache
中的 CSS 代码的时候了。这篇文章的重点不是如何设置模板样式,而是我最终使用的方法:
@import url('https://fonts.googleapis.com/css2?family=Anton&family=Raleway&display=swap');
.wrapper {
display: flex;
flex-direction: column;
}
main {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
position: relative;
}
h1 {
text-align: right;
margin: 2vh 3vw 10vh 20vw;
background: rgb(11,35,238);
background: linear-gradient(90deg, rgba(11,35,238,1) 0%, rgba(246,52,12,1) 100%);
-webkit-text-fill-color: transparent;
-webkit-background-clip: text;
font-family: 'Anton';
font-size: 14vh;
text-transform: uppercase;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
h2 {
color: white;
margin: 0;
font-family: 'Raleway';
font-size: 10vh;
}
footer {
flex: 0 0;
min-height: 20vh;
display: flex;
align-items: center;
background: rgb(11,35,238);
background: linear-gradient(90deg, rgba(11,35,238,1) 0%, rgba(246,52,12,1) 100%);
padding: 2vh 3vw 2vh 3vw;
}
footer img {
width: auto;
height: 100%;
border-radius: 50%;
margin-right: 3vw;
}
大多数尺寸依赖于 vw
和 vh
单位,以帮助预测模板可能渲染的各种上下文。我们将遵循 Facebook 的推荐,即 1200×630。另一方面,Twitter Cards 的尺寸不同。我们可以以低分辨率渲染图片,比如 600×315,但我们还是选择 1200×630,这样我们只需要使用像素进行操作。
查看器会以 1200×630 的尺寸渲染 Facebook 预览,并将其缩放到适合屏幕的大小。如果预览符合你的预期,那么实际的 Open Graph 图片也会符合预期。
到目前为止,模板已经满足了我们的需求。

图片怎么样?
在完成模板之前,还有一件小事需要添加。我们的一些博客文章会有图片,但并非所有文章都有。在帖子没有图片的情况下,使用图片填充左侧的空间会很酷。
这是一个新的模板参数,因此我们需要再次更新 resoc-templates/default/resoc.manifest.json
。
{
"partials": {
"content": "./content.html.mustache",
"styles": "./styles.css.mustache"
},
"parameters": [
{
"name": "title",
"type": "text",
"demoValue": "A picture is worth a thousand words"
},
{
"name": "sideImage",
"type": "imageUrl",
"demoValue": "https://resoc.io/assets/img/demo/photos/pexels-photo-371589.jpeg"
}
]
}
让我们在 resoc-templates/default/content.html.mustache
中声明一个额外的 div
。
<div class="wrapper">
<main>
{{#sideImage}}
<div class="sideImage"></div>
{{/sideImage}}
<h1>{{ title }}</h1>
</main>
<footer>
<img src="profil-pic.jpg" />
<h2>Philippe Bernard</h2>
</footer>
</div>
新的 {{#sideImage}} ... {{/sideImage}}
语法是一个 Mustache 部分。只有在定义了 sideImage
参数时才会出现。
我们需要一些额外的 CSS 来处理图片。请注意,我们可以在此处使用 Mustache 语法为特定帖子插入 background-image
值。以下是我在 resoc-templates/default/styles.css.mustache
文件中处理此问题的方式:
{{#sideImage}}
.sideImage {
position: absolute;
width: 100%;
height: 100%;
background-image: url({{{ sideImage }}});
background-repeat: no-repeat;
background-size: auto 150vh;
background-position: -35vw 0vh;
-webkit-mask-image: linear-gradient(45deg, rgba(0,0,0,0.5), transparent 40%);
}
{{/sideImage}}
我们的模板看起来很棒!

我们提交了模板。
git add resoc-templates
git commit -m "Resoc image template"
在我们自动化社交图片之前,让我们手动生成一个,作为预告。查看器提供了用于生成对应图片的命令行,以供我们测试。

复制它,从终端运行它,并打开 output-image.jpg
。

社交图片自动化
好的,我们通过命令行创建了一张图片。现在我们应该怎么做?像博客上的页面数量一样调用它?这听起来像是一项无聊的任务,而且这种方法存在一个更深层次的问题:时间。即使创建一张图片只需要两秒钟,我们也可以将它乘以页面数量,很容易看出工作量会越来越大。
原始的 Eleventy 博客模板几乎是瞬间生成的,但我们应该等待一分钟才能生成像社交图片这样微不足道的东西吗?这是不可接受的。
我们不会在构建时执行此任务,而是使用 Netlify Function 和 Netlify 按需构建器 将其延迟到后期。实际上,我们并不是直接处理 Netlify Function —— 一个 Eleventy 插件会为我们处理这个问题。
现在让我们安装它。我们可以添加 Resoc Eleventy 社交图片插件,以及它的配套 Netlify 插件,使用以下命令:
npm install --save-dev @resoc/eleventy-plugin-social-image @resoc/netlify-plugin-social-image
为什么有两个插件?第一个插件专门用于 Eleventy,而第二个插件是框架无关的(例如,它可以 用于 Next.js)。
编辑项目根目录中的 .eleventy.js
文件,以便导入插件。
const pluginResoc = require("@resoc/eleventy-plugin-social-image");
在 .eleventy.js
文件的顶部附近配置它,紧接在现有的 eleventyConfig.addPlugin
之后:
eleventyConfig.addPlugin(pluginResoc, {
templatesDir: 'resoc-templates',
patchNetlifyToml: true
});
templatesDir
是我们存储图片模板的位置。patchNetlifyToml
要求插件为我们配置 netlify.toml
中的 @resoc/netlify-plugin-social-image
。
我们希望所有页面都拥有自动化的社交图片。因此,让我们打开主模板 _includes/layouts/base.njk
,并在文件顶部附近添加以下代码:
{% set socialImageUrl %}
{%- resoc
template = "default",
slug = (title or metadata.title) | slug,
values = {
title: title or metadata.title,
sideImage: featuredImage
}
-%}
{% endset %}
这声明了一个名为 socialImageUrl
的新变量。此变量的内容由 resoc
短代码提供,它接受三个参数:
template
是我们模板的子目录(位于resoc-templates/default
中)。slug
用于构建社交图片 URL(例如/social-images/brand-new-post.jpg
)。我们将页面标题进行 slug 化,以提供一个唯一且可共享的 URL。values
是内容,如resoc-templates/default/resoc.manifest.json
中定义。title
很明显,因为页面已经有一个标题。sideImage
设置为名为featuredImage
的元数据,我们将在插图页面中定义它。
现在我们可以打开 _includes/layouts/base.njk
,将光标放在 <head>
中,添加一些新的标记来填充所有这些内容。
<meta property="og:title" content="{{ title or metadata.title }}"/>
<meta property="og:description" content="{{ description or metadata.description }}"/>
<meta property="og:image" content="{{ socialImageUrl }}"/>
<meta property="og:image:width" content="1200"/>
<meta property="og:image:height" content="630"/>
标题和描述标记与现有的 <title>
和 <meta name="description">
类似。我们直接使用 socialImageUrl
作为 og:image
元数据。我们还提供社交图片尺寸以完善整体效果。
社交图片自动化已准备就绪!
让我们部署它
当我们再次部署博客时,所有页面都会显示模板的纯文本版本。要查看完整版本,我们需要为现有页面分配一张图片。这需要我们编辑其中一篇帖子(我已经创建了四篇帖子,正在编辑第四篇,posts/fourthpost.md
),因此在现有元数据之后有一个 featuredImage
条目:
---
title: This is my fourth post.
description: This is a post on My Blog about touchpoints and circling wagons.
date: 2018-09-30
tags: second tag
layout: layouts/post.njk
featuredImage: https://resoc.io/assets/img/demo/photos/pexels-pixabay-459653.jpg
---
使用外部 URL 在这里已经足够了,但通常情况下,我们会将图片放在 Eleventy 的 img
目录中,并在 _includes/layouts/base.njk
中一次性提供基本 URL。
再次构建站点。
npm run build
运行 git status
时,我们可能会注意到除了我们自己编辑的文件之外,还有两个修改过的文件。在 .gitignore
中,插件添加了 resoc-image-data.json
。此文件存储 Netlify 插件内部使用的社交图片数据,netlify.toml
现在包含 Netlify 插件配置。
部署时间!
git commit -a -m "Automated social images"
git push
Netlify 会收到通知并部署站点。最新版本上线后,将主页分享到某个地方(例如,将其发送到你的 Slack 或使用 Facebook 调试器)。以下是主页的社交卡片的样子,它不包含图片:

以下是包含图片的帖子的社交卡片样子:

完美!
结论
到目前为止,社交图片自动化主要是开发者愿意探索和尝试各种不同的想法和方法,有些简单,有些困难。我们保持了相对简单。
只需几行代码,我们就能快速在基于 Eleventy 并托管在 Netlify 上的博客上设置社交图片自动化。我们花费了最多时间的部分是图片模板,但这不是问题。有了查看器和 Mustache 的集成,我们专注于我们所知、所爱、所重视的东西:网页设计。
希望像 Resoc 图片模板开发工具包 及其相关工具这样的工具能帮助社交图片自动化从一个利基爱好转变为主流。
很棒的文章。谢谢。
谢谢 Raj!
您好,感谢您的出色工作。我在实现此功能时遇到了一些问题,后来我通过 fcbk 调试器发现 og: 元标签应该定义为“property”而不是“name”。这解决了我的问题,不知道其他社交网络是否使用相同的约定。
嗨 Kuba,感谢您的反馈!您说得完全正确,很抱歉发生了这个错误!我已经在几分钟前修复了。
奇怪的是,演示网站存在这个问题,但 FB 和 Slack 仍然支持它。这并不完全令人意外:“节目必须继续”通常是网络上的一种做法。
您好!
感谢您提供如此出色的省时工具。
我的问题是,是否有可能为其他社交媒体服务添加另一个用于正方形尺寸或垂直尺寸的预览?
谢谢,祝您度过美好的一天!