尽管背景透明度生效,但 backdrop-filter(模糊)对 .menu-panel 无效

我正在定制一个长期使用的自定义主题,希望让汉堡/侧边栏菜单(.menu-panel)拥有与 .d-header 上已经正常工作的半透明模糊效果。透明度是生效的,但模糊效果没有——我想将此作为反馈提出,因为核心样式对该组件的某些处理方式使得这比预期更困难。

我想实现的效果

一个半透明的菜单面板,背后带有 backdrop-filter: blur(),这样页面内容仍能透过面板隐约可见,类似于许多原生应用使用的毛玻璃效果。对我来说,透明效果和模糊效果都很重要——在繁忙的主题列表上,没有模糊的透明效果看起来很杂乱。

已经生效的部分

在 .d-header 上,只需以下代码即可可靠地工作(已在 iOS Safari 和桌面版 Chrome 上测试):

.d-header {
  background-color: color-mix(in srgb, var(--header_background) 50%, transparent);
  -webkit-backdrop-filter: blur(3px) saturate(1.2);
  backdrop-filter: blur(3px) saturate(1.2);
}

不生效的部分

将完全相同的配方应用于 .menu-panel 时,在 iOS Safari 上只能得到透明度,但永远没有模糊效果:

.menu-panel {
  background-color: color-mix(in srgb, var(--secondary) 85%, transparent) !important;
  -webkit-backdrop-filter: blur(6px) saturate(1.2);
  backdrop-filter: blur(6px) saturate(1.2);
  border-radius: 14px;
}

我尝试了以下方法让模糊效果显示出来,但都没有帮助:

  • 在 backdrop-filter/-webkit-backdrop-filter 声明本身添加 !important。
  • 使用 transform: translateZ(0) 结合 overflow: hidden 强制创建专用的合成层(这是解决其他 backdrop-filter 问题的常见 Safari 变通方法)——这里没有任何区别,所以我再次移除了它,而不是保留一个不起作用的 hack。
  • 确认我针对的是正确的元素:根据 menu-panel.scss,不透明背景是直接设置在 .menu-panel 上的(而不是像 .panel-body 这样的子元素),我最初搞错了这一点,后来纠正了。

如果任何人知道为什么 .menu-panel 在这里的行为与 .d-header 不同,或者有可用的配方,我很乐意听到。

第二个问题:单个菜单行上的硬编码背景

即使将面板本身的背景设为透明,其中的一些元素仍然渲染为实心,因为核心直接设置它们的背景,而不是通过面板本身的背景:

  • .user-notifications-list .read 和 .bookmark — 用户菜单中的已读通知和书签直接获得 background-color: var(--secondary),因此每一行都显示为浮在半透明面板上的不透明块。
  • .hamburger-panel .sidebar-footer-wrapper .sidebar-footer-container — 侧边栏底部的个人资料/登录页脚存在同样的问题。

我可以在(并且已经)我的主题中覆盖这些,但这意味着要逐个查找 menu-panel.scss 中每个硬编码的 var(--secondary),并且下次核心添加具有相同模式的新元素时,它又会再次损坏。如果这些能回退到 CSS 自定义属性,例如类似 --d-menu-panel-background 并默认为 var(--secondary) 的东西,那将非常有帮助,这样主题只需重新定义一个变量就能使整个面板(包括其行)一致地透明,而不是去追逐单个选择器。

如果有用,我很乐意分享修改前后的截图,并在我这边测试任何建议的修复方案。

1 個讚

后续问题:同样的缺乏可见透明/模糊效果的问题现在也出现在另一个共享 .menu-panel 样式路径的元素上——即头部搜索下拉菜单的输入框(.search-input-wrapper,属于 glimmer 搜索菜单的一部分)。

配方(与正常工作的 .d-header 以及上述 .menu-panel 的模式完全相同):

