几天前,我在为一个客户项目工作,想要在<img>
上创建特定的效果。你看,背景图像可以通过background-attachment: fixed;
轻松实现我想要的效果。有了它,背景图像会保持在原位,即使页面滚动也不会移动。它并不经常使用,因此这种效果看起来可能不寻常且醒目,尤其是在谨慎使用时。
目录
我花了一些时间才弄清楚如何仅使用内联图像而不是 CSS 背景图像来实现相同的效果。这是一个演示效果的视频
上面演示的代码 在此 Git 仓库中可用。请注意,这是一个 Next.js 项目。稍后我们会提供一个使用原始 HTML 的 CodePen 示例。
<img>
而不是background-image
?
为什么使用在我的项目中,我想要这样做的原因有很多
- 更容易延迟加载(例如
<img loading="lazy"… >
)。 - 由于
alt
文本,它提供了更好的 SEO(更不用说可访问性了)。 - 可以 使用
srcset
/sizes
来提高加载性能。 - 可以 使用
<picture>
标签 为用户的浏览器选择最佳图像尺寸和格式。 - 它允许用户下载保存图像(无需使用 DevTools)。
总的来说,在可以使用的情况下最好使用图像标签,特别是如果图像可以被视为内容而不是装饰。因此,我最终使用了一种使用 CSS clip-path
的技术。我们稍后会讲到这一点,在我们首先查看background-image
方法以对这两种方法进行并排比较之后。
background-image
1. 使用 CSS 这是实现固定滚动效果的“原始”方法。这是 CSS 代码
.hero-section {
background-image: url("nice_bg_image.jpg");
background-repeat: no-repeat;
background-size: cover;
background-position: center;
background-attachment: fixed;
}
但正如我们刚刚看到的,这种方法在某些情况下并不理想,因为它依赖于 CSS background-image
属性来调用和加载图像。这意味着图像在技术上不被视为内容,因此屏幕阅读器无法识别。如果我们使用的是作为内容一部分的图像,那么我们确实应该使其可访问,以便将其像内容一样而不是像装饰一样使用。
否则,此技术效果很好,但仅在图像跨越视口的整个宽度和/或居中时才有效。如果您在页面右侧或左侧有一个图像(如示例所示),您会遇到很多定位问题,因为background-position
相对于视口中心。
修复它需要一些媒体查询来确保它在所有设备上都正确定位。
clip-path
技巧
2. 对内联图像使用StackOverflow 上的某人 分享了这个clip-path
技巧,它能很好地完成工作。您还可以继续使用<img>
标签,如上所述,这在某些情况下可能是有利的,尤其是在图像作为内容的一部分而不是纯装饰的情况下。
这是技巧
.image-container {
position: relative;
height: 200px;
clip-path: inset(0);
}
.image {
object-fit: cover;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
查看实际效果
现在,在我们急于将此代码片段粘贴到任何地方之前,它也存在自身的一些缺点。例如,对于如此简单的效果,我觉得代码有点冗长。但更重要的是,使用clip-path
也有一些影响。例如,我不能像在前面的示例中那样简单地添加border-radius: 10px;
来圆化图像的角。这行不通,它需要从裁剪路径本身创建圆角。
另一个例子:我不知道如何在clip-path
中定位图像。同样,这可能是非常了解clip-path
并将其绘制到所需位置,或根据需要提前裁剪图像本身的问题。
还有更好的方法吗?
就我个人而言,我放弃了在内联图像上使用固定滚动效果,并回到了使用 CSS 背景图像,我知道这有点限制性。
您是否尝试过实现这一点,特别是使用内联图像,并很好地管理它?我很乐意听到您的想法!
你好,
第一种方法有一个非常丑陋的缺陷(参见:https://bit.ly/32Y61HX)
第二种方法难以理解(我是高级用户,但真的不知道 unset(0) 是什么……)
使用 BG 图像的标准方法更易读且更好;)
Inset 实际上并不高级。
它是 CSS 简写,而不是编写 top、bottom、left 和 right。
您可以在此处了解更多信息
https://mdn.org.cn/en-US/docs/Web/CSS/inset
在撰写本文时,我们也遇到过一次这种缺陷。我个人认为这可能是 CodePen 相关的问题。在真实环境中,我从未见过图像发生这种扭曲。
顺便说一句 - background-attachment:fixed 由于错误在 Safari 或 iOS 中不起作用
您完全正确@Thomas。它在 Mac Safari 上运行良好,但似乎在 IOS Safari 上不受支持。我实际上并不知道这一点。谢谢!
似乎一种廉价的方法(带有一些额外的 DOM)是用 div 包装该标签。使用
opacity
隐藏图像而不更改语义/SEO。然后在包装器上设置背景图像我没想到这一点。我想知道这样做有什么缺点吗?
您还可以通过使用
object-position。
将 div 替换为 img,保留类并添加一行 css。
固定背景很棒,我使用它们已经几十年了,但要记住的一件事是 background image 属性仅用于装饰目的,它不打算像内联图像那样传达重要信息。因此,您无法真正从 WCAG 方面使背景图像更易访问,但您当然可以使其更难访问(https://www.w3.org/TR/WCAG20-TECHS/F3.html)。
虽然它没有特别介绍背景图片,但可能值得阅读一下https://www.w3.org/WAI/tutorials/images/中的一些原则,关于装饰性图片等,有助于解释为什么有些图片需要比其他图片更具信息性的描述。
最近我一直在尝试将固定的渐变背景与覆盖不同区域的纯色和轻微透明的内容蒙版结合起来,固定效果如果做好会非常棒,但要做到恰到好处可能很棘手。但这就像在打开一个装满虫子的潘多拉魔盒的同时掉进了兔子洞,一旦你看到了可能性,你就会开始尝试在不需要的地方创造复杂性。所以我的唯一建议是小心,有时候最简单的方法之所以简单是有原因的。
你完全正确,它确实可能是一个潘多拉魔盒。如果我没记错的话,我想我最终没有在客户端网站的生产版本中使用该图片的固定背景效果。
有趣的是,
clip-path
甚至会影响固定定位的元素。overflow: hidden;
和overflow: clip;
都不影响它。固定定位的元素以及固定定位的背景图片都被移出了页面流,并且仅相对于视口进行定位,因此你无法相对于父元素对其进行定位。你必须单独将其与同一位置对齐——要么使用中心对齐,要么使用媒体查询考虑所有可能的布局,要么使用 JS 获取偏移量。(此外,当在狭窄的视口中(例如手机或嵌入的笔)滚动时,你的背景图片方法会出现一些奇怪的拉伸。我不知道为什么会这样)
至于替代方案——我基于
position: sticky;
、一个额外的溢出容器和overflow: clip;
对你的第二种方法进行了修改。你可以看看:https://codepen.io/AnisMan/full/bGojraJ我甚至在发布之前就注意到了拉伸问题,但只出现在一种情况下。我们无法弄清楚为什么会偶尔发生这种情况。我个人认为这可能是 CodePen 的问题?但我不确定。
我查看了你的修改版本,甚至试着玩了一下。我不太清楚它如何实现了我的预期效果。
(看来我之前的回复没有发送成功)
假设我没有错过你的全部要点,我现在修复了修改版本,以真正展示附加到视口的背景效果。之前它更像是一个概念证明。
其原理是,当有足够的空间时,
position:sticky;
的行为与position:fixed;
相同,但你可以选择方向——将其垂直附加到视口,水平附加到父元素。您好,
玩了一下你的剪切路径方法。
clip-path: inset(0 round 25px);
在 FF、Safari 和 Chrome 中似乎效果很好。你代码片段的修改版本:这里
圆角技巧来源:这里
这实际上非常有用。示例和剪切路径生成器。非常感谢!