news 2026/10/14 1:41:52

HTML表单与表格实战:从图书登记到成绩统计的完整拆解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HTML表单与表格实战:从图书登记到成绩统计的完整拆解

聊到HTML入门作业,十个里至少有八个跟表单和表格有关。最近帮人看前端基础作业,收到两份很典型的要求:一份是“图书信息登记页面”,表单录数据、表格列清单;另一份是“学生成绩登记与统计页面”,表单收成绩、表格算汇总。这两道题看起来基础,实际上把HTML表单的所有核心控件、表格的语义化结构、合并单元格,甚至老式的表格页面布局都串起来了。这篇就用这两个经典作业案例,把从需求拆解到完整代码的过程完整跑一遍。适合刚学完HTML基础、想找实际操作练手的人,也适合正在做类似课程作业的同学直接对照参考。

1. 先拆题:两个作业案例到底在考什么

1.1 为什么“表单+表格”是作业标配

很多初学者觉得作业里表单和表格放一起是巧合,其实这就是Web开发里最典型的一个信息管理界面形态:上面是录入区,收集用户输入;下面是展示区,把数据列成表格给人看。比如后台管理系统的商品上架、员工信息维护、订单一览,底层都是这个套路。

表单负责“收集数据”,表格负责“展示数据”,两者配合就是一个完整的小型管理页面。课程作业选这两个来考,是因为它们把HTML里最常见的一组标签全部覆盖了:表单涉及form、input、select、textarea、label、fieldset,表格涉及table、thead、tbody、tfoot、th、td、colspan、rowspan。一套作业做完,HTML最核心的交互组件和结构化组件就都过了一遍。

1.2 案例A:图书信息登记页面的需求拆解

图书信息登记这个题目通常长这样:需要设计一个页面,用于录入图书的书名、作者、ISBN编号、出版日期、分类、阅读状态和价格,然后把已录入的图书以表格形式展示出来。

把它拆开看,表单部分考的是“控件选型”。书名是单行短文本,用input type="text";价格是数值,可以用input type="number"并且限制范围;出版日期有专门的input type="date",会弹出日期选择器;分类属于固定选项,用select下拉更省空间;阅读状态只有已读、未读、在读几种情况,用radio单选最直观。

表格部分考的是“信息呈现”。表格需要给每一列设置清晰的表头,行的组织要一致,必要的时候还要给表格加caption说明表标题。这个案例做完,基本上就把一个数据表格从结构到展示的完整流程走了一遍。

1.3 案例B:学生成绩登记与统计页面的需求拆解

学生成绩登记与统计比案例A上了一个台阶。它要求表单能录入姓名、学号、平时成绩、期末成绩,同时需要一个成绩表格,汇总每个学生的总成绩和等级,并且在表格底部展示全班平均分。

这个题目的考点很明确:首先表单要考数值输入的限制,成绩0到100之间,不能乱填;其次表格的语义化结构要完整,表头用thead,数据区用tbody,统计区用tfoot;最后还要用到合并单元格,表头里“平时/期末”两项属于“成绩”这个大列的细分,需要colspan跨列,序号列从第一行表头跨到第二行,需要rowspan跨行。

更有意思的是,有些版本的作业会额外要求用表格做整个页面的框架,比如顶部是标题栏、左侧是导航菜单、右侧是内容区、底部是页脚,这属于“表格布局页面”的经典考法。两个案例结合起来,正好把表格的数据功能和布局功能都练到了。

2. 表单部分:控件选型、校验和布局一次讲透

2.1 表单骨架:form、fieldset、legend、label怎么搭配

写表单第一步是搭骨架,不是急着堆输入框。骨架由四层组成:最外层是form,声明数据要往哪提交、用什么方式提交;里面用fieldset把控件按逻辑分组,比如案例A里“图书基本信息”一组;legend是分组的标题,浏览器会在组外框左上角显示一行说明文字;label负责关联具体的控件,点击文字就能聚焦到输入框。

