web前端开发这个领域,入门第一课通常就是HTML和CSS,而很多人的第一份作业,逃不掉一张“汇款单”。标题里写着“web前端第一次作业——汇款单”,看起来平平无奇,但它其实比传单、名片、个人主页更考验基本功:表单控件、表格行列、边框间距、字体排印,全都要在几百行代码里处理好。今天我就把这份作业掰开揉碎,讲讲怎么从零把它写清楚,顺便把新手最容易踩的坑也一并说完。
可能你拿到题目时一脸懵:都什么年代了还做汇款单?别急着嫌弃,这类单据页面在真实业务里非常常见,转账回单、报销单、快递面单本质上都是同一套页面结构。把这张“汇款单”吃透,后面再做任何表单类页面都会顺手很多。
1. 拿到“汇款单”这道题,先别急着写代码
1.1 这到底是个什么作业
通常老师会给你一张纸质汇款单图片,或者只丢下一句“做一个汇款单页面”,最多附几个字段要求。常见的是中国邮政汇款单或银行电子汇款单:抬头印着“汇款单”,旁边有汇票号码;左边是收款人姓名、地址、邮编;右边是汇款人姓名、地址、邮编;中间是币种、金额大写、小写和汇费;下面是附言、日期,加上经办、复核栏。第一份作业一般不要求JS,只要用HTML+CSS把这些栏目像模像样地排出来。
从这也能猜出出题人的意图:页面是纯静态的,但信息密度高、分区明确、布局紧凑,非常适合检验新人能不能读懂“区块—行—列”之间的关系。很多同学一上来就盯着某个输入框去调样式,结果越写越乱,就是因为没有先把整张单子的结构在脑子里过一遍。
1.2 为什么要拿汇款单练手
我见过不少培训班和学校的项目列表,第一次作业通常会在“名片、传单、个人主页、登录页”里挑一个,汇款单算比较硬核的那类。它有几个其他页面给不了的好处:
- 表单控件种类齐全:单行文本、下拉框、单选框、多行文本、日期区,几乎每个input类型都能用上;
- 布局天然是二维表格:收款人、金额、附言呈网格状排列,新手可以直观理解行和列;
- 风格还原难度不小:纸质单据有打印感、下划线、双线边框,这些细节最能拉开作业之间的差距;
- 适合做提交校验和打印样式的后续扩展:如果课程后面教了JavaScript,这个页面马上又能变成练习对象。
所以别把这张单子当成一个静态页,它其实是你第一个“信息架构”练习。不用一个div走天下,而是观察结构、规划区块,这种“先分析后动手”的习惯,比代码本身更值钱。
2. 开工前把页面拆成几个区块
2.1 汇款单的栏目结构
把一张纸质汇款单摊开,你会发现它和现代后台的表单页没有本质区别。我习惯先做一张字段表,确定每一块内容用什么标签承载:
| 区块名称 | 包含字段 | 建议标签/元素 |
|---|---|---|
| 单据抬头 | 汇款单标题、编号No.xxxxx | header > h1 + p |
| 收款人信息 | 收款人姓名、地址、邮政编码 | table 或 section |
| 汇款人信息 | 汇款人姓名、地址、联系电话、邮编 | 同上 |
| 汇款金额区 | 币种、大写金额、小写金额、汇费/手续费 | table |
| 汇款种类 | 普通、电子、加急、投单等 | fieldset + label + radio |
| 附言区 | 留言、备注 | textarea |
| 底部信息 | 日期、汇款人签名、经办人、复核人 | 签名栏样式的行 |
可能你拿到的素材没有这么完整,那也没关系,关键是把这些字段用清晰的区块组织起来。卡片是给用户看的,区块是给你自己写代码看的。写代码之前如果没有区块意识,后面一个间距不对就全局崩掉,返工成本非常高。
2.2 用语义化标签搭骨架
第一次作业很容易写出一个巨长的div海洋。我的建议是优先用main、header、section、label这些语义化标签,它们能告诉浏览器和屏幕阅读器“这块是什么”。结构大概是这个感觉:
<main class="remittance"> <header class="remittance-header"> <h1>汇 款 单</h1> <p class="bill-no">No. 2024-001</p> </header> <section class="party payee"> <h2 class="visually-hidden">收款人信息</h2> <!-- 表格内容 --> </section> <section class="party payer"> <h2 class="visually-hidden">汇款人信息</h2> </section> <section class="amount-info"> <!-- 金额表格 --> </section> <section class="type"> <!-- 汇款种类 --> </section> <label class="postscript"> <span>附言</span> <textarea></textarea> </label> </main>这里有一点要提醒:section里的h2如果不希望显示在页面上,不要用display:none藏掉,那会影响读屏和SEO。可以用一个视觉隐藏类:
.visually-hidden { position: absolute; width: 1px; height: 1px; clip: rect(0 0 0 0); overflow: hidden; white-space: nowrap; }第一次作业不会因为一个隐藏标题加分太多,但这个习惯能让你在后面做可访问性时少踩很多坑。
3. 核心细节:表格布局和表单控件
3.1 表格还是flex?新手怎么选
这是新手群里问得最多的问题。我的建议非常直接:如果老师没有特殊要求,用table来做汇款单的主布局。原因很简单,这张单子的本质是二维信息登记表,用table并不是“非法布局”,反而符合语义,因为里面的数据本来就是一张表格。你后面学的flex和grid更适合做页面导航、卡片流、整体框架,但不一定比table更适合还原一张纸质的单证。
table有天然的行列结构,colspan/rowspan正好能对应纸质单子的合并单元格,代码写起来直接。而且老式单据讲究横平竖直,table的border-collapse做出来最接近印刷效果。如果老师明确要求“不能使用table布局”,那再用flex/grid去做,但作为第一次作业,我没有遇到过这种限制。
提示:无论用哪种方案,一定要想清楚单元格的合并关系。表格里所有行的总列数必须一致,否则浏览器会自动补单元格,结果就是整个页面左右对不齐。
比如金额区可以写成这样:
<table class="amount-table"> <tbody> <tr> <td class="label">币种</td> <td>人民币</td> <td class="label">汇费</td> <td>¥</td> </tr> <tr> <td class="label">金额大写</td> <td colspan="3">壹仟贰佰元整</td> </tr> <tr> <td class="label">金额小写</td> <td colspan="3">¥1,200.00</td> </tr> </tbody> </table>这样写出来的表格行列非常清楚,后面加CSS时只需要用.label控制宽度和文字对齐,其他单元格自动填充。
3.2 输入框、单选框和印刷体的还原
纸质汇款单的填写区域通常是一条下划线,而不是一个方形的输入框。所以别让input默认的方框样式直接露出来,需要重置:
input[type="text"], textarea { border: none; border-bottom: 1px solid #333; background: transparent; border-radius: 0; outline: none; font: inherit; }单选框建议用fieldset分组,每个选项用label包起来,或者使用for和id关联。这样点击文字就能选中对应选项,操作体验接近纸质单据勾选的感觉。
印刷字体上,可以使用“楷体 + 宋体”的组合。标题用宋体或黑体加粗,填写区域用楷体模拟手写:
.remittance { font-family: "SimSun", "Songti SC", serif; } input, textarea { font-family: "KaiTi", "STKaiti", "SimSun", serif; }如果担心用户系统没装楷体,就把它放在字体栈靠前的位置,后面加一个serif兜底。第一次作业不需要追求完全跨平台一致,但至少在自己电脑上要先好看。
4. 像素级还原:字体、边框、间距
4.1 打印质感怎么调
调质感之前,先把页面当成一张真实的纸放在屏幕上。我给.remittance设置了宽度、居中、内边距、背景色和阴影,模拟纸张厚度:
body { margin: 0; background: #e9e6df; font-family: "SimSun", "Songti SC", serif; color: #222; } .remittance { width: 880px; margin: 40px auto; padding: 40px 60px; background: #fdfbf6; box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); }单证类页面的背景色不要用纯白,纯白在屏幕上显得太亮,用接近暖白的#fdfbf6或#faf7f2更接近纸张。字色用深灰而不是纯黑,避免打印和屏幕观感过于生硬。
标题“汇款单”三个字之间要拉开距离,可以用letter-spacing,并让它在横向居中:
.remittance-header h1 { font-size: 32px; letter-spacing: 0.5em; text-align: center; margin: 0 0 4px 0; } .bill-no { text-align: right; font-size: 14px; color: #444; }行高建议line-height: 1.8,这样下划线区域之间不会挤在一起,后续填字也有呼吸感。
4.2 边框线的细节
纸质单据上的线条分为实线、虚线和双线,它们用途不同:外框用实线,填写区用下划线,附言栏用虚线边框。CSS里要分清:
- 普通单元格边框用
border: 1px solid #aaa;,不要用纯黑,否则会像网页后台表格; - 表头或外框需要重点强调时,用
border-top: 2px solid #333;或者border-bottom: 2px solid #333;; - 要模拟双线效果,可以用
border-top: 3px double #333;; - 附言框用
border: 1px dashed #666;,虚线会让人直觉上知道这里是“手写区域”。
同时记得给表格设置:
.amount-table { width: 100%; border-collapse: collapse; }不写border-collapse: collapse的话,单元格之间会出现双线,看起来像断开的格线,很难用边框属性修复。
5. 我踩过的坑和调试经历
5.1 表格单元格合并的坑
我第一次做汇款单时,金额大写一行的colspan怎么算都是错的。后来在纸上画了个网格,才明白问题在于没有统一每行的总列数。比如上面那个金额表格,第一行有4个单元格,第二行第一列是“金额大写”,那么第二行总列数还是一列,所以第二列必须用colspan="3"才能把剩余3列填满,第三行同理。
如果你再加一列“备注”,那所有行的总列数都要跟着变,比如变成5列。这个变化特别容易把人绕晕。我自己的方法是:先在纸上画出格子,给每一行编号,标好每个单元格跨几行几列,再动手写HTML。代码写完后,用浏览器检查一下表格边缘是否齐整,如果出现一行少了一列,马上回头数格子。
另外也要小心rowspan的用法,很多新手在“经办人、复核人”这种垂直合并的单元格上用错。rowspan的意思是让这个单元格向下跨几行,使用后下方那一行对应位置就不要再写单元格了,否则表格总列数会多出来。
5.2 表单样式浏览器不一致
第一次作业大家通常只用Chrome调试,但打开Edge或者Safari后会发现页面走了样。最常见的几个差异是:button自带内边距和边框,textarea在Chrome右下角可以拖拽,select在不同系统下长得完全不同,input[type="number"]的上下箭头在Firefox和Safari里显示还不一样。
我建议在最外层写一个基础reset:
* { box-sizing: border-box; margin: 0; padding: 0; } button { cursor: pointer; } textarea { resize: vertical; }不要小看这段代码,它至少能让盒模型和默认边距一致。如果你的作业要求把分子数还原得很精确,box-sizing统一成border-box后,padding和border不会把单元格撑破。
提示:用
input[type="text"]还是input选择器,取决于你的页面里有没有radio、checkbox。如果只想改单行文本,建议写input[type="text"]避免把单选框样式也改乱。
5.3 宽度溢出和横向滚动
页面写完后,如果浏览器的窗口缩小,固定宽度880px的汇款单会出现横向滚动条。这在PC端作业里不算大问题,但最好还是处理一下:把固定width改成max-width加min-width,让它在小窗口下也能正常滚动,而不是被压缩成一团。
.remittance { width: 880px; max-width: 100%; min-width: 780px; }如果表格内容过长,单元格被撑破,可以给表格设置:
.amount-table { table-layout: fixed; width: 100%; word-break: break-all; }table-layout: fixed会让表列宽由第一行或设定的width决定,而不是由内容撑开,这样能避免金额、地址这种长文本把单元格撑乱。第一次作业如果能注意到这一点,页面在窗口缩放时会有明显更好的表现。
6. 提交前的自检清单和进阶方向
6.1 自检项目
交作业之前,别只停留在“能打开”的程度。我把当时自己用的检查清单整理成了一张表,你可以对照着过一遍:
| 检查项 | 说明 |
|---|---|
| 标题和单号 | 是否正确居中或靠右,字体是否堆积 |
| 区块顺序 | 收款人、汇款人、金额、附言是否与参考图一致 |
| 表格列数 | 每行总列数是否一致,有没有错位 |
| 表单控件 | 每个input的name是否预留,label是否关联 |
| 浏览器检查 | Chrome、Edge、Safari至少打开一次,并在不同宽度下观察 |
| 打印预览 | Ctrl+P 看一下打印效果,是否要加 @media print |
| 代码规范 | 标签是否闭合、缩进是否统一、CSS类名是否语义化 |
这里面最容易忽略的是label关联。很多人只写一个placeholder,真正的label缺失,虽然作业能过,但未来做无障碍时会遇到麻烦。养成习惯,给每个输入区域配上label或者aria-label,成本很低,收益是长期的。
6.2 做完之后还能怎么折腾
如果这份作业你一天就做完了,可以再往上叠几个小功能,把它们当成练手:
- 加一个打印样式,让
.remittance去掉阴影、背景变白、宽度适配A4纸:
@media print { body { background: #fff; } .remittance { width: 100%; margin: 0; box-shadow: none; } }用JavaScript做输入校验,比如金额必须是数字、姓名不能为空。这个动画可能需要用到表单事件,但第一次接触也不会太难。
写一个金额大小写转换函数,把数字
1234转成壹仟贰佰叁拾肆元整,这是我见过很多前端练习里最有成就感的函数之一。尝试把整张汇款单改成移动端布局,看看在小屏上怎么把表格拆开,这就是响应式设计的入口。
把字体换成在线WebFont,让楷体在别人电脑上也能显示出来,顺便学习引入外部字体的流程。
这些进阶练习都基于同一张汇款单,一次作业可以延伸成一个小型项目。我见过有同学做到第3步后,直接把页面做成一个“汇款单生成器”,输入金额自动生成完整单据,老师给的分数和收获都完全不一样。
最后说点个人体会。我自己第一次做这类单据页面时,觉得“汇款单”三个字很土,巴不得赶紧用几个div糊弄过去。后来在实习里补单据、做回单页面,才明白基础就是表格和表单的排列组合。如果你现在也在写这份作业,别急着把页面做出花,先把行和列关系理清,再把边框、字体、间距调到舒服,老师看到的就不只是一份作业,而是一种“能还原真实业务界面”的能力。真的把这个过程走一遍,后面再学浮动、flex、grid、组件化,都能找到对应的手感。