最终效果是这样的,下面我们一步步实现它

# 编写 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 的部分,但那部分被裁剪掉了,只剩下内部模糊效果较好的部分