<form action="#" method="post"> <fieldset> <legend>图书基本信息</legend> <label for="bookTitle">书名</label> <input type="text" id="bookTitle" name="bookTitle"> </fieldset> </form>

这里有个初学者很容易漏掉的细节:label的for属性必须跟对应input的id值一致。很多人在input上写了name却忘了id,导致label用不了。name和id是两个完全不同的东西,name是提交给后端用的字段名,id是页面里定位这个元素的标识,二者缺一不可。

2.2 输入控件怎么选:从文本到日期再到单选复选

控件选型说白了就是“什么数据用什么控件”。案例A里已经用到了好几种,这里展开说一下选型逻辑。

单行文本用input type="text",适合书名、作者、ISBN这类短内容。多行文本用textarea,适合填写简介、备注。数字用input type="number",浏览器会自动校验内容是不是数字,还可以配合min、max、step控制范围和步长。日期用input type="date",PC端Chrome会直接弹出日历选择器。下拉框用select配合option,适合分类这种固定选项,优点是节省页面空间,用户不会填错。单选用radio,同一组选项要保持name值相同,这样浏览器才会把它们当成一组,实现互斥选择。复选用checkbox,适合“是否重修”“是否借阅过”这种标记类选项。

这里重点说一下radio的坑。三个单选框如果name不一致,用户可以同时选中多个,那就失去了单选的意义。我在批类似作业时见过不少人把三个name写成三个不同的值,实际页面一跑,点哪个亮哪个,完全没互斥效果。另外,如果要设置默认选中,直接在对应的input上加checked属性就行,不用写checked="checked",HTML5模式下写checked就生效。

2.3 让浏览器帮忙校验:required、pattern、min、max

作业里经常要求“不能为空”“格式要正确”。如果只用纯HTML,不用JavaScript,靠的是HTML5的原生表单校验属性。

required让浏览器在提交时检查字段有没有值,空值会弹出提示并阻止提交。pattern用正则约束内容格式,比如ISBN的写法可以写成pattern="[0-9-]{10,17}",它允许10到17位的数字或连字符组合。min和max用于限制数值范围,成绩就用min="0" max="100"。type="email"会自动校验邮箱格式,type="number"自动校验是否为数字,这些都属于“免费的校验”,比起写一堆JS来验证要省事得多。

要注意的是,原生校验的逻辑是“输入框内容不满足约束时,点提交会弹出提示并且不发送表单”。这个提示文案浏览器默认是英文的,可在input上加title属性补充说明,这样用户悬停或看到提示时更容易明白哪里填错了。作业里如果只要求静态页面,原生校验完全够用。

2.4 表单排版:CSS布局和“表格布局表单”的旧写法

表单控件默认是竖着排列的,直接写能看但不好看,所以需要排版。现在主流做法是用CSS布局,比如案例A里我用.form-row把每个label和控件放在一行,label设置固定宽度并右对齐,看起来整齐。

但作业里偶尔会考一种老式写法:用表格来排表单控件。写法是form套table,table里若干行,第一行放label,第二行放input,利用表格的自动对齐让整个表单排列整齐。这个写法在早期Web开发里非常普遍,因为那时候CSS还不成熟,用表格排版是唯一简单靠谱的方式。

<form> <table> <tr> <th>书名</th> <td><input type="text" name="bookTitle"></td> </tr> <tr> <th>作者</th> <td><input type="text" name="bookAuthor"></td> </tr> </table> </form>

需要记住的是,form包table是合法的,反过来在table里直接嵌套form是不推荐的,因为表单控件可能无法正常关联提交。用表格排表单在今天已经很少用了,但理解它的原理可以帮助你读懂老代码。作业里既然教了这个技巧,就说明课程想让你明白表格的对齐能力有多强,这点在后面的“表格布局页面”里还会再遇到。

2.5 GET还是POST:作业里提交地址怎么处理

表单的method属性决定数据怎么发给服务器。GET会把表单字段拼在URL后面,比如提交后地址变成?bookTitle=xxx&author=yyy,好处是方便调试和分享,坏处是数据暴露在地址栏里,不适合提交密码或大段内容。POST把数据放在请求体里,地址栏不会显示,适合提交数据、保存信息。

