描述图片

用html和css实现一下液态玻璃(liquid glass)效果

Published on
Authors
  • Name
    Wxm
    Twitter

参考1 juejin 参考2 kube.io

参考了大神的实现,自己又调整了参数,并且适配了黑暗模式,仅供参考。

效果就在主页的菜单Hover就可以看到,在Safari中svg反射效果不生效,用Chrome就能正常显示。

<div className="liquid_glass-wrapper h-full w-full">
  <svg style={{ display: "none" }}>
    <defs>
      <filter
        id="liquid_glass_filter"
        x="0%"
        y="0%"
        width="100%"
        height="100%"
        filterUnits="objectBoundingBox"
      >
        <feDisplacementMap scale="200" />
      </filter>
    </defs>
  </svg>
  <div className="liquid_glass-outer"></div>
  <div className="liquid_glass-cover"></div>
  <div className="liquid_glass-sharp"></div>
  <div className="liquid_glass-reflect"></div>
</div>

适配了黑暗模式的css

.liquid_glass-wrapper {
  --liquid_glass-border-radius: 1rem;
  position: relative;
  display: flex;
  overflow: hidden;
  border: 1px solid #00000020;
  background: linear-gradient(180deg, #ffffff10, #fafafa00);
  box-shadow:
    inset 0 2px 4px 0 #fff,
    inset 0 -4px 4px 0 hsla(0, 0%, 100%, 0.1),
    inset 0 -4px 16px 0 #fff,
    inset 0 4px 10px 0 hsla(240, 3%, 45%, 0.07),
    0 4px 14px -10px rgba(53, 53, 79, 0.4),
    0 11px 28px -10px rgba(53, 53, 79, 0.1);
  border-radius: var(--liquid_glass-border-radius);
}

.liquid_glass-border-radius {
  border-radius: var(--liquid_glass-border-radius);
}

.liquid_glass-outer {
  backdrop-filter: url(#liquid_glass_filter);
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: var(--liquid_glass-border-radius);
  mask-image:
    url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"><rect x="0" y="0" width="100%" height="100%" rx="0" ry="0" fill="white"/></svg>'),
    url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"><rect x="5" y="5" width="calc(100% - 10px)" height="calc(100% - 10px)" rx="21" ry="21" fill="white"/></svg>');
  mask-composite: exclude;
}

.liquid_glass-cover {
  backdrop-filter: blur(2px);
  position: absolute;
  inset: 0;
  z-index: 2;
  border-radius: var(--liquid_glass-border-radius);
  background: rgba(0, 0, 0, 0.02);
}

.liquid_glass-sharp {
  position: absolute;
  inset: 0;
  z-index: 3;
  box-shadow:
    inset 1px 1px 0px 0px rgba(255, 255, 255, 0.5),
    inset -1px -1px 0px 0px rgba(255, 255, 255, 0.6);
  border-radius: var(--liquid_glass-border-radius);
}

.liquid_glass-reflect {
  position: absolute;
  inset: 1px;
  z-index: 2;
  border-radius: var(--liquid_glass-border-radius);
}

.dark {
  /* https://juejin.cn/post/7514618352829448244 */
  .liquid_glass-wrapper {
    --liquid_glass-border-radius: 1rem;
    position: relative;
    display: flex;
    overflow: hidden;

    border: 1px solid #ffffff20;
    background: linear-gradient(180deg, #ffffff10, #fafafa00);
    box-shadow:
      inset 0 2px 4px 0 #00000040,
      inset 0 -4px 4px 0 hsla(0, 0%, 0%, 0.1),
      inset 0 -4px 16px 0 #00000060,
      inset 0 4px 10px 0 hsla(0, 0%, 13%, 0.07),
      0 4px 14px -10px rgba(112, 112, 167, 0.4),
      0 11px 28px -10px rgba(53, 53, 79, 0.1);
    border-radius: var(--liquid_glass-border-radius);
  }

  .liquid_glass-border-radius {
    border-radius: var(--liquid_glass-border-radius);
  }

  .liquid_glass-outer {
    backdrop-filter: url(#liquid_glass_filter);
    position: absolute;
    inset: 0;
    z-index: 0;
    border-radius: var(--liquid_glass-border-radius);

    mask-image:
      url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"><rect x="0" y="0" width="100%" height="100%" rx="0" ry="0" fill="white"/></svg>'),
      url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"><rect x="5" y="5" width="calc(100% - 10px)" height="calc(100% - 10px)" rx="21" ry="21" fill="white"/></svg>');
    mask-composite: exclude;
  }

  .liquid_glass-cover {
    backdrop-filter: blur(2px);
    position: absolute;
    inset: 0;
    z-index: 2;
    border-radius: var(--liquid_glass-border-radius);
    background: rgba(0, 0, 0, 0.02);
  }

  .liquid_glass-sharp {
    position: absolute;
    inset: 0;
    z-index: 3;
    box-shadow:
      inset 1px 1px 0px 0px rgba(255, 255, 255, 0.2),
      inset -1px -1px 0px 0px rgba(255, 255, 255, 0.3);
    border-radius: var(--liquid_glass-border-radius);
  }

  .liquid_glass-reflect {
    position: absolute;
    inset: 1px;
    z-index: 2;
    border-radius: var(--liquid_glass-border-radius);
  }
}

0:00/0:00

植松伸夫 - フィナーレ

植松伸夫 - プレリュード

笹井隆司 - 異郷の町

伊藤賢治 - Rising Sun

植松伸夫 - 街のテーマ

植松伸夫 - 怒闘

植松伸夫 - コーネリア城

植松伸夫 - チョコボのテーマ