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

file

# 编写 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;
}

在应用了这些样式后,我们的页面成了这个样子

file

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;
}

现在的样子是这样的

file

# 收尾工作

看起来一切顺利,但是如果你放大页面,效果就显得不是那么完美

file

没错,边缘部分的模糊化看起来效果不大好,不过解决也很简单

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

file