作为一名天天和样式表打交道的前端我几乎每天都能在技术群里看到类似的问题两栏布局怎么写更稳、rotateY配translateZ出来的效果到底长什么样、涟漪光圈扩散用box-shadow还是伪元素做。这些问题看着零散其实都落在“布局”和“视觉样式”这两块主战场里。这篇全攻略就是我基于这些高频场景的一次系统梳理从布局选型、3D变换原理到动效细节、样式引入机制再到排查实战争取把平时最容易翻车、最容易被一笔带过的细节都摊开来讲清楚。不管你是刚入门的前端新手还是被抽调来写页面后端的同学只要能耐心顺着这篇走一遍日常开发里九成以上的CSS问题都能找到对应的解法。1. 布局方案的选型与核心思路拆解1.1 flex布局90%场景下的首选方案CSS布局演化到今天flexbox已经是当之无愧的日常主力。我自己的经验是不管接到什么页面先看结构能不能用flex解决——绝大多数情况下能。flex的核心思路就是“给容器一个轴”主轴main axis和交叉轴cross axis。容器上设display: flex之后子项默认沿着主轴排成一行这是理解所有flex行为的前提。真正让flex好用的是三条规则.container { display: flex; justify-content: center; /* 主轴对齐 */ align-items: center; /* 交叉轴对齐 */ gap: 12px; /* 子项间距亲爹级好用 */ }gap是让我从float时代过来的人最感动的属性。以前想给一排按钮加间距得用margin还要处理首尾多余的边距现在一行gap解决而且flex、grid通用。实测下来现代浏览器全部支持项目里可以放心用。再往下就是子项的弹性系数。flex: 1意味着子项会“瓜分”剩余空间这是做左右两栏布局的关键武器。举个例子经典的后台页面布局——左侧固定200px的导航右侧自适应内容区.layout { display: flex; min-height: 100vh; } .sidebar { flex: 0 0 200px; /* 不放大、不缩小、固定200px */ } .main { flex: 1; /* 吃掉所有剩余宽度 */ }这套写法比float方案不知道稳了多少倍。以前用float: left做侧边栏右边内容区还要算宽度、处理margin-left一旦内容多了还会被挤下去现在flex: 1天然吸收剩余空间浏览器自动计算完全不用手算百分比。我在实际项目中遇到“左右两栏布局”的需求90%都是这么写的。不过flex也不是没有坑最大的坑叫“最小尺寸问题”。当flex子项里的内容超长比如一长串没空格的英文URL子项会被内容撑破导致布局溢出。解决方案是给子项加上min-width: 0允许它收缩到比内容更窄让内部元素自己处理换行或省略。这个问题排查起来特别隐蔽因为表面上看是“文字把布局挤爆了”实际是flex的默认min-width: auto在作祟。1.2 grid布局与左右两栏布局的取舍flex擅长一维排列横着排或者竖着排grid擅长二维布局同时控制行列。这么说还是抽象我举个实际对比一个卡片列表电脑上显示4列平板上2列手机上1列。用flex实现你得嵌套好几层容器或者反复设置flex-wrap再加百分比宽度用grid就是一行事.card-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; }repeat(auto-fill, minmax(240px, 1fr))的意思是每一列最小240px如果容器够宽就多排几列不够就换行列数完全自适应。minmax这支语法是grid的精髓它限制了弹性范围比flex里手动算百分比优雅太多。左右两栏其实也可以用grid写而且语义更直观.layout { display: grid; grid-template-columns: 200px 1fr; min-height: 100vh; }这行的意思是“两列第一列200px第二列占满剩余空间”。跟flex方案相比grid不需要给子项写任何flex属性容器上就把所有规则定完了。我更推荐在“整页骨架明确、列数固定”的场景用grid而在“内部元素数量不定、需要灵活换行排列”的场景用flex。两个工具配合使用才能应对不同设计稿。顺带说一句早年还有浮动布局、inline-block布局、表格布局这些老方案。浮动布局是为了图文混排设计的硬拿来搭页面骨架会引发高度塌陷、清除浮动等一系列问题inline-block布局受空白字符影响严重元素之间有莫名空隙表格布局虽然当年兼容性最强但结构臃肿改样式困难。这些方案现在只作为了解即可新项目不建议碰。如果谁手头还维护着用float搭的旧项目下一个部分我会把清除浮动的标准做法拿出来讲。1.3 老牌布局方案的清理工作清除浮动的正确姿势“清除浮动”这个词对很多年轻前端来说是历史名词了但如果你维护过老后台、接到过老外包项目几乎一定会碰到。浮动float的本意是实现文字环绕图片元素浮起来以后就脱离了文档流父容器包裹不住它表现出来就是父容器高度塌陷背景色或者边框只显示一小截。清除浮动最主流的写法是clearfix我在代码里已经写过无数次.clearfix::after { content: ; display: block; clear: both; }原理就是给父容器加一个看不见的::after伪元素把它设置为块级并clear: both让它去“顶住”下面已经浮动的兄弟元素从而把父容器的高度撑回来。这套方案兼容性极佳从IE6时代用到现在。除clearfix之外还有两个讨巧的替代方案。一个是父容器直接display: flow-root现代浏览器都支持一行代码就能建立一个新的块级格式化上下文BFC干净利落另一个是父容器overflow: hidden原理同样是创建BFC但要注意如果父容器里有需要溢出的下拉菜单或气泡提示会被裁掉。实际工作中我的建议是老项目就老老实实加clearfix类新项目直接用flex/grid根本不需要清除浮动。浮动清理是历史遗留问题能做是技术储备但别在新技术栈里主动制造这种麻烦。2. 视觉样式的细节与3D变换原理2.1 transform 3D一次搞清rotateY和translateZ的组合效果搜索量最高的一个CSS问题是transform: rotateY(60deg) translateZ(300px)到底是什么样子。这问题很有代表性因为3D变换的书写顺序、坐标方向、正负规则哪怕写了好几年的前端也经常搞混。先给结论这个效果是“把元素先绕Y轴旋转60度再沿着旋转后的Z轴方向平移300px”。很多人以为transform是从左到右依次执行其实它的执行顺序是从右往左的也对应矩阵乘法的顺序。这里坑就出来了名字从左读到右像是先旋转再平移实际计算是从右往左先平移再旋转不很多人在这里都会卡壳我仔细说。CSS的transform列表是“先写后作用”的——表面的顺序看起来是这样rotateY(60deg) translateZ(300px)实际执行时是元素先被translateZ(300px)移动再被rotateY(60deg)旋转。但是要注意坐标系是跟着元素自身走的。最终效果等于元素先沿着自己原始的Z轴向前移动了300px然后整个坐标系绕原点或者说绕垂直于屏幕平面的竖轴旋转60度。所以最终我们看到的是“一个往屏幕外飞了300px的面又被顺时针拧了个角度”。这也是新手最容易迷的地方——不是“先站在原地转60度再飞”而是“先飞出去再转身”。还有一种理解方式是把它看作嵌套变换整个变换等价于“元素本身先平移到距屏幕300px的位置再在那个位置上自身旋转60度”。你可以用一张卡片的例子来想你把一张卡片举起距离眼睛300pxtranslateZ然后把卡片绕竖直旋转60度rotateY那最终卡片是斜着立在你面前的。这个知识最常见的落地场景是旋转木马轮播图、卡片云、3D相册。一个典型的三维空间容器代码是这样的.scene { perspective: 800px; /* 让子元素产生近大远小的纵深 */ } .card { transform-style: preserve-3d; transform: rotateY(60deg) translateZ(300px); }perspective非常关键没有它3D效果完全出不来。它表示“观察者离元素的距离”值越小透视效果越强烈变化越夸张值越大透视越平缓。800px是一个比较舒服的起始值像人坐在电脑前看屏幕的距离。transform-style: preserve-3d让卡片在父场景里保留立体空间位置而不是被压平到父元素的平面上。2.2 3D旋转正负判断的核心规则CSS 3D旋转的另一个大坑是判断正负方向。网上有各种口诀“正数是顺时针吗”“rotateX正数往上还是往下”看十篇帖子有八种说法。不废话直接说可以验证的规则。CSS 3D遵循右手坐标系x轴向右、y轴向下、z轴指向屏幕外。这个坐标系方向和传统数学课本里的不一样——数学里y轴往上CSS里y轴往下所以很多直觉会失灵。绕轴的旋转方向采用左手定则去判断原因在CSS规范里就是这么定义的意思是用左手拇指指向轴的正方向其余四指弯曲的方向就是正角度旋转的方向。用这个规则来推rotateX正角度左手拇指指向x轴正方向屏幕右边手指弯曲方向是从屏幕上方翻向下方所以元素的上边会向后倒下边向前翘。效果就是“向前俯身”倒下去。负角度则是“向后仰”。rotateY正角度左手拇指指向y轴正方向屏幕下方手指弯曲方向相当于元素左边朝后、右边朝前表现为“右侧朝向你转过来”顺时针拧动从上往下看是逆时针但直接看屏幕就是右转。rotateZ正角度左手拇指指向z轴正方向屏幕外手指弯曲方向从x轴正方向转向y轴正方向元素是逆时针旋转——等等这里最容易搞错我再严谨一点rotateZ的正角度在屏幕上看到的效果是逆时针旋转而很多人以为是顺时针实测会打脸。如果记不住左手定则我这里给一个零基础也能用的验证方法打开浏览器控制台随便找个元素给它加一行transform: rotateY(10deg)观察它是往左还是往右再改成rotateY(-10deg)对比。只要实测验一次你的肌肉记忆就建立了。我个人的记忆锚点是“rotateY正角度元素右半边朝你转过来rotateX正角度元素顶部向后倒”。再多说无益手试胜过一切理论。2.3 字体渐变与文本修饰的落地写法视觉样式里最有区分度的效果一个是字体渐变填充另一个是删除线等文本修饰。两者都是高频需求但很多人第一反应是找设计出切图其实CSS一行就能做到。字体渐变用的是background-clip: text这一招.gradient-text { background: linear-gradient(45deg, #667eea, #764ba2); -webkit-background-clip: text; background-clip: text; color: transparent; /* 关键一步把文字原本颜色变透明 */ }原理是先给元素铺渐变背景再用background-clip: text把背景裁剪成文字的形状最后把字体颜色设成透明露出来的就是渐变背景的形状。三个条件缺一不可尤其是color: transparent忘掉的话文字原色会把渐变盖住效果直接翻车。实测这个特性在Chrome、Edge、Safari和Firefox的最新版本都支持前缀写法保留一份-webkit-以防旧版本浏览器。文本修饰方向最基础的是删除线.del { text-decoration: line-through; }字面意思很简单但我提醒一点del标签本身在浏览器里有默认的删除线样式但如果你想统一控制删除线的颜色、粗细、位置可以直接写text-decoration-color、text-decoration-thickness、text-decoration-offset这几个属性。比如红字配灰删除线或者故意把删除线和文字拉开距离这种细节才是“视觉样式攻略”里能拉开差距的地方。.del { text-decoration: line-through; text-decoration-color: #999; text-decoration-thickness: 2px; text-decoration-offset: 6px; }商品列表的划线价、公告里的历史通知、待办事项的已完成标记都能用这套属性做得很精致。3. 动效与交互状态从涟漪光圈到鼠标移入3.1 涟漪光圈扩散效果的实现路径“CSS涟漪光圈扩散”这两年搜索量很大常见场景是按钮点击反馈、水波纹菜单、相机聚焦动画。实现路径有两条一条简单直接一条性能更优。先看入门做法用box-shadow扩散.ripple { width: 120px; height: 120px; border-radius: 50%; box-shadow: 0 0 0 0 rgba(0, 120, 255, 0.5); animation: ripple-ani 1.2s ease-out infinite; } keyframes ripple-ani { to { box-shadow: 0 0 0 40px rgba(0, 120, 255, 0); } }这段的原理是让box-shadow从半径为0、颜色半透明逐步扩到半径40px、颜色全透明。视觉上就像一圈光圈从圆心荡开并逐渐消失。优点是代码极少缺点是渲染阴影的代价高如果把动画放在大面积的列表每个条目上一屏几十个同时扩散低端手机会有明显的卡顿。做单点按钮的点击反馈完全够用做瀑布流就不明智了。更优雅的方式是用::after伪元素加scale变换加opacity渐变伪元素就是“一个随动画而生的圆形光波”.ripple { position: relative; overflow: hidden; width: 120px; height: 120px; border-radius: 50%; background: #4f7cff; } .ripple::after { content: ; position: absolute; inset: 0; border-radius: 50%; background: rgba(255, 255, 255, 0.5); transform: scale(0); opacity: 1; animation: ripple-wave 1.2s ease-out infinite; } keyframes ripple-wave { to { transform: scale(2.5); opacity: 0; } }scale和opacity都属于合成器友好的属性浏览器可以直接交给GPU处理动画全程不掉帧。这是我更推荐的生产级方案。如果你想让光圈只扩散一次而不是无限循环把animation里的infinite去掉就行。3.2 CSS鼠标移入交互的边界与hover实战“CSS鼠标移入事件”这个搜索词其实问法不准确CSS里没有“事件”只有“状态”选择器。鼠标移入对应的是:hover加上:focus键盘聚焦、:active鼠标按下和:focus-within自身或后代聚焦组成一套完整的交互状态体系。:hover最简单的用法是直接改自身样式.btn:hover { background-color: #356cff; transform: translateY(-2px); box-shadow: 0 6px 16px rgba(53, 108, 255, 0.3); }这里有个众所周知但总有人丢的细节hover的过渡要写在“默认状态”上而不是hover状态上。如果写在hover里鼠标移入时有过渡移出时瞬间变回去视觉上特别生硬。正确写法是把transition放在btn本身上让移入移出两个方向都有过渡。:hover还能配合子选择器实现“悬停父元素控制子元素”这是做卡片交互的利器.card:hover .card-title { color: #356cff; } .card:hover .card-more { opacity: 1; transform: translateY(0); }鼠标悬停在卡片上标题变色、按钮浮现这种交互在电商商品卡片、后台列表行上随处可见。要注意的是CSS里只有“子元素选择器”这种从上到下的方向没有“父选择器”。想通过悬停某个子元素去控制其他位置的兄弟元素就得依靠父容器回勾把hover挂在父容器上就像上面的.card:hover .card-title。能这样解决的就不用上JavaScript。还有一个移动端相关提醒:hover在触摸设备上有点特殊手指点击时也会触发hover态并且可能“粘住”不消失。实际项目里会在全局样式里关掉触摸端的hovermedia (hover: none) { .btn:hover { background-color: initial; transform: none; box-shadow: none; } }这个细节很多教程不会讲但在实机测试里非常关键不然手机上按钮一碰就变蓝、拿开不变样用户的感受很差。3.3 中心对齐与文本定位的几个正确姿势“css中心对齐”也是被搜索次数爆表的关键词。中心对齐分为块级元素居中和文本居中两者思路完全不同我把常见场景全部列一下方便直接对号入座。文本水平居中一行text-align: center。文本垂直居中如果是单行文本且高度固定可以用line-height等于容器高度.badge { height: 32px; line-height: 32px; text-align: center; }这段在老项目和标签类小元素里依然好用但如果文本变成两行这个方案直接失效文字会跑到容器外去。多行文本垂直居中推荐flex或grid.container { display: flex; align-items: center; justify-content: center; text-align: center; }块级元素垂直水平居中业界公认最稳的是flex三行法display: flex align-items: center justify-content: center。这个组合通吃绝大多数现代布局。还有一些绝对定位的居中方案比如position: absolute配合top: 50%; left: 50%; transform: translate(-50%, -50%)这种写法适合浮层、弹窗徽标这类脱离文档流的元素。注意transform的百分比是相对于元素自身尺寸所以先用50%定位到容器中心再平移自身一半尺寸回来才是真正的居中。网上还有一种margin: auto配合绝对定位的居中方案.modal { position: absolute; inset: 0; margin: auto; width: 400px; height: 300px; }这个技巧冷门但好用它利用“绝对定位元素上下左右都为0时margin: auto会自动吃满剩余空间”的特性。但它要求元素必须有确定的宽高否则会塌缩成0宽0高这点要特别注意。4. CSS的引入机制与选择器优先级4.1 样式引入的三种方式与优先级终局之战CSS样式的引入方式总共有三种外部样式表、内部样式表、内联样式。很多人一学就会但一接到“为什么我改了样式不生效”的问题就开始乱试核心是没有把优先级规则刻在脑子里。外部样式表就是link relstylesheet hrefstyle.css推荐在head里引避免页面出现无样式闪烁。内部样式表是写在style标签里适合单页小demo。内联样式是写在元素style属性里——优先级最高比id选择器还高除了!important这点后文说。优先级的层叠计算规则是内联样式 ID选择器 类选择器/属性选择器/伪类 标签选择器/伪元素 通配符。在实际开发中我强烈建议把CSS文件作为唯一来源内联样式能不用就不用因为内联样式写死在HTML里复用性为零而且后面想调整还得去改HTML维护成本成倍上升。关于!important我建议把它当成禁区。它能把单个样式的优先级直接提到最顶层看起来是解法实际上是饮鸩止渴。一个项目里只要出现两三次!important后面任何人再调试样式都会疯。真正想覆盖别人样式的时候先看自己选择器是不是给得太宽了比如直接用.btn这种类名不如加一层.main-content .btn提高权重这样既不动全局样式也不至于破坏优先级结构。有一点容易踩坑外部引入时link是并行加载样式的性能更好而import写在CSS文件内部是串行加载越多的import会拖慢渲染。手头老项目里如果看到CSS头部一溜烟的import建议逐步改成link页面首屏体验能明显提升。4.2 选择器优先级计算与常用选择器大盘点选择器是CSS的寻址系统用好了能写出一版既精简又健壮的样式。基础的四类就不展开说了重点聊聊实战中最高频的进阶选择器。属性选择器[typetext]选中所有文本框[data-stateopen]做状态驱动样式特别方便。结构伪类:nth-child(odd)给列表奇数行加底色:not(.disabled)排除掉禁用的按钮。组合器空格表示后代表示直接子元素表示相邻兄弟~表示后续兄弟。其中“相邻兄弟选择器”很适合做表单控件后跟错误提示的联动比如.input-error .tip。逻辑伪类:is()和:where()可以把一串选择器合并比如h1:is(.title, .main-title)这样不用重复写元素名。优先级的具体数值计算业内普遍用四位计数法来理解内联是(1,0,0,0)ID是(0,1,0,0)类/属性/伪类是(0,0,1,0)标签/伪元素是(0,0,0,1)。比较时从高位往低位逐位比。举个例子#app .card .title .name优先级是(0,1,0,2)——1个ID加2个类加1个标签。不同选择器的优先级不会自动相加超过上一级也就是说十个类选择器加起来也比不过一个ID。这个规则看起来枯燥却是排查“样式被谁覆盖了”的唯一钥匙。在DevTools的Elements面板里选中元素右侧Styles栏会从上到下显示所有匹配到的规则最下面一条通常是最优先的。如果一条规则被划掉大概率是同一属性在别的规则里优先级更高或写在了后面。4.3 文本换行、省略号与溢出处理的细节规范文本溢出处理是CSS日常里“看起来很简单做起来一堆坑”的典型。单行省略号是前端面试经典三件套.ellipsis { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }white-space: nowrap禁止换行overflow: hidden截断溢出内容text-overflow: ellipsis在截断处显示三个点。三个缺一不可忘掉text-overflow就只是个生硬截断。多行省略号目前最通用的写法依然需要-webkit-前缀.multiline-ellipsis { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }line-clamp直接指定显示两行超出部分隐藏。这个写法虽然带着-webkit-前缀但现在所有主流浏览器都能识别。唯一的局限是它只对块元素生效inline元素需要先转成块或flex容器。还有一个容易忽略的场景表格单元格里的长内容。表格默认的布局算法table-layout: auto会根据内容自动调整列宽导致整行被撑超。想控制列宽并让内容省略要把表格改成固定布局——table-layout: fixed然后配合word-break: break-all或者省略号那三件套。如果遇到的是英文不换行问题根源在word-break或overflow-wrap给容器加上word-break: break-word通常能解决长URL把布局撑破的问题。5. 常见问题与排查技巧实录5.1 布局重叠问题排查指南布局重叠是“css布局”热词下的高频问题典型场景有弹层遮不住底下的内容、两列内容交错叠在一起、卡片上下互相压住。我把自己排查重叠的固定流程分享出来。第一步在DevTools里选中重叠的元素看它的位置定位。绝大多数重叠都跟position有关元素一旦设为relative、absolute、fixed就会出现层叠的可能。如果发现两个元素都是absolute且都没有设置top/left/right/bottom之外的同级定位参照它们就会重叠在容器的左上角。第二步确认层叠上下文。z-index只在“同一个层叠上下文”内比较大小。元素设置为position: relative加上z-index: 999如果父元素本身有一个opacity: 0.9或者transform属性它可能会创建局部层叠上下文子元素再大的z-index也没法和外部元素比较。这是排查时最隐蔽的环节我印象里有过一次弹窗死活盖不住底部内容折腾了半小时最后发现是弹窗父容器设了transform: translateY(0)形成层叠上下文把弹窗的z-index: 9999封印在里面了。第三步检查是否存在负margin或translate负值造成的视觉重叠。这种一般不是bug而是布局特性但如果出现了不想要的效果移除负值或改用flex/grid重建结构。5.2 IE11下样式失效的关键排查点“html网页ie11打开css样式失效”这个问题虽然年头不短但至今仍有企业内网用户在用IE11。如果你遇到了这种需求我的核心建议是不要直接在老浏览器里硬调而是用自动化工具降级。IE11有几个著名的兼容短板不支持CSS自定义属性CSS变量var(--xxx)直接失效不支持display: grid的现代写法flexbox只支持到旧版本规范不支持gap属性不支持position: sticky。此外calc在flex布局内部经常失效vw/vh单位在某些场景下也会异常。与其手动改代码更靠谱的做法是用构建工具加Autoprefixer它能自动为老浏览器补私有前缀以及部分属性的降级写法。gap这种没法自动降级的就老老实实改用margin或者双列布局不用gap实现。如果连构建工具都没有纯静态页面想兼容的话做布局时尽量用最保守的组合块级元素加float加百分比宽度。虽然又回到了老布局但在“兼容IE”这个前提条件下这是性价比最高的方案。字体渐变、3D变换这类视觉特性在IE11上直接放弃是最明智的浏览器本身不支持硬做也是白费力气。另外检查IE兼容问题时记得用F12开发者工具里的浏览器模式切换用真实IE内核模拟切不要靠猜很多比IE新版更奇怪的问题反而不会出现。5.3 file协议下样式无法加载的原因与处理搜索词里有条长得离谱的错误信息access to css stylesheet at file:///c:/users/...。这是典型的“用浏览器直接双击打开本地HTML文件”时遇到的跨域限制。浏览器出于安全策略在file://协议下访问本地资源时安全限制非常严格。当你双击打开一个HTML里面通过相对路径引用style.css浏览器可能会拦截这个本地CSS文件报出“Cross origin requests are only supported for protocol schemes”之类的错误就算文件明明就在旁边也加载不了。解决方案分几个层次。第一在IDE里装一个本地服务器插件比如VS Code里的Live Server一键起服务用http://localhost:5500访问页面。这是我最推荐的方式因为本地服务器还能处理后续的AJAX请求、模块加载等更多问题。第二如果是临时看个样式也不想装插件可以试试把CSS内容直接复制到HTML文件里的style标签中从“外部引入”变成“内部样式”。这能绕开file协议下的跨域限制但只适合临时验证。第三如果页面引用了字体文件、图片、视频这些外部资源同样会有类似问题所以一并用本地服务器开发是正道。这也是所有前端项目开始前最值得先做的一步基础建设。5.4 几个高价值细节速查表最后把上面零散提到的写法整理成一张可直接参考的速查表方便收藏后用。场景推荐写法关键注意事项左右两栏display: grid; grid-template-columns: 200px 1fr;列数固定用grid内部动态用flex垂直水平居中display: flex; align-items: center; justify-content: center;最稳别用line-height拼多行单行省略white-space: nowrap; overflow: hidden; text-overflow: ellipsis;三个属性缺一不可多行省略display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;记得加overflow: hidden字体渐变background: linear-gradient(...); background-clip: text; color: transparent;color必须透明3D空间父容器perspective: 800px子元素transform-style: preserve-3d没有perspective就没有纵深涟漪扩散::after伪元素 scaleopacity动画避免用box-shadow大面积动画清除浮动.clearfix::after { content: ; display: block; clear: both; }新项目建议直接flex鼠标移入过渡transition写在默认状态hover只写目标状态移出也有过渡才自然这些内容我在项目里反复验证过尤其是grid列数自适应、3D旋转顺序、字体渐变裁剪这三点属于那种“以为会了但实际一写就会卡壳”的典型。如果你能把这套攻略里的代码全部实测一遍再遇到CSS的布局和视觉样式需求基本不会束手无策。我最后一次建议是别一次性贪多打开一个空页面从flex两栏开始练再试着做一个带涟漪光圈的按钮然后给按钮加上3D倾斜的hover效果。等你完成这三个小练习这篇攻略至少一半的价值就已经落到你手里了。