W3C 的 CSS 工作组经常为我们提供出色的 CSS 功能供我们实验。 有时我们偶然发现一些非常酷的东西,让我们脸上露出笑容,但它很快就消失了,因为我们认为,“这很棒,但我该怎么用它呢?” element()
函数对我来说就是这样。 这是一个 CSS 函数,它获取页面上的元素并将其呈现为要显示在屏幕上的图像。 令人印象深刻,但有点古怪。
下面是一个简单的 示例,说明它的工作原理。 它目前仅在 Firefox 中受支持,我知道这很糟糕。 但是请坚持下去,看看它有多有用。
<div id="ele">
<p>Hello World! how're you?<br>I'm not doing that<br>great. Got a cold 😷</p>
</div>
<div id="eleImg"></div>
#eleImg {
background: -moz-element(#ele) no-repeat center / contain; /* vendor prefixed */
}
element()
函数(带浏览器前缀)采用元素的 id
值,将其转换为图像。 输出看起来与屏幕上给定元素的外观相同。

当我想到 element()
的输出时,我想到的是 预览 这个词。 我认为这是能够最大限度地利用它的用例类型:我们可以预览元素,然后再将其显示在页面上。 例如,幻灯片中的下一张幻灯片,隐藏的选项卡或图库中的下一张照片。 或者……一个小地图!
小地图 是长文档或页面的迷你预览,通常显示在屏幕的一侧或另一侧,用于导航到该文档上的相应点。
您可能在 Sublime Text 等代码编辑器中看到过它。

CSS element()
在制作小地图的“预览”部分方面非常有用。
下面是小地图的演示,之后我们将逐步介绍其代码。 但是,我建议您查看 完整页面演示,因为小地图对于 长 文档(在 大 屏幕上)非常有用。
如果您使用的是智能手机,请记住,根据相对论,小地图将在迷你屏幕中变得超级迷你; 而且不,这实际上不是相对论的真实说法,但您明白我的意思。
查看 Pen 使用 CSS element() 和 HTML 输入范围的小地图,由 Preethi Sam (@rpsthecoder) 在 CodePen 上制作。

如果您正在为整个页面设计小地图(例如,用于单页网站),则可以使用文档主体元素作为图像。 否则,将主要内容元素(例如我的演示中的文章)作为目标也可以。
<div id="minimap"></div>
<div id="article"> <!-- content --> </div>
#minimap {
background: rgba(254,213,70,.1) -moz-element(#article) no-repeat center / contain;
position: fixed; right: 10px; top: 10px; /* more style */
}
对于小地图的背景图像,我们将文章的 id
作为 element()
的参数提供,并且与大多数背景图像一样,它被设置为不重复 (no-repeat
) 并适合内部 (contain
) 以及显示位置的框的中心 (center
)。
小地图也被固定在视窗的右上角。
准备好背景后,我们可以在它上面添加一个滑块,它将用于操作小地图滚动。 对于滑块,我选择了 input: range
,即原始、简单且普通的 HTML 滑块。
<div id="minimap">
<input id="minimap-range" type="range" max="100" value="0">
</div>
#minimap-range {
/* Rotating the default horizontal slider to vertical */
transform: translateY(-100%) rotate(90deg);
transform-origin: bottom left;
background-color: transparent; /* more style */
}
#minimap-range::-moz-range-thumb {
background-color: dodgerblue;
cursor: pointer; /* more style */
}
#minimap-range::-moz-range-track{
background-color: transparent;
}
不是 完全 不复杂,因为它确实需要一些调整。 我将滑块竖直旋转,以匹配小地图,并对其伪元素(特别是拇指和轨道)应用了一些样式,以替换其默认样式。 再次,由于我们正在处理有限的支持,因此我们只关心 Firefox。
剩下的就是将滑块的值与页面上相应的滚动点关联,当用户更改值时,该点将被调用。 这需要一些 JavaScript,看起来像这样
onload = () => {
const minimapRange = document.querySelector("#minimap-range");
const minimap = document.querySelector("#minimap");
const article = document.querySelector("#article");
const $ = getComputedStyle.bind();
// Get the minimap range width multiplied by the article height, then divide by the article width, all in pixels.
minimapRange.style.width = minimap.style.height =
parseInt($(minimapRange).width) * parseInt($(article).height) / parseInt($(article).width) + "px";
// When the range changes, scroll to the relative percentage of the article height
minimapRange.onchange = evt =>
scrollTo(0, parseInt($(article).height) * (evt.target.value / 100));
};
美元符号 ($
) 仅仅是 getComputedStyle()
的别名,这是获取元素 CSS 值的方法。
值得注意的是,小地图的宽度已在 CSS 中设置,因此我们实际上只需要计算其高度。 因此,我们正在处理小地图的高度和滑块的宽度,因为请记住,滑块实际上是向上旋转的。
以下是脚本中方程式的确定方式,从变量开始
- x1 = 小地图的高度(以及其中滑块的宽度)
- y1 = 小地图的宽度
- x2 = 文章的高度
- y2 = 文章的宽度
x1/y1 = x2/y2
x1 = y1 * x2/y2
height of minimap = width of minimap * height of article / width of article
并且,当滑块的值发生变化 (minimapRange.onchange
) 时,就会调用 ScrollTo()
方法,将页面滚动到文章上的相应值。 💥
我们需要回退!
显然,如果我们现在使用它,element()
将有很多时候不受支持,因此我们可能希望在这些情况下隐藏小地图。
我们在 CSS 中检查功能支持
@supports (background: element(#article)) or (background: -moz-element(#article)){
/* fallback style */
}
…或在 JavaScript 中
if(!CSS.supports('(background: element(#article)) or (background: -moz-element(#article))')){
/* fallback code */
}
如果您不介意背景图像缺失,那么您仍然可以保留滑块并对其应用不同的样式。
还有其他一些巧妙的方法来制作在野外飘浮的小地图(并且具有更多浏览器支持)。 这是一个由 Shaw 制作的 很棒的 Pen
查看 Pen
迷你地图进度跟踪器和滚动控制,由 Shaw (@shshaw) 制作。
在 CodePen 上。
还有一些工具,如 pagemap 和 xivimap 可以提供帮助。 element()
函数目前在 W3C 的 CSS 图像值和替换内容模块级别 4 中进行了规范。 绝对值得阅读,以充分了解其背后的意图和思考。
这些浏览器支持数据来自 Caniuse,其中包含更多详细信息。 数字表示浏览器从该版本开始支持该功能。
桌面
Chrome | Firefox | IE | Edge | Safari |
---|---|---|---|---|
否 | 4* | 否 | 否 | 否 |
移动/平板电脑
Android Chrome | Android Firefox | Android | iOS Safari |
---|---|---|---|
否 | 127* | 否 | 否 |
嘘! 你试过在 演示 中选择文章文本吗? 看看小地图上发生了什么。 😉
它在另一个方面也非常有用 - 模糊叠加。
当图像在捕获的元素内部使用时会发生什么?
宇宙爆炸了。
太棒了! 我以前听说过 element(),但我从未实现它,因为我想不出什么好的用例。 我很喜欢那个小地图!
我编辑了这个笔,在 iframe 中嵌入了一个 Youtube 视频。 它不仅有效,而且结果非常流畅,没有明显的延迟!