最终效果是这样的,下面我们一步步实现它
# 编写 dom 结构
我们需要的 dom 结构很少,只要一个 container 和一个 content 就可以了
<div class="container"> | |
<div class="content"> | |
Genius only means hard-working all one's life. | |
</div> | |
</div> |
# 初始化样式
这里主要是一些无关样式
body, h1{ | |
margin: 0; | |
padding: 0; | |
} | |
html, body { | |
font-size: 19px; | |
font-family: serif; | |
color: rgba(0,0,0,0.8); | |
} | |
.container { | |
width: 100%; | |
height: 100%; | |
position: relative; | |
background-image: url("./resource/images/bg.bmp"); | |
background-repeat: no-repeat; | |
background-position: center top; | |
background-size: cover; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
} | |
.content { | |
width: 800px; | |
height: 400px; | |
position: relative; | |
border-radius: 8px; | |
box-shadow: 0 10px 20px rgba(0,0,0,0.5); | |
padding: 50px; | |
box-sizing: border-box; | |
background: transparent; | |
} | |
.content h1 { | |
text-align: center; | |
margin-bottom: 20px; | |
} | |
.content p { | |
text-indent: 2em; | |
line-height: 1.7; | |
} |
在应用了这些样式后,我们的页面成了这个样子
container 占满整个屏幕,content 在 container 里水平居中,因为 content 设置了背景透明,所以可以直接透过 content 看到 container 的内容(背景)
# 编写核心 css 样式
我们要做的事情很简单,设置 content 的一个伪元素,让它的层叠等级低于 content,这样伪元素就可以在 content 的下面作为背景,然后设置伪元素的背景,背景设置除了 background-attachment 一定要设置成 fixed,让背景相对视口定位,其他的都直接照抄,这样伪元素的背景就会和 container 的背景重合,但是伪元素和 content 大小一样,而元素的背景的范围又不能超过元素本身,所以只显示 content 大小的模糊化背景
.content::before { | |
/* 让伪元素铺满 content */ | |
content: ''; | |
position: absolute; | |
top: 0; | |
left: 0; | |
right: 0; | |
bottom: 0; | |
/* 设置伪元素的背景,最重要的是设置背景图片的位置是视口固定 */ | |
/* 其他的设置直接照抄 container 的设置,否则可能导致不重合 */ | |
background-image: url("./resource/images/bg.bmp"); | |
background-position: center top; | |
background-size: cover; | |
background-attachment: fixed; | |
/* 让伪元素模糊化 */ | |
filter: blur(20px); | |
/* 降低伪元素的层级,让伪元素在 content 的下面展现 */ | |
z-index: -1; | |
} | |
.content { | |
overflow: hidden; | |
z-index: 1; | |
} |
现在的样子是这样的
# 收尾工作
看起来一切顺利,但是如果你放大页面,效果就显得不是那么完美
没错,边缘部分的模糊化看起来效果不大好,不过解决也很简单
.content { | |
/* 因为设置了溢出隐藏,所以看上去伪元素是没有变大的 */ | |
overflow: hidden; | |
z-index: 1; | |
} | |
.content::before { | |
content: ''; | |
position: absolute; | |
/* 让伪元素比 content 每边多 30px */ | |
/* 这样就可以避开 filter: blur (20px) 带来的边缘模糊效果不好 */ | |
top: -30px; | |
left: -30px; | |
right: -30px; | |
bottom: -30px; | |
/* 设置伪元素的背景,最重要的是设置背景图片的位置是视口固定 */ | |
/* 其他的设置直接照抄 container 的设置,否则可能导致不重合 */ | |
background-image: url("./resource/images/bg.bmp"); | |
background-position: center top; | |
background-size: cover; | |
background-attachment: fixed; | |
/* 让伪元素模糊化 */ | |
filter: blur(20px); | |
/* 降低伪元素的层级,让伪元素在 content 的下面展现 */ | |
z-index: -1; | |
} |
我们只要设置 top, left, right, bottom 都为 - 30px 就好了,这样模糊不全的部分其实就是移除 content 的部分,但那部分被裁剪掉了,只剩下内部模糊效果较好的部分