CSS
快来分享你的内容吧~
- 04-24 14:00·前端开发如何实现一个三角形? 原理:border 在前端 CSS 里,要把方块转变为三角形,主要借助边框属性来实现。下面为你介绍具体的实现方法: 实现方法 原理:元素的border是由三角形组合而成 宽高设为 0:把元素的宽度和高度都设成 0,这样元素本身就不会占据空间。 利用边框:通过设置不同方向的边框,让它们相互叠加,从而形成三角形。 控制边框颜色:将左右边框的颜色设为透明,底部边框设置成你想要的颜色查看全文加油鸭:太棒了!这份前端知识整理得既系统又深入,从三角形实现到盒模型、BFC、性能优化,全是硬核干货,看得出你下了大功夫梳理和理解~为你点赞!232分享
- 04-07 17:31·Java后端
- 2025-04-06·Java后端
写完这个微信风格按钮页面,我终于吃透了BEM命名+CSS重置
> 之前写页面一直有两个痛点,折磨我好久。 > > 一是**class命名**,每次都绞尽脑汁瞎编,写一个页面能冒出十几种命名风格,后续改代码完全找不到对应样式;二是页面默认样式乱飞,不同标签自带边距、行高,每次都要手动微调,越写越乱。 > 帅哥美女们帮我的掘金点点赞呗😘👍 完整文章地址👉:https://juejin.cn/post/7646728363236753449 直到这次手写一套微信风格的按钮页面,全程用规范写法落地,才算彻底搞懂了 **CSS Reset** 和 **BEM命名规范** 的真正用处,不是死板的八股文,是真的能救命的开发套路。 ## 先说说最基础的:为什么坚决不用 \* 通配符重置样式? 我之前图省事,重置样式永远一行代码搞定: ```js /* 千万别再这么写了! */ * { margin: 0; padding: 0; } ``` 当时觉得万能,直到慢慢踩坑才发现问题。 说实话,通配符是**贪婪匹配**,会把页面所有标签全部遍历一遍,不管你有没有默认样式,统统重置。页面标签少的时候没感觉,项目复杂后,性能损耗肉眼可见。 而且最坑的一点:很多原生标签的默认有用样式会被一刀切干掉,后续还要自己额外补样式,纯属多此一举。 现在我彻底换成了行业通用的「**全元素枚举重置方案**」,也就是我这次代码里用的规范写法。 html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; box-sizing: border-box; } 这套写法的核心逻辑特别简单:**只重置有默认样式的标签,精准清洗,不瞎遍历**。 相当于把浏览器自带的乱七八糟的默认样式,全部抹平,把页面变成一张干净的白纸,后续所有样式都由我们自己掌控,不会出现莫名其妙的边距、偏移。 **小补充**:这也是 normalize.css 的核心思路,不暴力通配,精准重置、兼容所有浏览器的样式差异。 另外我还补了几个高频元素的通用重置,解决日常开发90%的兼容问题: /* HTML5新标签统一转为块级元素,兼容旧浏览器 */ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; } /* 清除列表默认样式 */ ol, ul { list-style: none; } /* 清除超链接默认下划线、默认颜色继承父级 */ a { text-decoration: none; color: inherit; } /* 表单元素统一继承字体,清除默认边框和外发光 */ button, input, select, textarea { font: inherit; background: transparent; border: none; outline: none; } ## 告别瞎命名!BEM 规范真的太香了 以前写class,完全是随心所欲。头部就写top、header,主体就写main、content,写着写着命名全乱,复用和改代码都巨麻烦。 这次写页面全程用**BEM 国际命名规范**,写完瞬间明白,为什么大厂全都强制用这套规则——它根本不是约束,是开发提速神器。 先用人话翻译一下BEM的核心逻辑,不用记官方定义: * **B(Block 区块)** :独立的、可以单独复用的大模块,比如我页面里的 `page` 整个页面区块、`weui-btn` 按钮模块 * **E(Element 元素)** :区块内部的子元素,不能独立存在,用 `__` 连接,比如 `page__hd` 页面头部、`page__bd` 页面主体 * **M(Modifier 修饰符)** :用来区分同一模块的不同状态/样式,用 `_` 连接,比如 `weui-btn_primary` 主按钮、`weui-btn_default` 次要按钮 放一下我这次写的完整结构,一眼就能看懂: <!-- BEM规范完整结构演示 --> <div class="page"> <!-- 大区块 Block --> <header class="page__hd"><!-- 区块内元素 Element --> <h1 class="page__title">这是一个页面</h1> <p class="page__desc">这是一个页面的描述</p> </header> <main class="page__bd"><!-- 区块内元素 Element --> <div class="button-sp-area"> <a href="#" class="weui-btn weui-btn_primary">主要按钮</a> <!-- 修饰符 Modifier --> <a href="#" class="weui-btn weui-btn_default">次要按钮</a> </div> </main> </div> 说说我用下来最直观的几个好处: 第一,**结构一目了然**。看到class名就知道层级关系,`page__hd` 必然属于page区块的头部,不会出现层级混乱的问题。 第二,**彻底解决命名困难**。不用再绞尽脑汁想复杂英文单词,只需要区分「区块、元素、状态」,简单清晰,团队协作也不会出现命名冲突。 第三,**样式复用性拉满**。像weui-btn这个按钮组件,只需要通过修饰符区分主次样式,核心样式统一维护,不用重复写代码。 ## 细节拉满!复刻微信UI的小技巧 这次的页面是模仿微信UI的样式,写完发现大厂的UI细节是真的讲究,没有一个数值是乱写的。 最让我印象深刻的就是按钮的行高,设计师标注的`line-height: 1.41176471`,一开始我懵了,为什么要精确到8位小数? 后来一算才懂:按钮字体大小是17px,设计师要求按钮整体高度24px,24/17 刚好就是这个小数。**用相对行高适配不同场景,比固定行高更兼容、更美观**。 .weui-btn { position: relative; display: block; min-width: 184px; max-width: 280px; margin-left: auto; margin-right: auto; padding: 12px 24px; font-weight: 500; font-size: 17px; text-align: center; text-decoration: none; color: #fff; line-height: 1.41176471; /* 重点:24/17 精准适配UI高度 */ border-radius: 8px; -webkit-tap-highlight-color: rgba(0, 0, 0); user-select:none; } 还有一个很实用的细节:`-webkit-tap-highlight-color: transparent`,清空移动端点击高亮背景,`user-select: none` 禁止按钮文字选中,都是移动端页面的必备细节。 另外我用到了一个很省心的选择器,专门处理按钮间距: /* 只给后面的按钮加上边距,避免第一个按钮顶部多余间距 */ .weui-btn+.weui-btn { margin-top: 12px; } 相邻兄弟选择器真的太好用了,不用额外加class,就能统一处理同类元素的间距,页面更整洁。  ## 我踩过的两个低级坑 这次写的过程中,两个坑卡了我不少时间,分享出来大家直接避开: ### 坑1:忘记给根标签设置高度 一开始写完样式,页面高度塌陷,背景色只铺满内容区域。排查半天发现,没有给html、body设置满屏高度。 **正确姿势**:全局设置视口高度,保证页面满屏展示 html, body { height: 100vh; background-color: #ededed; } ### 坑2:混淆BEM的连接符 刚开始写的时候,把元素和修饰符的符号写混了,用 `page-hd`、`weui-btn__primary`,导致样式全部不生效。 记死这个规则就不会错:**区块和子元素用双下划线 \_\_,模块和状态修饰符用单下划线 \_** 。 ## 最后梳理下这次的核心收获 折腾完这一整套代码,不再是只会抄代码的小白,对页面布局和CSS规范有了实打实的认知: 1. **CSS Reset 拒绝暴力通配符**,枚举标签精准重置,兼顾性能和兼容性,是正式项目的唯一选择。 2. **BEM 规范是前端必备基本功**,不是花架子,能彻底解决命名混乱、层级不清、样式难复用的问题,团队协作效率翻倍。 3. **UI细节决定页面质感**,看似奇怪的小数行高、间距、移动端适配属性,都是为了还原设计师的精准效果。 当然也想说一句,BEM不是万能的。简单的静态页面、个人demo页面没必要强行用,过度规范反而累赘。但**企业项目、复用性高的组件、团队协作项目**,一定要坚持用,收益真的巨大。 如果你之前也跟我一样,写样式全靠瞎写、命名全靠随缘,建议亲手敲一遍这套代码,跑完绝对有不一样的感悟。 搞懂的朋友可以评论区留个言,说说你之前踩过的CSS命名的坑,一起交流下~
面试官:问几个简单的CSS吧
## 如何实现一个三角形? **原理:border** 在前端 CSS 里,要把方块转变为三角形,主要借助边框属性来实现。下面为你介绍具体的实现方法: `.triangle { width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px solid transparent; border-bottom: 100px solid #3498db; }` **实现方法** 原理:元素的border是由三角形组合而成 - 宽高设为 0:把元素的宽度和高度都设成 0,这样元素本身就不会占据空间。 - 利用边框:通过设置不同方向的边框,让它们相互叠加,从而形成三角形。 - 控制边框颜色:将左右边框的颜色设为透明,底部边框设置成你想要的颜色,这样就呈现出一个朝上的三角形。 改变三角形的方向: - 朝上的三角形:左右边框透明,底部边框设置颜色。 - 朝下的三角形:左右边框透明,顶部边框设置颜色。 - 朝左的三角形:上下边框透明,右边框设置颜色。 - 朝右的三角形:上下边框透明,左边框设置颜色。 下面是一个朝下三角形的示例: `.triangle-down { width: 0; height: 0; border-left: 50px solid transparent; border-right: 50px solid transparent; border-top: 100px solid #e74c3c; }` **Flex:1 和 Flex auto 的区别?** 在 Flexbox 布局中,flex: auto 和 flex: 1 是两个不同的简写值,简写语法如下 ini 体验AI代码助手 代码解读复制代码flex: [flex-grow] [flex-shrink] [flex-basis]; flex-grow 定义如何瓜分主轴上的剩余空间,默认值是 0,即使还有剩余空间也不瓜分。 - 数值越大,分配到的剩余空间越大(按比例来,如下图所示) - 计算方式:剩余空间 x,flex-grow 的值分别为 a,b,c - 每个元素可以分配的剩余空间为: a/(a+b+c) * x,b/(a+b+c) * x,c/(a+b+c) * x 以A为例:1/(1+2+3) = 1/6,A“瓜分”到的 150*1/6=25,实际宽度为100+25=125。 flex-shrink 由于 flex 默认不换行,所以当父容器空间不足时,则将子元素“收缩”,默认值为 1(即空间不够时会缩小) 数值越大,收缩比例越高(如下图) 计算方式:三个元素的宽度为 w1 w2 w3,flex-shrink 分别为 a,b,c,以 A 元素为例计算 - 计算总压缩权重: sum = a * w1 + b * w2 + c * w3(300 * 1 + 150 * 2 + 200 * 3 = 1200) - 计算每个元素压缩率: S1 = a * w1 / sum(300*1 / 1200 = 0.25) - 计算每个元素宽度:width - 压缩率 * 溢出空间(300 - (150 * 0.25) = 262.5) 注意: - 如果子容器没有超出父容器,设置 flex-shrink 无效 - 计算方式和 flex-grow 是不一样的 flex-basis 指定了 flex 元素在主轴方向上的初始大小,默认值为 auto(即由项目自身内容或 width/height 决定),也可以设为具体数值(如 100px)或百分比。 优先级:max-width/min-width > flex-basis > width > box flex-basis 是「初始尺寸」,flex-grow(扩展)和 flex-shrink(收缩)都是基于这个初始尺寸来计算空间分配 / 收缩的 **flex: 1 和 flex: auto 的区别** 真正的差异只有 flex-basis:一个是 0%,一个是 auto。  flex:1 忽略自身元素内容大小,强制按比例均分空间 如下所示,即使文本长度不一样,每个子元素的宽度依旧相等 flex: auto 优先保留元素自身内容尺寸,再分剩余空间。 如下图所示,文本长度(元素宽度)不一样时,每个元素宽度不一样 应用场景 需要 “等分空间”—— 用 flex:1 - 如卡片等分显示,多个导航栏均等显示 需要“优先保证内容显示”—— 用 flex:auto - 搜索框布局,需要优先保证输入框可输入宽度 **Float 为什么要清除浮动?以及如何清除?** 最开始的作用:图文环绕 要实现这样的效果,决定了 float 的两个特性: “破坏文档流”,使得父元素得高度塌陷。 禁止行框盒子与浮动元素发生重叠 一:为什么要清除浮动? 当子元素设置了float: left/right后,脱离文档流会引发以下问题: 1. - 父容器高度塌陷:父元素的高度默认由子元素撑开,但浮动元素 “飘” 起来后,父元素会认为内部没有可撑开高度的内容,高度变为 0。 2. - 布局混乱:页面下方的元素会 “钻” 到浮动元素下方,导致排版错位、重叠等问题。 3. - 背景和边框显示异常:父容器的背景和边框无法正常包裹浮动元素。 如以下布局: `<div class="parent"> <div class="float-item">浮动元素</div> </div> <div class="next">后续元素</div>` **二:如何清除浮动?(按推荐度排序)** 以下是常见的清除浮动方法: clearfix 伪元素法(最佳实践 / 主流方案) 通过 CSS 为父容器添加伪元素,自动清除浮动。 原理:clear: both 表示元素的左右两侧都不允许有浮动元素; 不增加冗余 HTML 标签,兼容性好(支持所有主流浏览器) 可封装成通用类 `.clearfix::after { content: ""; display: block; clear: both; /* 核心:清除左右浮动 */ visibility: hidden; /* 隐藏伪元素 */ height: 0; /* 避免占用额外空间 */ }` BFC(块级格式化上下文) 为父容器设置overflow: auto/hidden,使其创建 BFC 原理:BFC 会包裹内部的浮动元素,自动计算父元素高度。 缺点:如果子元素有超出父元素的内容(如下拉菜单、弹出层),会被 overflow: hidden 裁剪掉,适合简单布局。 使用 flexbox 或 Grid 布局 原理:现代布局方式会自动包含子元素,无需清除浮动。 缺点:兼容性没上面的高 额外标签法(不推荐,冗余标签) 在所有浮动子元素的末尾,添加一个空的块级标签(如 <div>),并设置 clear: both。 原理:直接在浮动元素后插入一个清除浮动的元素,强制父元素识别高度; 缺点:增加无意义的 HTML 冗余标签 **如何实现 0.5px 边框?** 在标准 css 中,通常无法直接设置 0.5px 的边框宽度,因为 css 像素的浏览器的最小渲染单位,而不支持亚像素级的渲染。但是可以通过一些技巧来模拟实现。 伪元素 可以使用伪元素 ::before 或 ::after 来创建一个额外的边框层,并设置高度为 0.5px。 `.element { position: relative; } .element::before { content: ""; position: absolute; top: 0; left: 0; width: 200%; /* 缩放后还原宽度 */ height: 200%; /* 缩放后还原高度 */ border: 1px solid #ccc; /* 先设 1px 边框 */ transform: scale(0.5); /* 缩放 0.5 倍,边框变为 0.5px */ transform-origin: 0 0; /* 缩放原点定位到左上角,避免偏移 */ box-sizing: border-box; /* 边框计入宽高,防止溢出 */ pointer-events: none; /* 伪元素不拦截点击事件 */ }` **阴影效果** 可以使用 box-shadow 属性来模拟一个细边框的效果 `.element { border: 1px solid transparent; /* 隐藏主边框 */ box-shadow: 0 0 0 0.5px #000; /* 模拟 0.5px 边框 */ }` **em 与 rem 的区别?** 1. em (相对单位) 参考基准:当前元素的字体大小(font-size)。 计算规则:如果当前元素的 font-size 为 16px,则 1em = 16px,2em = 32px。 特点:嵌套元素会继承父元素的字体大小,导致多次嵌套时可能出现尺寸累积。 **2. rem (根相对单位)** 参考基准:根元素(即 <html> 标签)的字体大小。 计算规则:如果 <html> 的 font-size 为 16px,则 1rem = 16px,2rem = 32px。 特点:全局统一,不受父元素字体大小影响,避免嵌套层级过深导致的尺寸失控。 浏览器的默认字体尺寸为 16px,所以有以下设置 `html { font-size: 62.%; /* 公式16px*62.5%=10px */ }` **什么是 BFC?** BFC (块级格式化上下文): 简单来说,BFC是一个完全独立的空间(布局环境),让空间里的子元素不会影响到外面的布局 当浮动时,会导致高度塌陷问题,如下图所示: 黄色框向左浮动,使它脱离了原本的位置,由此绿色框被定位到灰色父元素,并与浮动元素重叠。 由于父元素灰色框没有创建 BFC,由此计算高度时不会考虑灰色框的区域,也就是常见的 高度坍塌 问题 <div class='box'> // 灰色框 <div class='left' /> // 黄色框,向左浮动 <div class='right' /> // 绿色框 </div> **如何创建 BFC** - 根元素或其他包含它的元素 - 浮动:float: 不为 none - 绝对定位元素:position: absolute / fixed - 行内块级元素:display: inline-block - 表格单元格:display: table-cell - overflow 的值 不为 visible 的元素 - 弹性盒子:display: flex / inline-flex **BFC 的应用和效果** 应用一:防止高度坍塌 给灰色框创建一个新的 BFC 后,高度计算时会包括浮动元素(灰色框高度变化) `.BFC { overflow: hiddle; } <div className='box BFC'> <div className='left' /> <div className='right' /> </div>` **应用二:阻止与浮动元素重叠** 如下例:由于绿色框没有创建 BFC,其中的白色块受到黄色框(浮动元素)的影响,被挤到右边的同时超出了绿色框的范围。 `<style> .little{ background: #fff; width: 50px; height: 50px; margin: 10px; float: left; } </style> <div className='box BFC'> <div className='left' /> <div className='right'> <div className='little' /> <div className='little' /> <div className='little' /> </div> </div> ` 给绿色框创建 BFC 后,则并不会与黄色框发生重叠,同时由于 BFC 的隔离作用(一个独立容器),白色块不会受到黄色浮动框的影响(也说明其 每个元素的margin box的左边,与容器块border box的左边相接触 ) 注意:触发 BFC 不能阻止其他形式的脱离文档流的元素覆盖正常流元素(比如绝对定位元素) `<div className='right BFC'> ... </div>` **应用三:阻止 margin 合并** 阻止相邻元素的 margin 合并 给两个框分别添加 margin,由图可知相邻的 margin 会被合并 `<div className="box BFC"> <div className="left" /> // margin: 20px; <div className="right" /> // margin: 20px; </div>` 给其中一个元素(也可以两个元素)设置 BFC,可以阻止 margin 的合并 注意:块级元素会默认铺满一行 `<div className="box BFC"> <div className="BFC"> <div className="left" /> </div> <div className="right" /> `</div>`` **应用四:自适应两栏布局** 利用 BFC 不会与浮动元素重叠的特性,同时由于块级元素默认铺满整行,就可以实现两栏自适应布局 `<div className="box BFC"> <div className="left" /> // 保持左浮动 <div className="right BFC" /> // 删除 width </div>` ## 什么是盒模型? 可以认为每个html标签都是一个方块,然后这个方块又包着几个小方块,如同盒子一层层的包裹着,这就是所谓的盒模型。 默认width只是内容宽度,不是整体大小。 W3C 标准盒模型:box-sizing: content-box 内容的宽高度不包含 border 和 padding 属性 width, height 只包含内容 content ,不包含 border 和 padding。 width = 内容的宽度 height = 内容的高度 实际占用空间大于设定的宽高。 IE 盒模型:box-sizing: border-box 内容的宽高度包含 border 和 padding 属性 width, height 包含 border 和 padding,指的是 content+padding+border。 width = border + padding + 内容的宽度 height = border + padding + 内容的高度 这种模式的优势在于: 可以确切知道每个元素会占据多少空间,特别适合做栅格系统、卡片布局等需要精确控制尺寸的场景。 使用技巧 如果不想让 padding 或 margin 改变盒模型定义的宽高,则使用 border-box 尽量使用标准的W3C模型(需在页面中声明 DOCTYPE 类型),这样可以避免多个浏览器对同一页面的不兼容 若不声明 DOCTYPE 类型,IE浏览器会将盒子模型解释为IE盒子模型,FireFox 等会将其解释为 W3C 盒子模型; 若在页面中声明了 DOCTYPE 类型,所有的浏览器都会把盒模型解释为 W3C 盒模型。 css有哪些选择器?以及优先级? 层叠(Cascading)是CSS的一个核心机制,它决定了当多个样式规则应用到同一个元素时,哪些规则会生效,以及生效的顺序。 **常见的 css 选择器** - 元素选择器(Element Selector):选择指定元素类型的所有元素(p) - 类选择器(Class Selector):选择具有指定类名的元素,使用"."符号表示(.class) - ID选择器(ID Selector):选择具有指定id的唯一元素,使用"#"符号表示(#myId) - 属性选择器(Attribute Selector):选择具有指定属性或属性值的元素([type="text"]) - 后代选择器(Descendant Selector):选择指定元素的后代元素,使用空格分隔,例如div p选择所有div元素内部的p元素。 - 直接子元素选择器(Child Selector):选择指定元素的直接子元素,使用">"符号表示,例如div > p选择所有div元素的直接子元素p。 - 伪类选择器(Pseudo-class Selector):选择具有特定状态或行为的元素,例如:hover选择鼠标悬停的元素。 - 伪元素选择器(Pseudo-element Selector):选择元素的特定部分,例如::before选择元素的前面插入内容。 选择器优先级和权重列表  注意点: - CSS 选择器的特殊性(Specificity,权重) 遵循位权计算规则,存在层级壁垒,低层级选择器的数量无论堆叠多少,都永远无法跨越层级超过高层级选择器,这是和普通「数字加法」最本质的区别。 - 高位权重只要有值,低位权重堆到无穷大也无法超越。 - 同权重时,「后声明」覆盖「先声明」 - 继承的样式权重为 0, 会被子元素自身的任意选择器覆盖 **重绘与回流的区别?** 重绘(Repaint)和回流(Reflow)是与浏览器渲染引擎相关的概念,它们可以影响网页的性能。 回流 先画「骨架」—— 确定每个元素的位置、大小、间距(比如盒子的宽高、top/left、margin); 如果骨架变了(如盒子宽度变化),就需要重新计算所有相关元素的位置和尺寸,这个过程就是回流。 常见操作:(只要改变元素的几何属性,就会触发回流) - 修改元素尺寸、位置、字体、文本 - 增减 / 修改 DOM 节点 - 修改浏览器窗口 - 读取某些布局属性:offsetWidth/offsetHeight/clientWidth/getComputedStyle()(浏览器为了获取准确值,会强制触发回流)。 - 使用 JavaScript 计算样式或布局。 **重绘** 骨架不变,只改「外观」—— 比如改颜色、背景、阴影、透明度。 只需要在原有骨架上重新上色,不用动结构,这个过程就是重绘。 常见操作:只改视觉样式,不碰布局,仅触发重绘 修改颜色、阴影、透明度、背景图、光标等 性能优化:减少不必要的回流/重绘 批量修改,减少多次回流 合并样式修改 `const box = document.getElementById('box'); // 每改一个样式,触发一次回流 box.style.width = '200px'; box.style.height = '100px'; // 合并style属性 或 添加类名 box.style.cssText = 'width:200px; height:100px; margin:20px;'; // CSS:.box-new { width:200px; height:100px; margin:20px; } box.classList.add('box-new');` 2. 先「离线」修改 DOM,再「上线」 把元素从 DOM 树中移除,修改完成后再加回去(仅触发 2 次回流:移除 + 添加) `const ul = document.getElementById('list'); // 1. 离线:移除DOM ul.style.display = 'none'; // 2. 批量修改(无回流) for (let i = 0; i < 100; i++) { const li = document.createElement('li'); li.textContent = `Item ${i}`; ul.appendChild(li); } // 3. 上线:重新显示 ul.style.display = 'block'; 避免频繁读取「触发回流的属性」 如下例所示:每次读 offsetWidth 都触发回流,共 100 次,如果先缓存属性值,则仅触发一次; ini 体验AI代码助手 代码解读复制代码const box = document.getElementById('box'); let width = 0; for (let i = 0; i < 100; i++) { width = box.offsetWidth; // 每次读取都强制回流 box.style.left = `${width + i}px`; } // 先读取一次,缓存值 const baseWidth = box.offsetWidth; let width = baseWidth; for (let i = 0; i < 100; i++) { width = baseWidth + i; // 用缓存值计算,不触发回流 ... } 利用「文档碎片(DocumentFragment)」批量添加 DOM 文档碎片是「虚拟 DOM 容器」,修改碎片内的元素不会触发页面回流,最后一次性添加到页面: ini 体验AI代码助手 代码解读复制代码// 创建文档碎片(离线容器) const fragment = document.createDocumentFragment(); // 批量添加元素到碎片(无回流) for (let i = 0; i < 100; i++) { const li = document.createElement('li'); li.textContent = `Item ${i}`; fragment.appendChild(li); } // 一次性添加到页面(仅1次回流) document.getElementById('list').appendChild(fragment);` 使用 CSS3 硬件加速,减少回流 / 重绘 给元素添加transform/opacity(现代浏览器)等属性时,浏览器会将元素放到「GPU 层」渲染,避免触发全局回流: `.box { position: absolute; top: 10px; /* 改top会触发回流 */ } .box { transform: translateY(10px); /* 硬件加速,无回流 */ }` 核心区别: 回流是「布局重新计算」(耗性能),重绘是「外观重新渲染」(低消耗) 回流必触发重绘,重绘不触发回流; 水平垂直居中的方式有哪些? position: absolute + transform: translate 传统方式,基于定位,这类方法兼容性最好,适用于所有现代浏览器和一些旧版浏览器。 这是最常用、最灵活的方法之一,不需要知道元素的具体宽高。 `.parent { position: relative; width: 400px; height: 300px; border: 1px solid #ccc; } .child { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 150px; /* 子元素的宽高可以是固定的,也可以是自适应的 */ height: 100px; background-color: lightblue; }` position: absolute + 负 margin 一种经典方法,但是需要知道子元素的固定宽高 兼容性极佳,元素脱离文档流。 `.child { position: absolute; top: 50%; left: 50%; width: 150px; height: 100px; margin-top: -50px; /* -height / 2 */ margin-left: -75px; /* -width / 2 */ background-color: lightcoral; }` Flexbox 布局 (现代方法) 现代 css 布局的首选方案,简单直观 元素不脱离文档流,无需知道子元素宽高,还能处理更复杂的对齐和发布需求 `.parent { display: flex; justify-content: center; /* 水平居中 */ align-items: center; /* 垂直居中 */ width: 400px; height: 300px; border: 1px solid #ccc; }` Grid 布局 (更现代的方法) Grid 布局是二维布局系统,同样可以非常简单地实现居中。 元素不脱离文档流,代码更加简洁强大。 但兼容性没那么高,不支持 IE10 及以下版本。 `.parent { display: grid; place-items: center; /* 水平垂直居中,是 align-items 和 justify-items 的简写 */ width: 400px; height: 300px; border: 1px solid #ccc; } .child { width: 150px; height: 100px; background-color: lightsalmon; } ` 其他 只作为拓展思路 margin: auto; table: text-align + vertical-align ——转载自:Sport
重生之我在地球Online学JAVA day02
1、JS引入方式 内部脚本:将JS代码定义在html页面的< script>< /script>中; 建议:将< script>< /script>放在< body>的底部; 外部脚本:将JS代码定义在js文件中,通过< script>< /script>标签引入; 注意:通过< script>标签引入外部js文件时,标签不可以自闭合。 2、JS变量 (1)特点:JS是弱类型语言,变量可以存放不同类型的值。 (2)声明:var:声明变量,全局作用域/函数作用域,**允许重复声明**; let:声明变量,块级作用域,**不允许重复声明**; const:声明常量,一旦声明,**常量的值不能改变**。 3、运算符(注意):**==** 会进行类型转换,**===** 不会进行类型转换 4、**函数定义方式**(2中) (1)var functionName = function (参数1,参数2..){//要执行的代码} (2)function functionName(参数1,参数2..){//要执行的代码} 5、JS对象: (1)Array数组(注意):JavaScript 中的数组相当于 Java 中集合,数组的长度是可变的,而 JavaScript 是弱类型,所以可以存储任意的类型的数据。 箭头函数(ES6):是用来简化函数定义语法的。具体形式为: (…) => { … } ,如果需要给箭头函数起名字: var xxx = (…) => { … } (2)**JS自定义对象格式**: *var 对象名 = { 属性名1: 属性值1, 属性名2: 属性值2, 属性名3: 属性值3, 函数名称: function(形参列表){} };* (3)JSON介绍 概念:JavaScript Object Notation,JavaScript对象标记法。 JSON 是通过 JavaScript 对象标记法书写的文本。 **定义格式:** var 变量名 = '{"key1": value1, "key2": value2}'; (4)BOM对象 概念:Browser Object Model(浏览器对象模型),允许JavaScript与浏览器对话, JavaScript 将浏览器的各个组成部分封装为对象。 1)Window:浏览器窗口对象; 2)Navigator:浏览器对象; 3)Screen:屏幕对象; 4)History:历史记录对象; 5)Location:地址栏对象; (5)DOM对象 概念:Document Object Model (文档对象模型)。 将标记语言的各个组成部分封装为对应的对象: 1)Document:整个文档对象 2)Element:元素对象 3)Attribute:属性对象 4)Text:文本对象 5)Comment:注释对象 6)HTML中的Element对象可以通过Document对象获取,而Document对象是通过window对象获取的。 Document对象中提供了以下获取Element元素对象的函数: 根据id属性值获取,返回单个Element对象 **var h1 = document.getElementById('h1');** 根据标签名称获取,返回Element对象数组 **var divs = document.getElementsByTagName('div');** 根据name属性值获取,返回Element对象数组 **var hobbys = document.getElementsByName('hobby');** 根据class属性值获取,返回Element对象数组 **var clss = document.getElementsByClassName('cls');**
重生之我在地球online学JAVA day01
1、Web标准 HTML:负责网页的结构(页面元素和内容)。 CSS:负责网页的表现(页面元素的外观、位置等页面样式,如:颜色、大小等)。 JavaScript:负责网页的行为(交互效果)。 2、HTML的特点 (1)HTML标签不区分大小写 (2)HTML标签属性值单双引号都可以 (3)HTML语法松散 3、CSS引入方式 行内样式:< h1 style="..."> 内嵌样式:< style> … < /style> 外联样式:xxx.css < link href="..."> 4、CSS选择器 元素选择器:标签名 { … } id选择器:#id属性值 { … } 类选择器:.class属性值 { … } 优先级:id选择器 > 类选择器 > 元素选择器 5、CSS盒子模型 **组成:** 内容(content)、内边距(padding)、边框(border)、外边距(margin) 6、表单标签 (1)表单标签:< form> (2)表单属性:action:表单数据提交的url地址;method:表单提交方式
javaweb做的个人理财管理系统(功能多)
# 个人理财管理系统 ## 项目介绍 这是一个基于JavaWeb技术栈开发的个人理财管理系统,采用传统的Java EE架构,使用Servlet + JSP + JDBC技术实现。 ## 技术栈 - 后端:Java EE (Servlet + JSP) - 数据库:MySQL 5.7 - 前端:HTML + CSS + JavaScript - 数据库连接:JDBC - 图表展示:ECharts ## 主要功能 1. 用户管理 - 用户注册 - 用户登录 - 管理员权限控制 2. 收支管理 - 收入记录管理 - 支出记录管理 - 收支类别管理 - 支出阈值设置 3. 数据统计 - 月度报表 - 季度报表 - 年度报表 - 图表可视化 4. 公告系统 - 公告发布(管理员) - 公告查看 - 公告留言 ## 项目特点 1. 采用传统MVC架构,代码结构清晰 2. 使用原生JDBC进行数据库操作 3. 统一的页面布局和风格 4. 完善的数据可视化功能 5. 基于角色的访问控制 ## 部署说明 1. 导入finance.sql到MySQL数据库 2. 配置数据库连接参数 3. 部署到Tomcat服务器 ## 默认账号 - 管理员账号:admin - 管理员密码:admin             
javaweb做的社区养老保险管理系统
# 社区养老保险管理系统 ## 项目介绍 这是一个基于JavaWeb技术栈开发的社区养老保险管理系统,主要用于管理社区居民的养老保险信息。系统采用传统的Java EE架构,使用Servlet + JSP + JDBC技术实现。 ## 技术栈 - 后端:Java EE(Servlet、JSP) - 数据库:MySQL 5.7 - 前端:HTML、CSS、JavaScript - 连接池:JDBC直连 - 项目管理:传统项目结构(非Maven) ## 功能特点 1. 用户管理 - 用户注册 - 用户登录 - 用户退出 2. 保险管理 - 保险信息列表 - 添加保险信息 - 编辑保险信息 - 删除保险信息 3. 权限控制 - 管理员可查看所有用户的保险信息 - 普通用户只能查看自己的保险信息 ## 项目结构 roject ├── src │ ├── dao │ │ ├── UserDao.java │ │ └── InsuranceDao.java │ ├── entity │ │ ├── User.java │ │ └── Insurance.java │ ├── servlet │ │ ├── LoginServlet.java │ │ ├── RegisterServlet.java │ │ ├── LogoutServlet.java │ │ └── InsuranceServlet.java │ └── util │ └── DBUtil.java ├── WebContent │ ├── css │ │ └── style.css │ ├── js │ │ └── script.js │ ├── WEB-INF │ │ └── web.xml │ ├── login.jsp │ ├── register.jsp │ ├── insurance_list.jsp │ ├── insurance_add.jsp │ ├── insurance_edit.jsp │ ├── header.jsp │ ├── menu.jsp │ └── footer.jsp └── readme.md ## 部署说明 1. 创建MySQL数据库,执行insurance.sql脚本 2. 配置src/util/DBUtil.java中的数据库连接信息 3. 将项目导入Eclipse IDE 4. 配置Tomcat服务器 5. 部署运行项目 ## 默认账号 - 管理员账号:admin - 管理员密码:admin123 ## 注意事项 1. 项目使用UTF-8编码 2. 数据库默认使用UTF8MB4字符集 3. 需要配置Tomcat的JDK版本 4. 需要添加必要的JAR包依赖    
javaweb做的学校教务管理系统
# 教务管理系统 ## 项目介绍 这是一个基于JavaWeb技术栈开发的教务管理系统,采用传统的MVC架构模式,使用Servlet+JSP+JDBC技术实现。 ## 技术栈 - 后端:Java EE(Servlet、JSP) - 数据库:MySQL 5.7 - 前端:原生JavaScript、CSS - 连接池:JDBC直连 - 开发工具:Eclipse ## 功能特点 1. 用户管理 - 用户注册 - 用户登录 - 权限控制 2. 学生管理 - 学生信息CRUD - 学生查询 3. 课程管理 - 课程信息CRUD - 课程查询 4. 成绩管理 - 成绩录入 - 成绩查询 - 成绩统计 5. 班级管理 - 班级信息CRUD - 班级查询 <img src="https://pic.code-nav.cn/post_picture/1900441785166540802/u7bk71Llxxjhgn28.webp" alt="1.png" width="476px" /> <img src="https://pic.code-nav.cn/post_picture/1900441785166540802/yJN0DCZHc9PxjYTN.webp" alt="2.png" width="479px" />        
javaweb做的超市管理系统
# 超市管理系统 这是一个基于JavaWeb技术栈开发的超市管理系统,实现了商品和分类的基本管理功能。 ## 技术栈 - 后端: Java EE(Servlet + JSP) - 数据库: MySQL 5.7 - 前端: HTML + CSS + JavaScript - 连接池: JDBC - 权限控制: Session ## 功能特点 1. 用户管理 - 用户注册 - 用户登录 - 权限控制(管理员/普通用户) 2. 商品管理 - 商品列表(分页显示) - 添加商品 - 编辑商品 - 删除商品 - 按分类筛选 3. 分类管理(仅管理员) - 分类列表 - 添加分类 - 编辑分类 - 删除分类 ## 项目结构 supermarket/ ├── src/ │ └── com/ │ └── supermarket/ │ ├── dao/ # 数据访问层 │ ├── entity/ # 实体类 │ ├── servlet/ # Servlet控制器 │ └── util/ # 工具类 ├── WebContent/ │ ├── WEB-INF/ │ │ └── web.xml # Web应用配置文件 │ ├── css/ │ │ └── style.css # 全局样式表 │ ├── header.jsp # 页面头部 │ ├── footer.jsp # 页面底部 │ ├── menu.jsp # 左侧菜单 │ ├── login.jsp # 登录页面 │ ├── register.jsp # 注册页面 │ ├── product.jsp # 商品列表 │ ├── product_add.jsp # 添加商品 │ ├── product_edit.jsp # 编辑商品 │ ├── category.jsp # 分类列表 │ ├── category_add.jsp # 添加分类 │ └── category_edit.jsp # 编辑分类 └── db.sql # 数据库脚本 ... ## 开发环境要求 - JDK 1.8+ - Eclipse IDE - MySQL 5.7 - Tomcat 8.5+ - 必要的JAR包: - javax.servlet-api-3.0.1.jar - jstl-1.2.jar - mysql-connector-java-5.1.47.jar ## 安装说明 1. 创建数据库 ```sql source db.sql ``` 2. 配置数据库连接 - 修改 `src/com/supermarket/util/DBUtil.java` 中的数据库连接信息: ```java private static final String URL = "jdbc:mysql://localhost:3306/supermarket?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai"; private static final String USERNAME = "your_username"; private static final String PASSWORD = "your_password"; ``` 3. 部署到Tomcat - 将项目导入Eclipse - 配置Tomcat服务器 - 部署项目到Tomcat ## 使用说明 1. 启动项目后,访问: `http://localhost:8080/supermarket` 2. 默认管理员账号: - 用户名: admin - 密码: admin123 3. 普通用户需要先注册才能使用系统 4. 功能说明: - 管理员可以管理所有商品和分类 - 普通用户只能管理自己创建的商品 - 所有用户都可以查看商品列表 ## 注意事项 1. 请确保数据库配置正确 2. 请确保所有必要的JAR包都已添加到项目中 3. 建议使用UTF-8编码,避免中文乱码问题 4. 请定期备份数据库 ## 开发说明 1. 代码规范 - 使用UTF-8编码 - 遵循Java命名规范 - 代码缩进使用4个空格 2. 目录结构说明 - dao: 数据访问层,处理数据库操作 - entity: 实体类,对应数据库表 - servlet: 控制器,处理请求和响应 - util: 工具类,提供通用功能 3. 安全性考虑 - 使用Session进行权限控制 - 对用户输入进行验证 - 防止SQL注入攻击 <img src="https://pic.code-nav.cn/post_picture/1900441785166540802/pbMXRiu4LXy9KFXO.webp" alt="1.png" width="447px" /> <img src="https://pic.code-nav.cn/post_picture/1900441785166540802/SFQwd3FrDI4Mebdf.webp" alt="2.png" width="474px" />    
javaweb做的蛋糕店管理系统
# 蛋糕店管理系统 ## 项目介绍 这是一个基于JavaWeb技术栈开发的蛋糕店管理系统,采用传统的MVC架构模式。 ## 技术栈 - Java EE (Servlet + JSP) - JDBC - MySQL 5.7 - HTML/CSS/JavaScript ## 项目结构 cake-shop/ ├── src/ │ ├── com/ │ │ └── cakeshop/ │ │ ├── dao/ # 数据访问层 │ │ ├── entity/ # 实体类 │ │ ├── servlet/ # Servlet控制器 │ │ └── util/ # 工具类 │ └── resources/ # 资源文件 └── WebContent/ ├── css/ # 样式文件 ├── js/ # JavaScript文件 ├── WEB-INF/ │ ├── lib/ # 依赖的JAR包 │ └── web.xml # Web应用配置文件 ├── login.jsp # 登录页面 ├── register.jsp # 注册页面 ├── index.jsp # 主页 ├── category_list.jsp # 分类列表 ├── category_add.jsp # 添加分类 ├── category_edit.jsp # 编辑分类 ├── cake_list.jsp # 蛋糕列表 ├── cake_add.jsp # 添加蛋糕 ├── cake_edit.jsp # 编辑蛋糕 └── order_list.jsp # 订单列表 ## 必需的JAR包 - javax.servlet-api-3.1.0.jar - jsp-api-2.2.jar - jstl-1.2.jar - mysql-connector-java-5.1.47.jar ## 功能特点 1. 用户管理 - 用户注册 - 用户登录 - 权限控制 2. 分类管理(管理员) - 添加分类 - 编辑分类 - 删除分类 - 分类列表 3. 蛋糕管理 - 添加蛋糕 - 编辑蛋糕 - 删除蛋糕 - 蛋糕列表 4. 订单管理 - 创建订单 - 查看订单 - 更新订单状态 ## 安装说明 1. 创建数据库 - 使用MySQL 5.7 - 执行cake_shop.sql脚本创建数据库和表 2. 配置项目 - 将项目导入Eclipse - 添加所需的JAR包到WEB-INF/lib目录 - 修改src/com/cakeshop/util/DBUtil.java中的数据库连接信息 3. 部署运行 - 部署到Tomcat服务器 - 访问http://localhost:8080/cake-shop/ - 默认管理员账号:admin/admin ## 注意事项 1. 所有页面请求都通过Servlet处理,不要直接访问JSP页面 2. 用户需要登录后才能访问系统 3. 普通用户只能查看自己的订单 4. 管理员可以查看所有数据并进行管理 <img src="https://pic.code-nav.cn/post_picture/1900441785166540802/J1XEJcRHyw4UOJ6H.webp" alt="1.png" width="432px" />  <img src="https://pic.code-nav.cn/post_picture/1900441785166540802/naFoji2VAbx6ypm8.webp" alt="3.png" width="100%" />      
jsp+servlet做的超市商品管理系统
# 超市商品管理系统 ## 项目介绍 这是一个基于JavaWeb技术栈开发的超市商品管理系统,采用传统的MVC架构模式,使用Servlet作为控制器,JSP作为视图层,通过JDBC进行数据库操作。系统提供了商品管理和类别管理的基本功能,并实现了基于角色的访问控制。 ## 技术栈 - 后端:JavaWeb (Servlet + JSP) - 数据库:MySQL 5.7 - 前端:原生JavaScript + CSS - 连接池:JDBC直连 - 项目管理:Eclipse IDE ## 系统特点 1. **用户权限管理** - 支持用户注册和登录功能 - 实现了基于角色的访问控制(RBAC) - 区分普通用户和管理员权限 2. **商品管理功能** - 商品的增删改查操作 - 支持按类别管理商品 - 用户只能管理自己添加的商品 - 管理员可以查看所有商品 3. **类别管理功能** - 商品类别的增删改查操作 - 仅管理员可以管理类别 4. **界面设计** - 清晰的布局结构(header、left menu、content、footer) - 响应式设计,适配不同屏幕尺寸 - 统一的页面风格和操作体验 ## 项目结构 ``` supermarket/ ├── WebContent/ # Web资源目录 │ ├── WEB-INF/ # Web配置目录 │ │ └── web.xml # Web应用配置文件 │ ├── css/ # 样式文件 │ │ └── style.css # 全局样式 │ ├── login.jsp # 登录页面 │ ├── register.jsp # 注册页面 │ ├── product_list.jsp # 商品列表页面 │ ├── product_form.jsp # 商品编辑页面 │ ├── category_list.jsp # 类别列表页面 │ └── category_form.jsp # 类别编辑页面 ├── src/ # Java源代码目录 │ └── com/supermarket/ │ ├── entity/ # 实体类 │ │ ├── User.java │ │ ├── Product.java │ │ └── Category.java │ ├── dao/ # 数据访问层 │ │ ├── UserDao.java │ │ ├── ProductDao.java │ │ └── CategoryDao.java │ ├── servlet/ # 控制器层 │ │ ├── UserServlet.java │ │ ├── ProductServlet.java │ │ └── CategoryServlet.java │ └── util/ # 工具类 │ └── DBUtil.java # 数据库连接工具 └── supermarket.sql # 数据库脚本 ``` ## 代码特点 1. **规范的代码组织** - 采用标准的MVC分层架构 - 清晰的包结构和命名规范 - 统一的编码风格 2. **安全性考虑** - 登录状态验证 - SQL注入防护 - 权限检查机制 3. **用户体验优化** - 表单验证 - 友好的错误提示 - 操作确认提示 4. **代码复用** - 通用的数据库连接工具 - 统一的页面布局 - 可重用的CSS样式 ## 部署说明 1. 创建MySQL数据库,执行`supermarket.sql`脚本 2. 配置`DBUtil.java`中的数据库连接信息 3. 使用Eclipse导入项目 4. 配置Tomcat服务器 5. 部署运行项目 ## 注意事项 1. 请确保MySQL 5.7已正确安装并运行 2. 数据库字符集使用utf8mb4 3. 请根据实际情况修改数据库连接配置 4. 建议使用Eclipse IDE进行开发和调试 <img src="https://pic.code-nav.cn/post_picture/1900441785166540802/4TIgDP3KOcqrUDbH.png" alt="1.png" width="395px" /> <img src="https://pic.code-nav.cn/post_picture/1900441785166540802/dvgILY6Yay2Ar5Xo.png" alt="2.png" width="348px" /> <img src="https://pic.code-nav.cn/post_picture/1900441785166540802/byHxr23xx6r2YHE0.webp" alt="3.png" width="100%" /> <img src="https://pic.code-nav.cn/post_picture/1900441785166540802/eRFXTkkgdnnjK1Bn.webp" alt="4.png" width="100%" /> <img src="https://pic.code-nav.cn/post_picture/1900441785166540802/37NlR5YErZIGKvFq.webp" alt="5.png" width="100%" /> <img src="https://pic.code-nav.cn/post_picture/1900441785166540802/5g564pNy9VWujayh.webp" alt="6.png" width="100%" />