作业里通常没有写好的后端接口,action往往填#,意思是不跳转到其他页面,提交时停留在当前页。这种写法点提交后页面会刷新一下,看起来“数据没保存”,这其实是正常的,因为浏览器没有后端配合,表单数据发出去也没人接收。如果老师只要求静态页面,你大可放心用action="#" method="post"。

我见过一种常见误解:有人以为action="#method="post"填上之后,提交的数据会被保存在页面里。实际上纯HTML没有任何本地存储能力,要真正保存数据得配合后端程序或本地存储,这不是HTML能单独完成的。作业里演示效果到“提交刷新”这一步就算完成。

3. 表格部分:语义化、合并单元格与页面布局

3.1 不要再一个table打天下:thead、tbody、tfoot各司其职

很多初学者写表格就是一堆tr和td堆到底,虽然浏览器能正常显示,但少了三层结构标签:thead、tbody、tfoot。这三个标签不会改变页面的视觉效果,但把表格分成了表头、主体、表尾三个逻辑部分,对样式控制和语义表达都有帮助。

表头区放th标签,浏览器默认加粗居中,一般用于列标题。主体区放真正的数据行,用td。表尾区适合放汇总行,比如成绩表格的“平均分”那一行。使用tfoot之后,即使tbody里的数据很多,滚动页面时表格底部的统计行也能被浏览器识别为独立区块,方便统一处理样式。

从语义化的角度讲,th和td的区别不只是加粗和居中。th告诉屏幕阅读器“这一格是表头,用于描述整列或整行的含义”,对无障碍访问很重要。作业里如果要求语义结构完整,记得thead、tbody、tfoot三个都要出现。

3.2 合并单元格的“格子守恒定律”:colspan和rowspan实战

合并单元格是表格最考验逻辑的部分,很多人的表格错位都出在这。colspan表示单元格横向跨几列,rowspan表示单元格纵向跨几行。比如“成绩”表头想覆盖“平时”和“期末”两列,就在“成绩”这一格写colspan="2";序号列想让两个表头行都共享同一格,就写rowspan="2"。

我习惯用“格子守恒定律”来检查合并有没有写对:每一行的总列数必须相等。计算方法是把这一行所有单元格的colspan值累加起来(没写rowspan的按1算,写了rowspan的也要按列数算进去),得到的结果应该等于表格的总列数。如果某一行加起来比总列数少一列,那多半是colspan少写了1;如果多了一列,那多半是某一行多写了一个td。

举例来说,案例B的成绩表总列数是7列:序号、学号、姓名、平时、期末、总分、等级。表头第一行有4个rowspan="2"的单元格,占4列,再加上“成绩”这个colspan="2"占2列,最后“总分”占1列,一共4+2+1=7列。第二行用来补全第一行被合并掉的平时和期末两列,所以只有2个th。这个计算过程一写出来,逻辑就清楚了。

3.3 表格布局页面框架:经典写法与为什么不推荐

“表格布局”这个词在HTML作业里通常指用表格搭建整个页面的骨架。经典结构是一个外层table,第一行放顶部标题栏,colspan="2"横跨全页;第二行左侧单元格固定宽度放导航菜单,右侧单元格放主要内容;第三行又是colspan="2"的底部页脚。案例B的页面框架就是这样设计的。

这个写法的好处是简单粗暴,不用写任何CSS,表格的单元格天然具备宽度、对齐、嵌套等布局能力。早期浏览器CSS支持很差,表格布局几乎是唯一可靠的方案,也因此留下了大量用表格堆出来的老站点。

但放在今天,表格布局的缺点非常明显。第一,表格的结构标签是为了表示数据而设计的,拿它做布局会让HTML语义变得混乱,屏幕阅读器读起来很痛苦。第二,表格嵌套过多时页面代码极难维护,改一列样式可能要动十几个td。第三,表格布局天然不支持响应式,手机端不会自动重排。所以现在的实际开发中,页面整体布局首选CSS排版,表格只负责展示真正的数据。

