外观
html
2260字约8分钟
html
2020-05-06
毛玻璃效果
<div class="box">
<div class="glass">
<div class="light" data-js-background-attachment-fixed></div>
<div class="drag-me">Drag Me</div>
</div>
</div>
/**
* Iterates through all `HTMLElement`s with
* `data-js-background-attachment-fixed` and updates the `background-position`
* to simulate `background-attachment: fixed`.
*/
const updateDataJSBackgroundAttachmentFixedElements = () => {
// Find all elements with the `data-js-background-attachment-fixed` attribute
const elements = document.querySelectorAll(
"[data-js-background-attachment-fixed]",
);
for (const element of elements) {
// Only consider `HTMLElement`s
if (!(element instanceof HTMLElement)) continue;
// Find the position of the element
const clientRect = element.getBoundingClientRect();
// Move the background position opposite the position in the viewport
const backgroundPositionX = `${(-clientRect.x).toString()}px`;
const backgroundPositionY = `${(-clientRect.y).toString()}px`;
element.style.backgroundPositionX = backgroundPositionX;
element.style.backgroundPositionY = backgroundPositionY;
}
};
/**
* Begins a loop which simulates `background-attachment: fixed` for
* `HTMLElement`s with `data-js-background-attachment-fixed`.
*
* This loop executes each animation frame.
*/
const initDataJSBackgroundAttachmentFixed = () => {
requestAnimationFrame(() => {
updateDataJSBackgroundAttachmentFixedElements();
initDataJSBackgroundAttachmentFixed();
});
};
// 添加拖拽功能
const glass = document.querySelector('.glass');
const dragMe = document.querySelector('.drag-me');
let isDragging = false;
let currentX;
let currentY;
let initialX;
let initialY;
let xOffset = 0;
let yOffset = 0;
dragMe.addEventListener('mousedown', dragStart);
document.addEventListener('mousemove', drag);
document.addEventListener('mouseup', dragEnd);
function dragStart(e) {
initialX = e.clientX - xOffset;
initialY = e.clientY - yOffset;
if (e.target === dragMe) {
isDragging = true;
}
}
function drag(e) {
if (isDragging) {
e.preventDefault();
currentX = e.clientX - initialX;
currentY = e.clientY - initialY;
xOffset = currentX;
yOffset = currentY;
setTranslate(currentX, currentY, glass);
}
}
function dragEnd() {
isDragging = false;
}
function setTranslate(xPos, yPos, el) {
el.style.transform = `translate3d(${xPos}px, ${yPos}px, 0)`;
}
initDataJSBackgroundAttachmentFixed();.box {
/* Full screen */
height: 360px;
margin: 0;
padding: 0;
/* Background image */
background-image: url('https://w.wallhaven.cc/full/45/wallhaven-45dd35.jpg');
background-size: cover;
/* Center the glass div */
display: flex;
justify-content: center;
align-items: center;
}
.glass {
/* Size */
height: 300px;
width: 200px;
margin: 0;
padding: 0;
/* Blur effect */
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
box-shadow:
/* Bottom and right depth effect */
inset -0.75px -0.5px rgba(255, 255, 255, 0.1),
/* Top and left depth effect */
inset +0.75px +0.5px rgba(255, 255, 255, 0.025),
/* Shadow effect */
3px 2px 10px rgba(0, 0, 0, 0.25),
/* Short subsurface effect */
inset 0px 0px 10px 5px rgba(255, 255, 255, 0.025),
/* Long subsurface effect */
inset 0px 0px 40px 5px rgba(255, 255, 255, 0.025);
/* Allow children to fill the parent */
position: relative;
/* Round the corners */
border-radius: 5px;
/* Hide the corners of the header */
overflow: hidden;
}
.glass::before {
/* Make the element render */
content: "";
/* Apply the background image */
background-repeat: repeat;
background-size: 750px;
/* Adjust the intensity */
opacity: 0.075;
/* Fill the background space */
position: absolute;
bottom: 0;
left: 0;
right: 0;
top: 0;
/* Render behind other children */
z-index: -1;
/* Fix the reflection to the screen */
background-attachment: fixed;
}
.drag-me {
/* Center the content */
display: flex;
align-items: center;
justify-content: center;
/* Size the content */
height: 30px;
/* Add a transparent background */
background-color: rgba(12, 13, 14, 0.75);
color: rgba(201, 216, 232, 0.75);
/* Add cursor style */
cursor: move;
}液态玻璃效果
<div class="box">
<div class="glass">
<div class="light" data-js-background-attachment-fixed></div>
<div class="drag-me">Drag Me</div>
</div>
</div>/**
* Iterates through all `HTMLElement`s with
* `data-js-background-attachment-fixed` and updates the `background-position`
* to simulate `background-attachment: fixed`.
*/
const updateDataJSBackgroundAttachmentFixedElements = () => {
// Find all elements with the `data-js-background-attachment-fixed` attribute
const elements = document.querySelectorAll(
"[data-js-background-attachment-fixed]",
);
for (const element of elements) {
// Only consider `HTMLElement`s
if (!(element instanceof HTMLElement)) continue;
// Find the position of the element
const clientRect = element.getBoundingClientRect();
// Move the background position opposite the position in the viewport
const backgroundPositionX = `${(-clientRect.x).toString()}px`;
const backgroundPositionY = `${(-clientRect.y).toString()}px`;
element.style.backgroundPositionX = backgroundPositionX;
element.style.backgroundPositionY = backgroundPositionY;
}
};
/**
* Begins a loop which simulates `background-attachment: fixed` for
* `HTMLElement`s with `data-js-background-attachment-fixed`.
*
* This loop executes each animation frame.
*/
const initDataJSBackgroundAttachmentFixed = () => {
requestAnimationFrame(() => {
updateDataJSBackgroundAttachmentFixedElements();
initDataJSBackgroundAttachmentFixed();
});
};
// 添加拖拽功能
const glass = document.querySelector('.glass');
const dragMe = document.querySelector('.drag-me');
let isDragging = false;
let currentX;
let currentY;
let initialX;
let initialY;
let xOffset = 0;
let yOffset = 0;
dragMe.addEventListener('mousedown', dragStart);
document.addEventListener('mousemove', drag);
document.addEventListener('mouseup', dragEnd);
function dragStart(e) {
initialX = e.clientX - xOffset;
initialY = e.clientY - yOffset;
if (e.target === dragMe) {
isDragging = true;
}
}
function drag(e) {
if (isDragging) {
e.preventDefault();
currentX = e.clientX - initialX;
currentY = e.clientY - initialY;
xOffset = currentX;
yOffset = currentY;
setTranslate(currentX, currentY, glass);
}
}
function dragEnd() {
isDragging = false;
}
function setTranslate(xPos, yPos, el) {
el.style.transform = `translate3d(${xPos}px, ${yPos}px, 0)`;
}
initDataJSBackgroundAttachmentFixed();.box {
/* Full screen */
height: 360px;
margin: 0;
padding: 0;
/* Background image */
background-image: url('https://w.wallhaven.cc/full/45/wallhaven-45dd35.jpg');
background-size: cover;
/* Center the glass div */
display: flex;
justify-content: center;
align-items: center;
}
.glass {
/* Size */
height: 200px;
width: 150px;
margin: 0;
padding: 0;
border-radius: 15px;
position: relative;
/* Liquid Glass 核心样式 */
background-color: rgba(255, 255, 255, 0.15); /* 半透明背景 */
backdrop-filter: blur(12px) saturate(150%); /* 模糊和饱和度 */
-webkit-backdrop-filter: blur(12px) saturate(150%); /* Safari 兼容 */
border: 1px solid rgba(255, 255, 255, 0.4); /* 边框 */
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1); /* 轻微阴影 */
transition: background-color 0.3s ease; /* 平滑过渡 */
/*transition: transform 0.3s ease, box-shadow 0.3s ease;*/
/* 卡片样式 */
overflow: hidden;
padding: 30px;
text-align: center;
color: #333;
}
.glass:hover {
/*transform: translateY(-8px) scale(1.02); *//* 悬停上浮并轻微放大 */
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.2);
}
.drag-me {
/* Center the content */
display: flex;
align-items: center;
justify-content: center;
/* Size the content */
height: 30px;
/* Add a transparent background */
/*background-color: rgba(12, 13, 14, 0.75);*/
font-size: 1.8em;
margin-bottom: 15px;
color: #2a7aff; /* 卡片标题颜色 */
/* Add cursor style */
cursor: move;
}新拟态
<div class="box">
<div class="container">
<header class="neu-header">
<i class="fas fa-bars"></i>
<h1>新拟物化设计</h1>
<i class="fas fa-cog"></i>
</header>
<main class="content">
<div class="neu-card neu-convex">
<i class="fas fa-music"></i>
<h2>音乐播放</h2>
<p>享受您的音乐,体验极致音质。</p>
<div class="neu-buttons">
<button class="neu-button neu-concave"><i class="fas fa-backward"></i></button>
<button class="neu-button neu-convex"><i class="fas fa-play"></i></button>
<button class="neu-button neu-concave"><i class="fas fa-forward"></i></button>
</div>
</div>
<div class="neu-section">
<div class="neu-input-wrapper neu-concave">
<input type="text" placeholder="输入您的内容..." class="neu-input">
</div>
<div class="neu-toggle-wrapper">
<label class="neu-toggle neu-convex">
<input type="checkbox" id="darkModeToggle">
<span class="neu-slider"></span>
</label>
<span>深色模式</span>
</div>
</div>
<div class="neu-button-group">
<button class="neu-button neu-concave">设置</button>
<button class="neu-button neu-convex active">个人资料</button>
<button class="neu-button neu-concave">通知</button>
</div>
</main>
</div>
</div>document.addEventListener('DOMContentLoaded', () => {
// 切换按钮组的激活状态
const buttonGroup = document.querySelector('.neu-button-group');
if (buttonGroup) {
buttonGroup.addEventListener('click', (e) => {
if (e.target.classList.contains('neu-button')) {
// 移除所有按钮的激活状态
buttonGroup.querySelectorAll('.neu-button').forEach(btn => {
btn.classList.remove('active');
// 移除旧的凸起阴影,恢复凹陷阴影
btn.classList.add('neu-concave');
btn.classList.remove('neu-convex');
});
// 为点击的按钮添加激活状态
e.target.classList.add('active');
// 添加凸起阴影
e.target.classList.remove('neu-concave');
e.target.classList.add('neu-convex');
}
});
}
// 深色模式切换(仅模拟视觉效果)
const darkModeToggle = document.getElementById('darkModeToggle');
if (darkModeToggle) {
darkModeToggle.addEventListener('change', () => {
if (darkModeToggle.checked) {
document.documentElement.style.setProperty('--bg-color', '#333333');
document.documentElement.style.setProperty('--light-shadow', '#424242');
document.documentElement.style.setProperty('--dark-shadow', '#242424');
document.documentElement.style.setProperty('--text-color', '#dddddd');
document.documentElement.style.setProperty('--accent-color', '#64b5f6'); // 蓝色强调色
} else {
document.documentElement.style.setProperty('--bg-color', '#e0e0e0');
document.documentElement.style.setProperty('--light-shadow', '#ffffff');
document.documentElement.style.setProperty('--dark-shadow', '#a0a0a0');
document.documentElement.style.setProperty('--text-color', '#6a6a6a');
document.documentElement.style.setProperty('--accent-color', '#3f51b5');
}
});
}
});.box {
/* Full screen */
height: 700px;
margin: 0;
padding: 0;
/* Background image */
background-color: #e0e0e0;
color: #6a6a6a;
background-size: cover;
/* Center the glass div */
display: flex;
justify-content: center;
align-items: center;
}
.container {
background-color: #e0e0e0;
border-radius: calc(15px * 2);
padding: 30px;
box-shadow: 10px 10px 20px #a0a0a0,
calc(10px * -1) calc(10px * -1) 20px #ffffff;
display: flex;
flex-direction: column;
gap: 30px;
max-width: 600px;
width: 100%;
}
/* 头部样式 */
.neu-header {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 1.5em;
padding: 10px 0;
color: #6a6a6a;
}
.neu-header h1 {
font-size: 1.8em;
margin: 0;
font-weight: 600;
}
.neu-header .fas {
cursor: pointer;
padding: 10px;
border-radius: 15px;
transition: all 0.3s ease;
}
.neu-header .fas:active {
box-shadow: inset 10px 10px 20px #a0a0a0,
inset calc(10px * -1) calc(10px * -1) 20px #ffffff;
color: #3f51b5;
}
/* 通用新拟物化样式 - 凸起 */
.neu-convex {
background-color: #e0e0e0;
border-radius: 15px;
box-shadow: 10px 10px 20px #a0a0a0,
calc(10px * -1) calc(10px * -1) 20px #ffffff;
transition: all 0.3s ease;
}
/* 通用新拟物化样式 - 凹陷 */
.neu-concave {
background-color: #e0e0e0;
border-radius: 15px;
box-shadow: inset 10px 10px 20px #a0a0a0,
inset calc(10px * -1) calc(10px * -1) 20px #ffffff;
transition: all 0.3s ease;
}
/* 卡片样式 */
.neu-card {
padding: 20px;
text-align: center;
}
.neu-card .fas {
font-size: 3em;
margin-bottom: 15px;
color: #6a6a6a;
}
.neu-card h2 {
font-size: 1.8em;
margin-bottom: 10px;
color: #6a6a6a;
}
.neu-card p {
font-size: 0.9em;
line-height: 1.6;
margin-bottom: 25px;
}
.neu-buttons {
display: flex;
justify-content: center;
gap: 15px;
}
/* 按钮样式 */
.neu-button {
width: 60px;
height: 60px;
border: none;
outline: none;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.2em;
color: #6a6a6a;
cursor: pointer;
border-radius: 50%; /* 圆形按钮 */
background-color: #e0e0e0; /* 确保背景色一致 */
}
.neu-button.neu-convex:active {
box-shadow: inset 10px 10px 20px #a0a0a0,
inset calc(10px * -1) calc(10px * -1) 20px #ffffff;
color: #3f51b5;
}
.neu-button.neu-concave:active {
box-shadow: 10px 10px 20px #a0a0a0,
calc(10px * -1) calc(10px * -1) 20px #e0e0e0;
color: #3f51b5;
}
/* 输入框样式 */
.neu-section {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 20px;
}
.neu-input-wrapper {
flex-grow: 1;
padding: 10px 15px;
}
.neu-input {
width: 100%;
border: none;
outline: none;
background-color: transparent;
color: #6a6a6a;
font-size: 1em;
padding: 5px 0;
}
.neu-input::placeholder {
color: rgba(106, 106, 106, 0.7);
}
/* 开关样式 */
.neu-toggle-wrapper {
display: flex;
align-items: center;
gap: 10px;
font-size: 0.9em;
}
.neu-toggle {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
cursor: pointer;
}
.neu-toggle input {
opacity: 0;
width: 0;
height: 0;
}
.neu-slider {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: 34px;
background-color: #e0e0e0; /* 凸起背景 */
box-shadow: 10px 10px 20px #a0a0a0,
calc(10px * -1) calc(10px * -1) 20px #ffffff;
transition: .4s;
}
.neu-slider::before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: #e0e0e0; /* 滑块背景 */
border-radius: 50%;
box-shadow: inset 2px 2px 5px #a0a0a0,
inset -2px -2px 5px #ffffff; /* 凹陷滑块 */
transition: .4s;
}
input:checked + .neu-slider {
background-color: #e0e0e0; /* 选中时背景不变,但阴影会变 */
box-shadow: inset 2px 2px 5px #a0a0a0, /* 选中时整体凹陷 */
inset -2px -2px 5px #ffffff;
}
input:checked + .neu-slider::before {
transform: translateX(26px);
background-color: #3f51b5; /* 滑块颜色变为强调色 */
box-shadow: 2px 2px 5px rgba(0,0,0,0.2), -2px -2px 5px rgba(255,255,255,0.7); /* 凸起效果 */
}
/* 按钮组 */
.neu-button-group {
display: flex;
background-color: #e0e0e0;
border-radius: 15px;
box-shadow: inset 10px 10px 20px #a0a0a0,
inset calc(10px * -1) calc(10px * -1) 20px #ffffff;
padding: 5px; /* 内部小间距 */
}
.neu-button-group .neu-button {
flex: 1;
height: auto;
padding: 10px 15px;
border-radius: calc(15px - 5px); /* 组内按钮圆角稍小 */
box-shadow: none; /* 组内按钮初始无阴影 */
font-size: 1em;
white-space: nowrap; /* 防止文本换行 */
}
.neu-button-group .neu-button.active {
box-shadow: 10px 10px 20px #a0a0a0,
calc(10px * -1) calc(10px * -1) 20px #ffffff;
color: #3f51b5;
}
/* 响应式设计 */
@media (max-width: 600px) {
.container {
padding: 20px;
margin: 10px;
}
.neu-header h1 {
font-size: 1.5em;
}
.neu-card {
padding: 15px;
}
.neu-buttons {
gap: 10px;
}
.neu-button {
width: 50px;
height: 50px;
font-size: 1em;
}
.neu-input-wrapper {
width: 100%;
}
.neu-section {
flex-direction: column;
align-items: flex-start;
}
.neu-button-group {
width: 100%;
}
}