.search-menu .search-input-wrapper {
  background: color-mix(in srgb, var(--header_background) 85%, transparent) !important;
  -webkit-backdrop-filter: blur(6px) saturate(1.2);
  backdrop-filter: blur(6px) saturate(1.2);
  border-radius: 14px;
  box-shadow: 0 0 0 1px var(--primary-low-mid);
  overflow: hidden;
}

.search-menu .search-input {
  background: transparent !important;
}

渲染正确的部分: 细边框(box-shadow)和 border-radius 均按预期显示——这表明选择器匹配到了正确的元素,规则已生效,并未被静默覆盖。

未渲染的部分: 没有可见的半透明效果,也没有对字段背后内容的可见模糊,症状与上述报告的 .menu-panel(侧边栏/汉堡菜单面板)相同。而 .d-header 使用了字面上相同的三行代码(通过 color-mix 设置 background-color、-webkit-backdrop-filter、backdrop-filter),仍然工作正常。

这让我越来越怀疑问题并非特定于 .menu-panel 本身,而是这些下拉菜单/覆盖层样式元素共有的某些特性(例如核心代码其他位置创建的层叠上下文,或者一个并非 backdrop-filter 适当包含块的合成层,或类似情况)——而不是我们自己的选择器或属性值的问题,因为完全相同的三个 CSS 属性在附加到不同的核心元素时表现不同。

有没有人遇到 backdrop-filter/半透明背景在搜索下拉菜单或其他 .menu-panel 系列覆盖层上不渲染的情况,即使同样的配方在头部上有效?

问题在于每个已读通知都有独立的背景颜色,这也需要被覆盖。除了你之前的其他更改外,这应该会有所帮助。

.user-menu .quick-access-panel .read {
  background: transparent;
}

搜索输入框的情况类似,那里也应用了一个独立的背景,需要将其移除:

.search-menu .search-input, .search-menu-container .search-input {
  background: transparent;
}

我们有一份指南,介绍了如何进行此类 CSS 更改,可能对你有帮助:Making custom CSS changes on your site

2 個讚

非常感谢!——两个修复方案都完全按照描述生效了。

给遇到同样问题的朋友:除了你提到的那两个覆盖样式外,.search-menu-panel 内部还有一个嵌套的 .results 元素,它会独立于 .menu-panel 绘制自己的不透明背景,因此也需要做同样的处理:

.search-menu-panel .results {
  background: transparent !important;
}

加上你的那两段代码后,现在所有地方的透明效果都完美运行了——侧边栏、汉堡菜单面板、快速访问通知,以及包含结果列表的完整搜索下拉菜单。整个界面中的文字都清晰可读,所以在透明度方面,我们这边的问题已经完全解决了。

目前唯一尚未解决的问题仍然是本帖的原始主题:backdrop-filter/模糊效果本身。尽管现在所有背景都已正确设置为透明,但这些元素仍然没有显示出任何模糊效果——症状和之前一样,而且这与 .d-header 形成鲜明对比,因为在那里完全相同的 backdrop-filter 代码运行正常。所以透明度问题已经解决,但模糊效果的问题仍然存在。

再次感谢你花时间深入研究这个问题——真的很有帮助。

1 個讚

好的,这要稍微复杂一些……当像 header 这样的元素应用了 backdrop-filter 时,它就会成为该效果的根元素。因此,嵌套在该根元素内部的任何后代元素(如下拉面板)只能模糊该根元素内部的内容……即使面板超出了 header 的范围,它们也无法看到 header 之外的页面内容,所以在那部分区域你看不到任何模糊效果。

作为替代方案,你可以在 header 上使用伪元素来避免这种根元素限制。

.d-header {
  position: relative;
  isolation: isolate;
  background-color: transparent;

  &::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background-color: color-mix(in srgb, var(--header_background) 70%, transparent);
    backdrop-filter: blur(12px);
    pointer-events: none;
  }
}

.menu-panel {
  background-color: color-mix(in srgb, var(--secondary) 70%, transparent);
  backdrop-filter: blur(12px);
}

.user-menu .quick-access-panel .read {
  background: transparent;
}
4 個讚

(帖子已被作者删除)

1 個讚