Cover image for Hexo butterfly主题实现MacOS液态玻璃效果

Hexo butterfly主题实现MacOS液态玻璃效果

字数 1.9k
阅读
访客
时间轴

时间轴

2025-12-27

init

本文介绍了在Hexo butterfly主题中实现MacOS液态玻璃效果的方法。文章详细阐述了实现思路,即通过多层叠加共四层结构来模拟玻璃质感:最外层容器负责阴影与动画过渡,核心模糊层利用SVG滤镜实现背景扭曲与液态流动感,色调蒙层叠加半透明白色以增强可读性,高光层通过内阴影模拟边缘反光。同时说明了内容层的放置方式及悬停时的动态交互效果,包括圆角变化与内边距调整。最后以作者信息卡片为例,展示了在butterfly主题中修改pug文件、创建自定义CSS并注入的具体步骤。

在 CodePen 上看到的,稍微改了一下,效果可以看本站 aside 的 card 或 nav。

实现思路

主要思路是利用多层叠加,共四层

12345678
<div class="liquidGlass-wrapper">  <div class="liquidGlass-effect"></div>   <!-- 模糊 + 扭曲 -->  <div class="liquidGlass-tint"></div>     <!-- 半透明白色蒙层 -->  <div class="liquidGlass-shine"></div>    <!-- 内发光高光 -->  <div class="liquidGlass-box">            <!-- 实际内容容器 -->    <!-- 内容 -->  </div></div>

liquidGlass-wrapper

容器壳

12345678
.liquidGlass-wrapper {  box-shadow: 0 6px 6px rgba(0, 0, 0, 0.2), 0 0 20px rgba(0, 0, 0, 0.1) !important;  transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 2.2) !important;  background: none !important;  backdrop-filter: none !important;  -webkit-backdrop-filter: none !important;  border-style: none !important;}
  • 作用:最外层容器,负责整体阴影和动画过渡。
  • 关键点:
    • background: none和backdrop-filter: none是为了不让它自己产生模糊,把模糊交给内部.liquidGlass-effect。
    • 阴影模拟玻璃的立体感。
    • transition让 hover 时的圆角和 padding 变化更流畅。

liquidGlass-effect

核心“液态”模糊层

