简介这是一套仿小米商城Web页面的HTMLCSS实战练习面向前端初学者用来训练电商首页的布局搭建与视觉还原能力。项目采用语义化标签组织头部、导航、商品区域、侧边栏和底部重点练习盒模型、浮动、Flexbox、Grid、响应式媒体查询以及轮播图、商品卡片、按钮等典型样式。资源为RAR压缩包共410个文件包含248个JPG、98个WebP、56个PNG图片素材4个CSS样式文件、2个JS脚本、1个HTML入口页和1个ICO图标整体3.28MB。JPG与PNG多用于商品图和轮播图WebP可节省加载流量CSS负责版式和主题风格JS辅助轮播切换。目前已有906人学习下载。对照源码可以快速理解网站模块拆分、命名约定和布局技巧也可替换文字图片改造成个人作品为后续深入学习交互效果打下基础。1. 仿商城 web 练习这份 HTMLCSS 资源能让你少走一半弯路很多初学者拿到一个商城首页的 HTMLCSS 练习资源第一反应是去看它「像不像」而不是看它「怎么拆」。这是最大的误区。我见过太多人照着静态页面抄代码抄完换了台电脑、换个屏幕宽度就崩了原因就是只抄了表面样式没理解骨架和排版逻辑。这份「仿商城 web 练习」资源最大的价值是帮你把一套真实的 3C 电商首页拆成你能完全控制的盒子顶部工具条、主导航、轮播区、商品网格、底部分区每一步都有对应的布局思路和参数可查。适合想把静态页面从「能看出来」练到「能写对」的前端初学者也适合准备求职作品集、想补一个完整首页案例的从业者。标题里的 wed 是 web 的手误说法不影响阅读。2. 先拆后写页面模块划分与版心宽度设计仿站的第一步永远不是写 HTML而是把页面拆成模块。3C 商城首页的信息密度很高如果上来就写div写不到一半就会因为嵌套过深把自己绕晕。我拿到这份练习资源时做的第一件事是在纸上把页面从上到下画了一遍确认每一块区域归属哪个语义化标签、宽度怎么约束。2.1 页面模块清单与 1226px 版心的由来一个典型的商城首页从上到下可以分成这么几块模块功能常见布局方式顶部工具条用户入口、购物车入口深色全宽背景 内层固定宽度 Flex主导航区Logo、频道入口、搜索框Flex 左右分布轮播区大图横幅切换position 叠放 radio 控制频道入口区分类入口图标Flex 多列均分商品陈列区商品卡片网格CSS Grid 多列自适应底部服务与版权服务承诺、链接、备案信息多列网格或 Flex 换行这些模块里最容易忽略的是「版心宽度」。早年主流屏幕宽度是 1280px减去滚动条后实际可用宽度大约在 1263px 左右要留出两侧安全边距于是 1226px 成了一个常见值。1226 能被 2 整除方便做左右分栏也可以很好地容纳「234px 商品卡 × 5 列 间距」这种经典栅格。现在做仿站不需要纠结某个固定数值的来历但需要知道版心是怎么工作的.container { max-width: 1226px; margin: 0 auto; padding: 0 16px; }上面这段是版心的标准写法。max-width保证在窄屏上容器会跟着收缩不会撑破视口margin: 0 auto让容器在宽屏上居中padding: 0 16px给内容左右留出安全距离避免贴边。我一般会在写任何模块之前先把.container这类版心类建好后面所有模块都套用而不是每个模块自己写一套宽度逻辑。还有一层容易忽略背景和内容要分开。顶部工具条想要深色背景横贯整个屏幕但里面的文字要对齐版心这时候结构要拆两层——外层管背景background: #333宽度 100%内层用.container管对齐。很多人直接把背景色写在版心容器上结果两侧露出白边这也是仿站翻车的高频原因。2.2 用语义化标签搭骨架拆完模块后HTML 骨架应该长这样。语义化标签的作用不是「显得专业」而是让样式的选择器有明确的作用域后续写 CSS 时不用靠层级硬拼选择器body header classtopbar div classcontainer topbar-inner !-- 顶部工具条内容 -- /div /header header classmain-header div classcontainer main-header-inner !-- Logo、导航、搜索框 -- /div /header main section classhero div classcontainer !-- 轮播区 -- /div /section section classproducts div classcontainer !-- 商品陈列区 -- /div /section /main footer classsite-footer div classcontainer !-- 底部链接与版权 -- /div /footer /body注意这里有两个header这在 HTML5 里是合法的第一个是顶部工具条第二个是主头部区域。两者样式完全独立不会冲突。使用main包裹主体内容section区分功能区块footer收尾结构上一眼能看出页面的信息层级。我给骨架里的每个区块都加了带前缀的类名比如topbar-inner、main-header-inner这样写 CSS 时选择器永远保持扁平不会出现.container .nav ul li a span这种长串选择器。2.3 顶部工具条的完整实现顶部工具条是练习盒模型和 Flex 对齐的好样本。它内部一般有左侧的用户入口链接、右侧的购物车和消息入口逻辑上就是一行左右分布header classtopbar div classcontainer topbar-inner ul classtopbar-left lia href#商城首页/a/li lia href#全部商品/a/li /ul ul classtopbar-right lia href#购物车/a/li lia href#我的订单/a/li /ul /div /header.topbar { background: #333; color: #b0b0b0; font-size: 12px; } .topbar-inner { display: flex; justify-content: space-between; align-items: center; height: 40px; } .topbar-left, .topbar-right { display: flex; gap: 0 18px; margin: 0; padding: 0; list-style: none; }justify-content: space-between把左右两组推到两端align-items: center保证行内垂直居中gap: 0 18px处理组内元素的左右间距。这里我刻意不用margin-right去逐个推间距因为gap会把间距逻辑收敛在父容器后续增删链接时不需要改子元素。顶部工具条的字号一般压在 12px颜色用浅灰而不是纯白这是商城页面的通用做法让次要信息视觉上往后退一层。3. 布局选型Flex 与 Grid 的边界与组合用法很多人在仿站时纠结一个问题这个区域该用 Flex 还是 Grid答案是看结构形态。判断标准其实很直接如果只有一行、元素沿着一个方向排列用 Flex如果既要横向分列又要纵向换行、元素呈网格状排布用 Grid。两个模型各有边界硬混用会写出大量没必要的外层包裹。3.1 一维布局用 Flex二维布局用 GridFlex 的命名来自「flexible」它的核心能力是一维分布主轴方向上的对齐、换行、拉伸。商品卡片内部的图文结构是 Flex 的典型场景——图片、标题、价格从上到下竖着排这是单列布局用flex-direction: column就好。而商品陈列区本身是「多行多列」的二维结构你既要控制一屏显示几列又希望行与行之间对齐用 Grid 的grid-template-columns一次就能声明清楚。有个经典问题是用 Flex 加flex-wrap也能做出多列效果为什么还要用 Grid区别在于对齐能力。Flex 换行后每条新行是一个独立的上下文行与行之间、列与列之间的对齐全靠内容自然撑开Grid 则严格按行列网格对齐所有单元格的宽度和间距是一致的。商城商品卡要求每列宽度一致、卡片高度一致Grid 的1fr单位天然满足这个需求。但 Grid 也有边界它的子项如果不写grid-column永远只占一格如果你的布局里有「某个元素要跨越两列」这种需求Flex 做不到Grid 又要写额外属性。好在商城首页的常规骨架里Flex 处理条状结构Grid 处理面状结构不会出现太复杂的跨列场景。3.2 主导航与工具条的 Flex 实现主导航区域一般包含三块左侧 Logo、中间频道链接、右侧搜索框。整体是一行天然用 Flex.main-header-inner { display: flex; align-items: center; justify-content: space-between; height: 80px; } .site-logo { width: 48px; height: 48px; background: #ff6700; border-radius: 4px; } .main-nav ul { display: flex; gap: 0 22px; margin: 0; padding: 0; list-style: none; } .search-box { display: flex; align-items: center; width: 240px; height: 36px; border: 1px solid #e0e0e0; }这段代码里有几个参数值得说明。gap: 0 22px的 22px 是导航链接间距的经验值太密显得拥挤太疏导致导航宽度撑不开height: 80px是头部高度的常见值配合align-items: center可以让内容垂直居中。border-radius: 4px是 Logo 占位符的圆角模拟品牌标识时不需要真的放图片一个色块足够定位布局。搜索框用width: 240px固定宽度而不是flex: 1是因为商城页面的搜索框通常是一个固定宽度组件不应随屏幕伸缩。3.3 商品陈列区的 Grid 实现商品区是整页最考验布局能力的地方。一个典型做法是 234px 宽的商品卡一行 5 列加上间距正好接近版心宽度。用 Grid 写起来很干净.product-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(234px, 1fr)); gap: 14px; } .product-card { display: flex; flex-direction: column; background: #fff; padding: 20px; transition: box-shadow .3s ease, transform .3s ease; } .product-card img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }repeat(auto-fill, minmax(234px, 1fr))是这段代码的核心。auto-fill表示浏览器根据容器宽度自动计算能放几列minmax(234px, 1fr)表示每列宽度最小 234px最大占满剩余空间。这样在 1226px 版心内自然得到 5 列在更窄的容器内会自动降为 4 列或 3 列不需要写媒体查询。gap: 14px是商品卡的间距基数14px 在视觉上比 10px 通透比 20px 紧凑适合信息密度高的商品区。商品卡内部用flex-direction: column做纵向排列aspect-ratio: 1 / 1强制图片框为正方形配合object-fit: cover保证图片不变形。这套写法的好处是列的宽度和间距完全由 Grid 计算你不需要关心第 4 列和第 5 列的间距是否一致也不需要处理最后一行的对齐问题。我第一次用minmax(234px, 1fr)时还被auto-fill的列数计算震惊了一下但这种「让浏览器算」的思维恰恰是 Grid 对比 Flex 的核心差异。4. 轮播图与交互纯 CSS 轮播的边界与 JS 的取舍商城首页最显眼的位置就是轮播图。很多练习资源会在这里炫技但我建议先弄清楚边界纯 CSS 能做轮播吗能但有明显限制。理解这个限制你才能在练习和真实项目中做出对的选择。4.1 用 radio 加 label 实现纯 CSS 轮播纯 CSS 轮播最常见的实现是利用input:checked状态切换。基本原理是用一组隐藏的 radio 作为状态源每个 radio 对应一张轮播图用 label 的 点击切换 radio 的选中状态再用 CSS 的兄弟选择器根据选中状态控制对应图片的显示和隐藏。radio 天然互斥所以永远只有一个处于选中状态不会出现两张图同时显示的情况div classslider input typeradio nameslider idslide1 classslider-radio checked input typeradio nameslider idslide2 classslider-radio input typeradio nameslider idslide3 classslider-radio div classslides div classslide第一张/div div classslide第二张/div div classslide第三张/div /div div classslider-controls label forslide1 classdot/label label forslide2 classdot/label label forslide3 classdot/label /div /div.slider { position: relative; height: 460px; overflow: hidden; } .slides .slide { position: absolute; inset: 0; opacity: 0; visibility: hidden; transition: opacity .4s ease; } #slide1:checked ~ .slides .slide:nth-child(1), #slide2:checked ~ .slides .slide:nth-child(2), #slide3:checked ~ .slides .slide:nth-child(3) { opacity: 1; visibility: visible; } .slider-controls { position: absolute; bottom: 16px; left: 50%; transform: translateX(-50%); display: flex; gap: 8px; } .dot { width: 10px; height: 10px; border-radius: 50%; background: rgba(255, 255, 255, .6); cursor: pointer; }这段代码的工作方式所有.slide绝对定位叠在同一位置默认visibility: hidden隐藏当对应的 radio 被选中时通过兄弟选择器把它对应的那张图改为可见。opacity配合transition做出淡入淡出效果visibility防止透明元素仍然拦截点击事件。这里必须注意结构层级radio 和.slides必须是兄弟关系否则~兄弟选择器选不中。.dot是指示点用label forslide1和 radio 的id关联点击 label 就相当于点击了 radio。4.2 纯 CSS 轮播的边界自动播放做不了上面这套方案有两个硬边界没有自动播放也没有循环滑动。所谓「自动播放」需要定时器定时器属于 JS 能力纯 CSS 没有时间驱动机制。所谓「滑动切换」需要记录当前索引并做位移计算CSS 的transition只能在状态变化时执行一次动画无法感知「下一次该去哪张」。如果你的练习目标只是还原静态交互纯 CSS 方案够用且零依赖。但真实项目中轮播图几乎都要自动播放这时候最常见的做法是加少量 JS。我一般会用一个setInterval控制索引配合transform: translateX做整体位移let current 0; const slides document.querySelectorAll(.slide); const total slides.length; setInterval(() { current (current 1) % total; const offset -current * 100; document.querySelector(.slides).style.transform translateX(${offset}%); }, 3000);这段代码的核心逻辑只有两行current (current 1) % total让索引在 0 到总张数之间循环translateX(-current * 100%)把整个轮播容器向左偏移。3000是 3 秒间隔这个值是轮播图的常见节奏太短让人来不及看内容太长则失去轮播的意义。要注意的是如果每个.slide设置了width: 100%那么整个.slides容器的宽度应该等于总张数 × 100%否则偏移的百分比基数不对。这个细节经常让人翻车明明 JS 逻辑没错但轮播图偏移位置总是不对十有八九是容器的宽度没有撑开成「总宽度」。4.3 hover 交互与过渡参数轮播图之外的页面交互最见功力的是 hover 效果。商品卡片鼠标悬停时常见的反馈是「抬起来」加阴影、轻微上移、边框点亮。参数怎么选是有讲究的.product-card:hover { box-shadow: 0 15px 30px rgba(0, 0, 0, .1); transform: translateY(-2px); }box-shadow的三个关键参数0 15px 30px表示阴影垂直向下偏移 15px、模糊半径 30px这个比例让阴影看起来是「自然投射」而不是「生硬描边」rgba(0, 0, 0, .1)的透明度 0.1 是阴影存在感的临界点低于 0.05 基本看不出高于 0.2 会显得脏。translateY(-2px)的上移幅度也是经验值1px 太含蓄3px 以上又显得卡片在飘。配合之前样式里的transition: box-shadow .3s ease, transform .3s ease悬停效果在 300ms 内完成这个时长接近人类视觉对「即时反馈」的感知上限太短会觉得生硬太长会觉得拖沓。提示transition的属性值最好分开写不要用all。用all会在 hover 时把background、border等所有属性都做过渡性能差且容易出现意外动画。5. 避坑仿商城页面最常见的五个翻车现场做仿站练习时翻车是常态我拆这份资源时也踩了不少坑。下面五个问题基本覆盖了初学者复制粘贴后最常遇到的故障每条都按「现象、原因、解决」的顺序说清楚。5.1 页面莫名出现横向滚动条现象页面整体看起来正常但底部总有一条横向滚动条往右拖能看到一片空白。原因某个元素的宽度超过了视口宽度。常见于顶部工具条里的链接太多Flex 子项默认不换行内容被强行撑出容器或者某张图片没有限宽原始宽度直接撑破版心。解决先用document.documentElement.scrollWidth和document.documentElement.clientWidth对比确认溢出然后在可疑元素上临时加outline: 1px solid red逐个排查。修复方法按情况选给 Flex 容器加flex-wrap: wrap或者给图片加max-width: 100%。横向滚动条在移动端尤其明显因为视口宽度小一点点溢出都会触发。5.2 同样的字号不同电脑上显示的大小不一样现象在 Windows 上调试好的 14px 文字换到 Mac 上变大了或者行高变了页面整体观感不同。原因不同操作系统的默认字体不同Windows 下渲染微软雅黑Mac 下渲染苹方两者的字形高度和行高比例不一样。解决给body设置统一的字体栈和行高基准。常见的做法是body { font-family: Helvetica Neue, Arial, PingFang SC, Microsoft YaHei, sans-serif; line-height: 1.6; }字体栈的排列顺序有讲究先放英文优先的字体再放中文优雅的字体最后用sans-serif兜底。行高用相对值1.6而不是固定像素24px这样无论字体渲染差异多大行高都会按字号比例缩放不会因为字体替换而崩掉。5.3 图片被拉伸变形现象商品图片被塞进固定宽高的容器后人脸或产品外形被拉扁拉长。原因直接对img设置了width和height但图片原始比例和容器比例不一致浏览器默认拉伸铺满。解决用aspect-ratio固定容器比例再用object-fit: cover处理裁切。之前的商品卡代码里已经写过这两个属性它们的作用是容器宽高比固定为 1:1图片等比缩放并裁切多余部分。要注意object-fit: cover会裁掉图片边缘如果图片里的核心内容靠近边缘会被切掉。这时候可以改用object-fit: contain图片完整显示但容器会留白具体取舍看图片内容。5.4 轮播图指示点点了没反应现象鼠标点击轮播图下方的圆点图片切换没有任何响应。原因label的for属性和input的id没有对上或者input和label的结构层级不对导致点击事件无法触发 radio。解决检查每一对id和for是否严格一致并且确认.slider容器内 radio 和.slides是兄弟关系而不是嵌套关系。我习惯把 radio 的 id 统一命名为slide1、slide2、slide3label 的for逐字对应这样从命名上杜绝拼写错误。另外 radio 如果被 CSS 设了display: none点击 label 依然能触发不需要保留可视元素。5.5 间距越改越乱牵一发动全身现象调整一个区块的间距导致旁边几个区块的布局也跟着变化。原因所有间距都用margin堆砌而且没有统一的间距数值体系改一处就要连带改多处。解决建立间距刻度。把 8px、14px、24px、32px 作为间距基准Flex 和 Grid 容器内部用gap处理margin只负责「组件与外部」的距离不负责「组件内部」的排列。gap的好处是只影响子元素之间的间距不影响首尾元素的外边距。6. 还原度校准与性能小技巧用 DevTools 自查三件套6.1 用 DevTools 测量视口与间距仿站做完后我一般会花十分钟做一次系统自查。第一件事是开 DevTools 的布局检查。在元素面板里选中任意元素浏览器会直接显示它的内边距、外边距和尺寸标注配合设备模拟器能快速查看页面在 375px 手机宽度和 1280px 桌面宽度下的表现。重点检查三处版心容器是否在窄屏收缩、商品网格是否从 5 列降为 2 列、顶部工具条的链接是否换行。6.2 图片加载顺序与体积第二件事是处理图片加载。首屏轮播图和 Logo 应该正常加载首屏之外的商品图可以用loadinglazy延迟加载。这个属性是浏览器原生支持的不需要额外的 JS 库img srcproduct.jpg alt商品名称 loadinglazyloadinglazy告诉浏览器当图片进入视口附近时才加载。这个机制能大幅减少首次加载的请求数。要注意的是首屏内的图片不要加这个属性加了反而会导致首次绘制变慢。图片体积上用压缩过的 JPG 或 WebP 格式单张控制在 200KB 以内避免页面加载白屏时间过长。6.3 代码组织的小习惯从这份练习资源里学到最有用的东西其实是代码组织方式。样式按 base、layout、components 三个维度分文件base 放 reset 和全局变量layout 放版心和骨架布局components 放轮播、商品卡、按钮这类独立组件。类名统一用「块 元素 修饰符」的命名方式比如product-card、product-card--hover避免出现left、right这种没有语义的命名。从那以后我每次做完仿站页面都会强制走一遍 DevTools 测量流程先查横向溢出再看 hover 层叠最后顺手核对图片加载顺序。这三个动作看似简单但能把练习作业从「看着像」推进到「能直接用」希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?