小众但非常实用的 CSS 属性
元素倒影 -webkit-box-reflect
-webkit-box-reflect 是一个非标准的 CSS 属性,主要用于在 WebKit 浏览器(如 Chrome 和 Safari)中创建元素的倒影效果。这个属性能够增强网页的视觉效果,使元素呈现出更加立体和生动的感觉。
-webkit-box-reflect 的基本语法结构为:-webkit-box-reflect: [direction] [offset] [mask-image];
- direction:指定倒影的方向,可以是 below(下方)、above(上方)、left(左侧)或 right(右侧)。
- offset:倒影与元素之间的距离,可以使用像素(px)、百分比(%)等单位。这个参数决定了倒影与原始元素之间的间隔大小。
- mask-image:(可选)一个图像,用于创建倒影的遮罩效果。如果未指定,倒影将是不透明的。通过遮罩图像,可以实现更加复杂的倒影效果,如渐变透明度等。
代码实现
<style>
.outer {
width: 500px;
height: 250px;
background-color: #f0f0f0;
margin: auto;
padding: 20px;
}
.inner {
width: 100px;
height: 100px;
background-color: #f40;
margin: auto;
-webkit-box-reflect: below 10px linear-gradient(transparent, black);
}
</style>
<div class="outer">
<div class="inner"></div>
</div>元素背面是否可见 backface-visibility
backface-visibility 是一个 CSS 属性,用于控制元素的背面是否可见。它主要用于在进行 3D 转换时控制元素的背面可见性
当我们对一个元素应用 3D 转换(例如旋转或倾斜)时,默认情况下,元素的背面是不可见的,即不会显示在屏幕上。这是因为浏览器默认会进行背面剪裁(backface culling),以提高性能和减少不必要的渲染。但有时候,我们可能需要让元素的背面可见,这时就可以使用 backface-visibility 属性来控制。
backface-visibility 属性有两个可能的值:
- visible:表示元素的背面可见。背面将正常渲染并显示在屏幕上。
- hidden:表示元素的背面不可见。背面将被隐藏,不会显示在屏幕上(这是默认值)
代码实现
<style>
.card {
width: 320px;
height: 200px;
border-radius: 10px;
perspective: 1000px;
margin: auto;
}
.card:hover .card-inner {
transform: rotateY(180deg);
}
.card-inner {
position: relative;
width: 100%;
height: 100%;
border-radius: 10px;
transition: transform 600ms ease;
transform-style: preserve-3d;
box-shadow: 0 0 25px 2px rgba(0, 0, 0, 0.2);
}
.card-front,
.card-back {
position: absolute;
top: 0;
width: 100%;
height: 100%;
border-radius: 10px;
overflow: hidden;
backface-visibility: hidden; /* 背面隐藏*/
background: linear-gradient(321.03deg, #01adef 0%, #0860bf 91.45%);
}
.card-front {
border-radius: 10px;
overflow: hidden;
position: relative;
transition: transform 300ms ease-in-out;
}
.card-back {
transform: rotateY(180deg);
}
.card-back::before {
content: '';
position: absolute;
top: 40%;
left: 20%;
width: 180%;
height: 120%;
border-radius: 100%;
background-image: linear-gradient(to right top, #a3d4e7, #a7d5e6, #abd5e4, #aed6e3, #b2d6e2, #aed4e2, #abd3e1, #a7d1e1, #9bcee1, #8ecae1, #81c7e1, #73c3e1);
filter: blur(10px);
opacity: 0.15;
}
.card-back::after {
content: '';
position: absolute;
top: 15%;
width: 100%;
height: 40px;
background-image: linear-gradient(to right top, #021318, #07191f, #0a1f26, #0b262e, #0c2c35, #0c2c35, #0c2c35, #0c2c35, #0b262e, #0a1f26, #07191f, #021318);
}
.card-bg {
position: absolute;
top: -20px;
right: -120px;
width: 380px;
height: 250px;
background: linear-gradient(321.03deg, #01adef 0%, #0860bf 91.45%);
border-top-left-radius: 100%;
}
.card-bg::before {
content: '';
position: absolute;
top: -20px;
right: -80px;
width: 380px;
height: 250px;
background: linear-gradient(321.03deg, #01adef 0%, #0860bf 91.45%);
border-top-left-radius: 100%;
}
.card-bg::after {
content: '';
position: absolute;
top: -20px;
right: -120px;
width: 380px;
height: 250px;
background: linear-gradient(321.03deg, #01adef 0%, #0860bf 91.45%);
border-top-left-radius: 100%;
}
.card-glow {
position: absolute;
top: -140px;
left: -65px;
height: 200px;
width: 400px;
background: rgba(0, 183, 255, 0.4);
filter: blur(10px);
border-radius: 100%;
transform: skew(-15deg, -15deg);
}
.card-contactless {
position: absolute;
right: 15px;
top: 55px;
transform: scale(0.5);
}
.card-chip {
position: absolute;
top: 65px;
left: 25px;
width: 45px;
height: 34px;
border-radius: 5px;
background-color: #ffda7b;
overflow: hidden;
}
.card-chip::before {
content: '';
position: absolute;
left: 49%;
top: -7%;
transform: translateX(-50%);
background: #ffda7b;
border: 1px solid #a27c1f;
width: 25%;
height: 110%;
border-radius: 100%;
z-index: 2;
}
.card-chip::after {
content: '';
position: absolute;
top: 30%;
left: -10%;
background: transparent;
border: 1px solid #a27c1f;
width: 120%;
height: 33%;
}
.card-holder {
position: absolute;
left: 25px;
bottom: 30px;
color: white;
font-size: 14px;
letter-spacing: 0.2em;
filter: drop-shadow(1px 1px 1px rgba(0, 0, 0, 0.3));
}
.card-number {
position: absolute;
left: 25px;
bottom: 65px;
color: white;
font-size: 16px;
font-weight: 600;
letter-spacing: 0.2em;
filter: drop-shadow(1px 1px 1px rgba(0, 0, 0, 0.3));
}
.card-valid {
position: absolute;
right: 25px;
bottom: 30px;
color: white;
font-size: 14px;
letter-spacing: 0.2em;
filter: drop-shadow(1px 1px 1px rgba(0, 0, 0, 0.3));
}
.card-valid::before {
content: 'WEB DEV';
position: absolute;
top: 1px;
left: -45px;
width: 50px;
font-size: 7px;
}
.card-signature {
position: absolute;
top: 120px;
left: 15px;
width: 70%;
height: 30px;
background: #eeecec;
display: flex;
justify-content: center;
align-items: center;
color: #021318;
font-family: 'Mr Dafoe', cursive;
font-size: 38px;
font-weight: 400;
}
.card-signature::before {
content: 'Authorized Signature';
position: absolute;
top: -15px;
left: 0;
font-family: 'Overpass Mono', monospace;
font-size: 9px;
color: #eeecec;
}
.card-seccode {
position: absolute;
top: 125px;
left: 245px;
display: flex;
justify-content: center;
align-items: center;
width: 40px;
height: 17px;
color: #021318;
background-color: #eeecec;
text-align: center;
font-size: 11px;
}
.logo {
position: absolute;
right: 25px;
top: 30px;
}
.hint {
padding: 2em 0;
font-family: 'Noto Sans KR', sans-serif;
letter-spacing: 0.025em;
font-weight: 400;
color: #a3d4e7;
}
</style>
<div class="card">
<div class="card-inner">
<div class="card-front">
<div class="card-bg"></div>
<div class="card-glow"></div>
<svg width="72" height="24" viewBox="0 0 72 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="logo">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M52.3973 1.01093L51.5588 5.99054C49.0448 4.56717 43.3231 4.23041 43.3231 6.85138C43.3231 7.89285 44.6177 8.60913 46.178 9.47241C48.5444 10.7817 51.5221 12.4291 51.5221 16.062C51.5221 21.8665 45.4731 24 41.4645 24C37.4558 24 34.8325 22.6901 34.8325 22.6901L35.7065 17.4848C38.1115 19.4688 45.4001 20.032 45.4001 16.8863C45.4001 15.5645 43.9656 14.785 42.3019 13.8811C40.0061 12.6336 37.2742 11.1491 37.2742 7.67563C37.2742 1.30988 44.1978 0 47.1132 0C49.8102 0 52.3973 1.01093 52.3973 1.01093ZM66.6055 23.6006H72L67.2966 0.414276H62.5732C60.3923 0.414276 59.8612 2.14215 59.8612 2.14215L51.0996 23.6006H57.2234L58.4481 20.1566H65.9167L66.6055 23.6006ZM60.1406 15.399L63.2275 6.72235L64.9642 15.399H60.1406ZM14.7942 16.3622L20.3951 0.414917H26.7181L17.371 23.6012H11.2498L6.14551 3.45825C2.83215 1.41281 0 0.807495 0 0.807495L0.108643 0.414917H9.36816C11.9161 0.414917 12.1552 2.50314 12.1552 2.50314L14.1313 12.9281L14.132 12.9294L14.7942 16.3622ZM25.3376 23.6006H31.2126L34.8851 0.414917H29.0095L25.3376 23.6006Z"
fill="white" />
</svg>
<div class="card-contactless">
<svg xmlns="http://www.w3.org/2000/svg" width="46" height="56">
<path
fill="none"
stroke="#f9f9f9"
stroke-width="6"
stroke-linecap="round"
d="m35,3a50,50 0 0,1 0,50M24,8.5a39,39 0 0,1 0,39M13.5,13.55a28.2,28.5
0 0,1 0,28.5M3,19a18,17 0 0,1 0,18" />
</svg>
</div>
<div class="card-chip"></div>
<div class="card-holder">webDev</div>
<div class="card-number">1234 5678 9000 1234</div>
<div class="card-valid">12/24</div>
</div>
<div class="card-back">
<div class="card-signature">webdev</div>
<div class="card-seccode">123</div>
</div>
</div>
</div>元素阴影 box-shadow 与 drop-shadow
| 属性 | 类型 | 说明 |
|---|---|---|
box-shadow | CSS 属性 | 给元素的边界框(bounding box) 添加阴影 |
drop-shadow | CSS 滤镜函数(filter: drop-shadow(...)) | 给元素的实际像素轮廓(包括透明区域)生成阴影 |
核心区别
(1) 阴影形状依据不同
- box-shadow
- 始终基于元素的矩形边框(即使内容是圆形、带透明或 PNG 图片)。
- 不管内容是否透明,阴影都是一个矩形。
- drop-shadow
- 基于元素的实际可见像素轮廓(alpha 通道)。
- 对 PNG 图标、SVG、带圆角/裁剪的内容,能生成贴合形状的阴影。
(2) 对透明/镂空区域的处理
- box-shadow:忽略透明区域,只对整个盒子加阴影。
- drop-shadow:能“穿透”透明区域,只为不透明部分投射阴影。
举例:一个带透明背景的 PNG 箭头图标 box-shadow → 阴影是矩形(包含透明区域) drop-shadow → 阴影只出现在箭头形状周围
(3) 性能与兼容性
- box-shadow:
- 性能好,广泛支持(IE9+)
- 可单独设置内阴影(inset)
- drop-shadow:
- 是 filter 的一部分,性能略低(尤其动画时)
- 不支持 inset(无法做内阴影)
- 兼容性:IE 不支持,现代浏览器良好
代码实现
<style>
.demo {
width: 150px;
margin: 20px;
display: inline-block;
background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><circle cx="50" cy="50" r="40" fill="deepskyblue"/></svg>') no-repeat center;
background-size: contain;
padding: 20px;
}
.box-shadow {
box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.5);
}
.drop-shadow {
filter: drop-shadow(4px 4px 8px rgba(0, 0, 0, 0.5));
}
</style>
<div class="demo box-shadow">box-shadow</div>
<div class="demo drop-shadow">drop-shadow</div>box-shadow 是“盒子的影子”,drop-shadow 是“内容的影子”。
不规则的文字环绕 shape-outside
shape-outside 的 CSS 属性定义了一个可以是非矩形的形状,相邻的内联内容应围绕该形状进行包装。默认情况下,内联内容包围其边距框; shape-outside 提供了一种自定义此包装的方法,可以将文本包装在复杂对象周围而不是简单的框中。
/* 关键字值 */
shape-outside: none;
shape-outside: margin-box;
shape-outside: content-box;
shape-outside: border-box;
shape-outside: padding-box;
/* 函数值 */
shape-outside: circle();
shape-outside: ellipse();
shape-outside: inset(10px 10px 10px 10px);
shape-outside: polygon(10px 10px, 20px 20px, 30px 30px);
/* <url> 值 */
shape-outside: url(image.png);
/* 渐变值 */
shape-outside: linear-gradient(45deg, rgba(255, 255, 255, 0) 150px, red 150px);
/* 全局值 */
shape-outside: initial;
shape-outside: inherit;
shape-outside: unset;
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus lacinia odio vitae vestibulum vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed blandit ligula non leo cursus, vitae eleifend nisl molestie. Nulla quis ligula at mauris rhoncus vestibulum. Maecenas at nulla ipsum. Donec rutrum congue leo at malesuada. Integer auctor tristique sem, vitae lacinia sem sagittis sed. Nullam auctor, enim nec pellentesque aliquam, arcu dui lacinia mauris, id lobortis enim odio id felis.
代码实现
<style>
img {
float: left;
shape-outside: circle(50%); /* 50% of the element's width */
padding: 5px;
border-radius: 50%;
}
</style>
<img src="https://picsum.photos/id/238/200/200.jpg" />
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus lacinia odio vitae vestibulum vestibulum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed
blandit ligula non leo cursus, vitae eleifend nisl molestie. Nulla quis ligula at mauris rhoncus vestibulum. Maecenas at nulla ipsum. Donec rutrum congue leo at malesuada. Integer auctor tristique
sem, vitae lacinia sem sagittis sed. Nullam auctor, enim nec pellentesque aliquam, arcu dui lacinia mauris, id lobortis enim odio id felis.
</p>行盒的截断样式 box-decoration-break
box-decoration-break 属性用来定义当元素跨多行、多列或多页时,元素的片段应如何呈现。
/* Keyword values */
box-decoration-break: slice;
box-decoration-break: clone;
/* Global values */
box-decoration-break: initial;
box-decoration-break: inherit;
box-decoration-break: unset;Lorem ipsum, dolor sit amet consectetur adipisicing elit. Provident quidem fugiat architecto. Hic blanditiis laborum culpa fuga quia neque eum, repellat tenetur voluptatum inventore numquam aspernatur totam eveniet quae qui!
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Provident quidem fugiat architecto. Hic blanditiis laborum culpa fuga quia neque eum, repellat tenetur voluptatum inventore numquam aspernatur totam eveniet quae qui!
代码实现
<style>
.content {
width: 600px;
margin: 0 auto;
line-height: 2;
}
.highlight {
background: linear-gradient(#d5e8b7, #bad6b3);
border: 1px solid #7e876b;
padding: 0 4px;
border-radius: 5px;
}
.word-wrap {
box-decoration-break: clone;
}
</style>
<div class="content">
<p>
<span class="highlight">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Provident quidem fugiat architecto. Hic blanditiis laborum culpa fuga quia neque eum,</span> repellat tenetur
voluptatum inventore numquam aspernatur totam eveniet quae qui!
</p>
<p>
<span class="highlight word-wrap">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Provident quidem fugiat architecto. Hic blanditiis laborum culpa fuga quia neque eum,</span>
repellat tenetur voluptatum inventore numquam aspernatur totam eveniet quae qui!
</p>
</div>field-sizing
CSS field-sizing 是一个 CSS 新特性,专门给输入型表单元素使用的,例如 <input>、<textarea> 元素等。
是这样的,在过去,无论是单行输入框,还是多行文本域,其宽度在内容输入的时候,都是固定的,如果希望尺寸跟着内容的宽度走,需要使用 JavaScript 代码帮忙处理,现在,无需这么麻烦,使用field-sizing 设置下就好了,例如:
<style>
input {
/* fixed是默认值,表示尺寸固定。 */
/* content表示尺寸根据内容多少进行变化。 */
field-sizing: content;
}
</style>
<input placeholder="输入内容" />此时,你在输入框内键入内容,可以看到,输入框的宽度基于你输入的内容多少自动撑大或缩小了。
说明
- 当输入框设置了
field-sizing:content声明的时候,原本会影响尺寸的 size 属性就会变得无效。 textarea元素的rows和cols属性也会无效。field-sizing属性也可以用在<select>元素上。- 实际使用的时候,可以配合
min-width和max-width属性限制输入框的最小尺寸和最大尺寸。避免内容过多的时候,影响排版布局。