12345678910
.liquidGlass-effect {  position: absolute;  z-index: 0;  inset: 0;  backdrop-filter: blur(3px);  filter: url(#glass-distortion);  overflow: hidden;  isolation: isolate;}
  • backdrop-filter: blur(3px)
    对背景内容(如网页其他部分)做模糊处理 → 这是“毛玻璃”的基础。
  • filter: url(#glass-distortion) ⭐ 这是“液态”感的关键!它引用了一个 SVG 滤镜(#glass-distortion),通常定义在页面<svg>中,用于对图像施加扭曲、波纹、液态流动等效果。
  • isolation: isolate 确保该层创建新的层叠上下文,避免滤镜影响其他元素。

glass-distortion

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
<svg style="display: none"><filter  id="glass-distortion"  x="0%"  y="0%"  width="100%"  height="100%"  filterUnits="objectBoundingBox">  <feTurbulence    type="fractalNoise"    baseFrequency="0.01 0.01"    numOctaves="1"    seed="5"    result="turbulence"  />  <!-- Seeds: 可替换为其他值如 14, 17 等 -->  <feComponentTransfer in="turbulence" result="mapped">    <feFuncR type="gamma" amplitude="1" exponent="10" offset="0.5" />    <feFuncG type="gamma" amplitude="0" exponent="1" offset="0" />    <feFuncB type="gamma" amplitude="0" exponent="1" offset="0.5" />  </feComponentTransfer>  <feGaussianBlur in="turbulence" stdDeviation="3" result="softMap" />  <feSpecularLighting    in="softMap"    surfaceScale="5"    specularConstant="1"    specularExponent="100"    lighting-color="white"    result="specLight"  >    <fePointLight x="-200" y="-200" z="300" />  </feSpecularLighting>  <feComposite    in="specLight"    operator="arithmetic"    k1="0"    k2="1"    k3="1"    k4="0"    result="litImage"  />  <feDisplacementMap    in="SourceGraphic"    in2="softMap"    scale="150"    xChannelSelector="R"    yChannelSelector="G"  />  </filter></svg>

liquidGlass-tint

色调蒙层

123456
.liquidGlass-tint {  z-index: 1;  position: absolute;  inset: 0;  background: rgba(255, 255, 255, 0.25);}
  • 在模糊层之上叠加一层半透明白色(也可改为浅蓝、浅灰等)。
  • 模拟真实玻璃的“反光底色”,让文字/内容更易读。
  • z-index: 1确保它在 effect 之上、shine 之下。

liquidGlass-shine

高光层

12345678910
.liquidGlass-shine {  position: absolute;  inset: 0;  z-index: 2;  overflow: hidden;  box-shadow: inset 2px 2px 1px 0 rgba(255, 255, 255, 0.5),    inset -1px -1px 1px 1px rgba(255, 255, 255, 0.5);}
  • 使用 内阴影(inset box-shadow) 模拟玻璃边缘的高光和微反光。
  • 上右亮(+2px 白光),下左稍暗(-1px 白光)→ 营造光照方向感。
  • z-index: 2放在最上层(但低于内容)。

liquidGlass-box

内容层

1234567
.liquidGlass-box {  z-index: 3;  position: relative;  box-shadow: none !important;}
  • 真正放内容的地方(如头像、文字)。
  • z-index: 3确保内容在所有玻璃效果层之上,清晰可见。
  • position: relative使其脱离普通流,但仍在 wrapper 内。

交互效果(Hover 动态)

12345678910111213141516
/* OTHER STYLES */.liquidGlass-wrapper,.liquidGlass-wrapper > div:not(.liquidGlass-box) {  padding: 0.4rem !important;  border-radius: var(--glass-border-radius) !important;}.liquidGlass-wrapper:hover {  padding: 0.6rem !important;  border-radius: calc(var(--glass-border-radius) + 1em) !important;}.liquidGlass-wrapper > div:not(.liquidGlass-box):hover {  border-radius: calc(var(--glass-border-radius) + 1em) !important;}
  • 悬停时:
    • 圆角变大(+1em)→ 模拟“液体膨胀”或“柔软变形”;
    • 内边距增大 → 整体“呼吸感”;
    • 所有非内容层同步圆角变化,保持视觉一致。

应用到butterfly的例子

下面以card_author为例,即显示作者信息的卡片。

card_author.pug

修改themes/butterfly/layout/includes/widget/card_author.pug

12345678910111213
if theme.aside.card_author.enable  .card-widget.card-info.text-center.liquidGlass-wrapper    .liquidGlass-effect    .liquidGlass-tint    .liquidGlass-shine    .liquidGlass-box      div.card-info-avatar        .avatar-img          img(            src=url_for(theme.avatar.img)            onerror="this.onerror=null;this.src='" + url_for(theme.error_img.flink) + "'"            alt="avatar"          )

liquid_glass.css

创建自定义css文件themes\butterfly\source\css\liquid_glass.css

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
/* LIQUID GLASS STYLES */:root {  --glass-border-radius: 1.2rem; /* 默认圆角 */}.liquidGlass-wrapper {  box-shadow: 0 6px 6px rgba(0, 0, 0, 0.2), 0 0 20px rgba(0, 0, 0, 0.1) !important;  transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 2.2) !important;  background: none !important;  backdrop-filter: none !important;  -webkit-backdrop-filter: none !important;  border-style: none !important;}.liquidGlass-effect {  position: absolute;  z-index: 0;  inset: 0;  backdrop-filter: blur(3px);  filter: url(#glass-distortion);  overflow: hidden;  isolation: isolate;}.liquidGlass-tint {  z-index: 1;  position: absolute;  inset: 0;  background: rgba(255, 255, 255, 0.25);}.liquidGlass-shine {  position: absolute;  inset: 0;  z-index: 2;  overflow: hidden;  box-shadow: inset 2px 2px 1px 0 rgba(255, 255, 255, 0.5),    inset -1px -1px 1px 1px rgba(255, 255, 255, 0.5);}.liquidGlass-box {  z-index: 3;  position: relative;  box-shadow: none !important;}/* OTHER STYLES */.liquidGlass-wrapper,.liquidGlass-wrapper > div:not(.liquidGlass-box) {  padding: 0.4rem !important;  border-radius: var(--glass-border-radius) !important;}.liquidGlass-wrapper:hover {  padding: 0.6rem !important;  border-radius: calc(var(--glass-border-radius) + 1em) !important;}.liquidGlass-wrapper > div:not(.liquidGlass-box):hover {  border-radius: calc(var(--glass-border-radius) + 1em) !important;}

inject

主题的_config.yml的 inject 中引入

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
inject:  head:    - <link rel="stylesheet" href="/css/liquid_glass.css">  bottom:    - |      <svg style="display: none">      <filter        id="glass-distortion"        x="0%"        y="0%"        width="100%"        height="100%"        filterUnits="objectBoundingBox"      >        <feTurbulence          type="fractalNoise"          baseFrequency="0.01 0.01"          numOctaves="1"          seed="5"          result="turbulence"        />        <!-- Seeds: 可替换为其他值如 14, 17 等 -->        <feComponentTransfer in="turbulence" result="mapped">          <feFuncR type="gamma" amplitude="1" exponent="10" offset="0.5" />          <feFuncG type="gamma" amplitude="0" exponent="1" offset="0" />          <feFuncB type="gamma" amplitude="0" exponent="1" offset="0.5" />        </feComponentTransfer>        <feGaussianBlur in="turbulence" stdDeviation="3" result="softMap" />        <feSpecularLighting          in="softMap"          surfaceScale="5"          specularConstant="1"          specularExponent="100"          lighting-color="white"          result="specLight"        >          <fePointLight x="-200" y="-200" z="300" />        </feSpecularLighting>        <feComposite          in="specLight"          operator="arithmetic"          k1="0"          k2="1"          k3="1"          k4="0"          result="litImage"        />        <feDisplacementMap          in="SourceGraphic"          in2="softMap"          scale="150"          xChannelSelector="R"          yChannelSelector="G"        />        </filter>      </svg>

参考

评论加载中…