作业里如果明确要求“使用表格布局页面”,那你就按经典写法来,同时心里明白这是一个历史产物;如果要求不严,更建议用CSS布局,并且可以在作业说明里写下你选择CSS的理由,这反而能成为加分项。

3.4 表格样式三板斧:边框、内边距和斑马纹

纯HTML表格的默认样式很朴素,边框细得看不清,单元格之间还有双线间距。为了作业效果更好看,通常要给表格写一点基础CSS。我建议先从三个方向下手。

第一是边框。table { border-collapse: collapse; }可以把相邻单元格的边线合并成一条,否则表格会出现双线。给th, td加border: 1px solid #ccc;,整个表格的格子轮廓就出来了。第二是内边距。th, td { padding: 8px; }让内容不贴边,看起来更透气。第三是斑马纹。用tr:nth-child(even) { background: #f9f9f9; }给偶数行加浅色背景,阅读长表格时不容易看串行。

这三个样式加起来不到十行代码,但表格的观感会发生质变。进阶一点还可以给表头加背景色,比如th { background: #4a90d9; color: #fff; },整个表格立刻从“作业的草稿”变成“可以拿去演示的成品”。这些CSS不是HTML的重点,但能让作业在验收时第一印象好很多。

4. 两个案例的完整代码与实现详解

4.1 案例A完整代码:图书信息登记

案例A的核心思路是“上半部分表单录入,下半部分表格展示”。表单字段覆盖了文本、数字、日期、下拉、单选、按钮这些常见控件,表格则用caption加thead加tbody组成标准结构。

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>图书信息登记</title> <style> body { font-family: "Microsoft YaHei", sans-serif; background: #f5f5f5; padding: 20px; } .container { max-width: 800px; margin: 0 auto; background: #fff; padding: 25px; border-radius: 8px; } h1 { text-align: center; color: #333; } form { margin-bottom: 30px; } fieldset { border: 1px solid #ddd; border-radius: 6px; padding: 15px 20px; margin-bottom: 15px; } legend { color: #555; font-weight: bold; } .form-row { margin-bottom: 12px; } .form-row label { display: inline-block; width: 100px; text-align: right; margin-right: 10px; } .form-row input[type="text"], .form-row input[type="number"], .form-row input[type="date"], .form-row select { width: 260px; padding: 5px; } .btn-group { text-align: center; margin-top: 15px; } .btn-group input { padding: 6px 18px; margin: 0 6px; cursor: pointer; } table { width: 100%; border-collapse: collapse; } th, td { border: 1px solid #ccc; padding: 8px; text-align: center; } th { background: #4a90d9; color: #fff; } tr:nth-child(even) { background: #f9f9f9; } </style> </head> <body> <div class="container"> <h1>图书信息登记</h1> <form action="#" method="post"> <fieldset> <legend>图书基本信息</legend> <div class="form-row"> <label for="bookTitle">书名</label> <input type="text" id="bookTitle" name="bookTitle" placeholder="请输入书名" required> </div> <div class="form-row"> <label for="bookAuthor">作者</label> <input type="text" id="bookAuthor" name="bookAuthor" required> </div> <div class="form-row"> <label for="isbn">ISBN</label> <input type="text" id="isbn" name="isbn" placeholder="13位数字,可带连字符" pattern="[0-9-]{10,17}" required> </div> <div class="form-row"> <label for="publishDate">出版日期</label> <input type="date" id="publishDate" name="publishDate" required> </div> <div class="form-row"> <label for="category">图书分类</label> <select id="category" name="category"> <option value="计算机">计算机</option> <option value="文学">文学</option> <option value="历史">历史</option> <option value="科学">科学</option> <option value="其他">其他</option> </select> </div> <div class="form-row"> <label>阅读状态</label> <input type="radio" id="statusRead" name="status" value="已读" checked> <label for="statusRead">已读</label> <input type="radio" id="statusUnread" name="status" value="未读"> <label for="statusUnread">未读</label> <input type="radio" id="statusReading" name="status" value="在读"> <label for="statusReading">在读</label> </div> <div class="form-row"> <label for="price">价格(元)</label> <input type="number" id="price" name="price" min="0" max="1000" step="0.1" required> </div> </fieldset> <div class="btn-group"> <input type="submit" value="添加图书"> <input type="reset" value="重置"> </div> </form> <h2>图书列表</h2> <table> <caption>馆藏图书清单</caption> <thead> <tr> <th>序号</th> <th>书名</th> <th>作者</th> <th>ISBN</th> <th>出版日期</th> <th>分类</th> <th>状态</th> <th>价格</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>深入理解计算机系统</td> <td>某作者</td> <td>978-7111-00000-0</td> <td>2021-06-01</td> <td>计算机</td> <td>已读</td> <td>89.00</td> </tr> <tr> <td>2</td> <td>活着</td> <td>某作者</td> <td>978-7506-00000-0</td> <td>2020-09-15</td> <td>文学</td> <td>在读</td> <td>35.50</td> </tr> <tr> <td>3</td> <td>JavaScript高级程序设计</td> <td>某作者</td> <td>978-7111-00001-7</td> <td>2019-11-20</td> <td>计算机</td> <td>未读</td> <td>128.00</td> </tr> </tbody> </table> </div> </body> </html>

4.2 案例A关键实现点:表单控件组合与表格列设计

案例A里值得注意的第一个细节是pattern="[0-9-]{10,17}"这个校验。它允许10到17位数字或连字符,基本覆盖了常见ISBN写法。但要注意当年份、出版社编号不规范时,这个正则可能误判,所以只适合演示效果,真实项目里ISBN校验要用更精确的算法。

第二个细节是单选按钮的写法。三个radio的name都是status,所以浏览器知道它们是一组,value分别是已读、未读、在读,提交后后端接收到的就是这三个值之一。第一个radio加了checked,页面加载时默认选中已读,这对用户体验有实际意义。

第三个细节是表格的“列设计”。表头8列,数据行就要一一对应8个td,这个对应关系一旦错位,表格内容就会往左或往右偏一格,看起来乱七八糟。自查方法就是数列数:thead里几个th,tbody每一行就必须几个td,不能多也不能少。

4.3 案例B完整代码:成绩登记、统计与表格页面框架

案例B的页面比案例A复杂一些,它融合了表格的数据功能和布局功能。外层表格负责整个页面的框架,内层表格负责成绩数据展示。表单字段包括姓名、学号、平时成绩、期末成绩,外加一个复选的重修标记,成绩表用colspan和rowspan做了一个双行表头,底部用tfoot放平均分。

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>学生成绩登记与统计</title> <style> body { font-family: "Microsoft YaHei", sans-serif; } .page-table { width: 900px; margin: 20px auto; border-collapse: collapse; } .page-table td { border: 1px solid #ccc; vertical-align: top; padding: 12px; } .page-header { background: #3b6ea5; color: #fff; text-align: center; height: 60px; } .page-nav { width: 160px; } .page-nav ul { list-style: none; padding: 0; margin: 0; } .page-nav li { padding: 8px 12px; margin-bottom: 6px; background: #efefef; } .page-footer { text-align: center; background: #eee; height: 40px; } .data-table { width: 100%; border-collapse: collapse; margin-top: 10px; } .data-table th, .data-table td { border: 1px solid #aaa; padding: 6px; text-align: center; } .data-table th { background: #5b8dcf; color: #fff; } .data-table tfoot td { background: #eef4fb; font-weight: bold; } .form-row { margin-bottom: 8px; } .form-row label { display: inline-block; width: 80px; text-align: right; margin-right: 8px; } </style> </head> <body> <table class="page-table"> <tr> <td colspan="2" class="page-header">某学院课程管理系统</td> </tr> <tr> <td class="page-nav"> <ul> <li>学生管理</li> <li>成绩管理</li> <li>课程管理</li> <li>系统设置</li> </ul> </td> <td> <h3>成绩登记</h3> <form action="#" method="post"> <div class="form-row"> <label for="stuName">姓名</label> <input type="text" id="stuName" name="stuName" required> </div> <div class="form-row"> <label for="stuId">学号</label> <input type="text" id="stuId" name="stuId" pattern="[0-9A-Za-z]{6,12}" required> </div> <div class="form-row"> <label for="dailyScore">平时成绩</label> <input type="number" id="dailyScore" name="dailyScore" min="0" max="100" required> </div> <div class="form-row"> <label for="finalScore">期末成绩</label> <input type="number" id="finalScore" name="finalScore" min="0" max="100" required> </div> <div class="form-row"> <input type="checkbox" id="retake" name="retake" value="是"> <label for="retake">重修标记</label> </div> <input type="submit" value="提交登记"> <input type="reset" value="清空"> </form> <h3>成绩统计表</h3> <table class="data-table"> <caption>学期成绩汇总</caption> <thead> <tr> <th rowspan="2">序号</th> <th rowspan="2">学号</th> <th rowspan="2">姓名</th> <th colspan="2">成绩</th> <th rowspan="2">总分</th> <th rowspan="2">等级</th> </tr> <tr> <th>平时</th> <th>期末</th> </tr> </thead> <tbody> <tr> <td>1</td> <td>2023001</td> <td>学生甲</td> <td>85</td> <td>90</td> <td>175</td> <td>优秀</td> </tr> <tr> <td>2</td> <td>2023002</td> <td>学生乙</td> <td>70</td> <td>66</td> <td>136</td> <td>及格</td> </tr> <tr> <td>3</td> <td>2023003</td> <td>学生丙</td> <td>92</td> <td>88</td> <td>180</td> <td>优秀</td> </tr> </tbody> <tfoot> <tr> <td colspan="3">平均分</td> <td>82.3</td> <td>81.3</td> <td>163.7</td> <td>—</td> </tr> </tfoot> </table> </td> </tr> <tr> <td colspan="2" class="page-footer">前端课程作业 · 表格布局演示</td> </tr> </table> </body> </html>

4.4 案例B关键实现点:跨行表头、汇总行与页面框架

案例B的表头是整个代码里最容易写错的部分。第一行表头写了序号、学号、姓名、成绩、总分、等级,其中序号等前三项和后两项一共五个单元格都加了rowspan="2",成绩列加的是colspan="2"。第二行只有两个th:平时和期末。两个表头行拼在一起才组成完整的7列表头,这就是双行表头的标准写法。

tfoot里的平均分行同样用到了表格的布局逻辑。colspan="3"让“平均分”这个说明文字横跨序号、学号、姓名三列,后面再写平时平均、期末平均、总分平均各占一列,最后一列等级不需要统计,用横杠占位。这样底部一行7格,和上方的表格结构保持了一致。

外层表格则是“表格布局页面”的体现。第一行colspan="2"放标题栏,第二行左侧td固定宽度160px放导航,右侧td放内容和成绩表,第三行再一个colspan="2"放页脚。整个页面不需要写float或flex,靠表格的自然排列就能铺满,这就是老式页面布局的核心原理。如果你交作业时能把这个表格布局的思路写进说明里,老师一眼就能看出你吃透了知识点。

5. 作业实战中的高频问题与自查清单

5.1 label点了没反应、表单提交后页面空白

llabel点了没反应,十有八九是for和id没对上。检查方法很简单:在浏览器里按F12打开开发者工具,查看这个label的for属性值,再对比对应input的id值,必须完全一致才算关联成功。有些同学在input上写的是name,以为for填name就行,这是最常见的错误。

表单提交后页面空白,通常是因为action="#"且没有写method。表单默认的method是GET,提交后地址栏会多出一串参数,看起来像页面“摔了”,其实只是表单把数据拼到了URL里。如果你想让提交后页面规规矩矩地保持在原位置,可以写成action="#" method="post",这样地址栏不会出现参数,页面原地刷新。

5.2 表格错位:合并单元格后列对不上

表格错位几乎都是合并单元格后“格子守恒定律”被打破了。要么colspan多写一列,要么rowspan少跨一行,导致下一行的单元格数量跟总列数对不上。

排查时不要盯着DOM看,用最笨的办法:把每一行单独列出来,数一下这一行的colspan累加值。比如一个7列表格,某一行只有一个<td colspan="2">加五个普通<td>,那就是2+5=7,正确;如果只有2+4=6,差一列,那就要检查是不是某个td漏写了,或者某个colspan少写了1。这个检查逻辑对双层表头尤其有效。

另外,rowspan会导致被跨掉的下一行“少”一列,这是正常现象。比如案例B第一行表头有五个rowspan="2"的单元格,第二行就只有两个th,而不是七个。如果你在第二行也写了七个th,表格结构反而会多出来五列,直接错位。

5.3 表格嵌套表格导致页面布局失控

表格布局页面的代码里经常出现“表格套表单表单里再套表格”的情况,层级一深,宽度就容易崩。最典型的症状是:某个单元格里嵌了一个宽表格,把父级单元格撑得特别宽,整个页面框架被挤变形。

解决办法是给外层表格设置固定或最大宽度,比如案例B里的.page-table { width: 900px; },同时给嵌套表格设置width: 100%,让它按父容器的宽度自适应,而不是按自己的内容撑开。还有一点,table默认是“内容多宽就多宽”,画表格前尽量在样式里统一给table声明宽度,避免出现“内容越长页面越宽”的连锁反应。

5.4 交作业前必过的自查清单

每次作业交出去之前,我都会按下面这个清单过一遍,能挡掉绝大部分低级错误:

  • 每个input都有对应的label,且for和id一致
  • 同一组单选按钮的name相同,且有默认checked
  • 每个form里有submit按钮和reset按钮
  • 表格有thead、tbody,需要统计时有tfoot
  • 用了合并单元格后,每行colspan累加值等于表格总列数
  • 所有标签都闭合,没有遗漏</td>或</tr>
  • 页面在浏览器里缩放宽度后没有明显横向滚动条

清单看起来琐碎,但都是真实批改作业时的高频扣分点。尤其是标签闭合这块,少一个</td>浏览器不会直接报错,而是默默把结构自动补齐,导致表格出现不明所以的空格或错位,这种问题最烦人,也最影响最终效果。

做这两个案例给我的整体感受是,HTML表单和表格的知识点并不难,但它是特别容易“想当然”的内容。控件、结构、合并规则这些细节,看文档时觉得都会,自己动手一写就漏洞百出。我自己批改类似的作业时,最常见的扣分点从来不是不会写,而是写了错、错了不知道怎么查。希望这篇拆解和排查清单,能让你在交作业之前把那些“想当然”的坑全部填平。最后一个小建议:代码一定不要复制粘贴完就交,把每个标签的作用在脑子里过一遍,再自己动手默写一个表格,比看十遍教程都有用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 1:41:49

零硬件入门STM32:Keil仿真跑通GPIO、定时器与串口

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/14 1:41:48

推荐系统增量重训练新思路:序列元学习如何实现快速适应

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/14 1:41:47

本地优先的AI资讯筛选浏览器插件:从采集到通知的完整开发实战

1. 项目起因与整体思路&#xff1a;被 AI 信息洪水淹没之后的“反叛”我每天打开电脑的第一件事&#xff0c;不再是写代码&#xff0c;而是刷各类 AI 资讯&#xff1a;公众号推送、技术社区热帖、模型发布公告、开源项目的 release note&#xff0c;还有各种榜单和复盘。刷了半…

作者头像 李华
网站建设 2026/10/14 1:41:31

QCC300x左右声道合并输出:单喇叭音频调试全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/14 1:41:03

PyQt5/PyQt6 实现 Windows 亚克力效果:原理、代码与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/14 1:41:00

手持示波器实战指南:从吃灰到现场调试利器

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华