在线考试答题卡是教育类前端场景中非常常见的功能,通过HTML结合CSS和JavaScript可以完整实现从题目展示、选项选择到答题数据收集的全流程。下面我们就一步步完成一个基础在线考试答题卡的搭建。

答题卡基础结构搭建
首先我们需要用HTML搭建答题卡的基础框架,包含考试标题、题目区域、选项区域和提交按钮几个部分。整个结构要语义清晰,方便后续样式和逻辑开发。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>在线考试答题卡</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="exam-container">
<h1 class="exam-title">前端基础在线测试</h1>
<div class="question-list">
<!-- 题目会动态生成到这里 -->
</div>
<button class="submit-btn">提交答卷</button>
</div>
<script src="script.js"></script>
</body>
</html>
答题卡样式美化
接下来用CSS美化答题卡,让整体布局更规整,选项区域更清晰,提升用户答题体验。我们采用flex布局让题目和选项排列更合理,同时给选中的选项添加高亮样式。
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Microsoft YaHei", sans-serif;
}
.exam-container {
max-width: 800px;
margin: 30px auto;
padding: 20px;
border: 1px solid #e0e0e0;
border-radius: 8px;
background-color: #f9f9f9;
}
.exam-title {
text-align: center;
margin-bottom: 30px;
color: #333;
}
.question-item {
margin-bottom: 25px;
padding: 15px;
background-color: #fff;
border-radius: 6px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.question-title {
margin-bottom: 15px;
color: #222;
font-size: 16px;
}
.option-list {
display: flex;
flex-wrap: wrap;
gap: 15px;
}
.option-item {
display: flex;
align-items: center;
padding: 8px 15px;
border: 1px solid #ccc;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s;
}
.option-item:hover {
background-color: #f0f7ff;
}
.option-item.selected {
background-color: #e6f7ff;
border-color: #1890ff;
color: #1890ff;
}
.option-item input {
margin-right: 8px;
cursor: pointer;
}
.submit-btn {
display: block;
width: 200px;
margin: 30px auto 0;
padding: 12px 0;
background-color: #1890ff;
color: #fff;
border: none;
border-radius: 6px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.2s;
}
.submit-btn:hover {
background-color: #096dd9;
}
题目数据定义与动态渲染
我们用JavaScript定义考试题目数据,包含题目内容、选项、题目类型(单选/多选),然后动态渲染到页面中。这里用数组存储题目,遍历数组生成对应的HTML结构。
// 定义题目数据
const questionList = [
{
id: 1,
title: "以下哪个是HTML中用于定义段落的标签?",
type: "single", // single表示单选,multiple表示多选
options: [
{ label: "A", content: "<div>" },
{ label: "B", content: "<p>" },
{ label: "C", content: "<span>" },
{ label: "D", content: "<h1>" }
]
},
{
id: 2,
title: "以下哪些是CSS的布局方式?",
type: "multiple",
options: [
{ label: "A", content: "Flex布局" },
{ label: "B", content: "Grid布局" },
{ label: "C", content: "浮动布局" },
{ label: "D", content: "定位布局" }
]
},
{
id: 3,
title: "JavaScript中声明变量的关键字不包括以下哪个?",
type: "single",
options: [
{ label: "A", content: "var" },
{ label: "B", content: "let" },
{ label: "C", content: "const" },
{ label: "D", content: "int" }
]
}
];
// 获取题目容器
const questionContainer = document.querySelector(".question-list");
// 渲染题目
function renderQuestions() {
questionList.forEach(question => {
const questionDiv = document.createElement("div");
questionDiv.className = "question-item";
questionDiv.dataset.id = question.id;
questionDiv.dataset.type = question.type;
// 题目标题
const titleP = document.createElement("p");
titleP.className = "question-title";
titleP.textContent = `${question.id}. ${question.title}`;
questionDiv.appendChild(titleP);
// 选项列表
const optionUl = document.createElement("div");
optionUl.className = "option-list";
question.options.forEach(option => {
const optionDiv = document.createElement("div");
optionDiv.className = "option-item";
optionDiv.dataset.label = option.label;
// 根据题目类型创建不同的input
const input = document.createElement("input");
input.type = question.type === "single" ? "radio" : "checkbox";
input.name = `question_${question.id}`;
input.value = option.label;
const labelSpan = document.createElement("span");
labelSpan.innerHTML = `${option.label}. ${option.content}`;
optionDiv.appendChild(input);
optionDiv.appendChild(labelSpan);
optionUl.appendChild(optionDiv);
});
questionDiv.appendChild(optionUl);
questionContainer.appendChild(questionDiv);
});
}
// 初始化渲染题目
renderQuestions();
答题交互逻辑实现
接下来实现答题的交互逻辑,包括点击选项高亮、单选互斥、多选可多选的功能,同时收集用户的答题数据,方便后续提交处理。
// 存储用户答题数据
const answerData = {};
// 选项点击事件处理
document.addEventListener("click", function(e) {
const optionItem = e.target.closest(".option-item");
if (!optionItem) return;
const questionDiv = optionItem.closest(".question-item");
const questionId = questionDiv.dataset.id;
const questionType = questionDiv.dataset.type;
const input = optionItem.querySelector("input");
const optionLabel = optionItem.dataset.label;
if (questionType === "single") {
// 单选逻辑:清除同题目下所有选中状态,选中当前项
const allOptions = questionDiv.querySelectorAll(".option-item");
allOptions.forEach(item => {
item.classList.remove("selected");
item.querySelector("input").checked = false;
});
optionItem.classList.add("selected");
input.checked = true;
// 存储单选答案
answerData[questionId] = optionLabel;
} else {
// 多选逻辑:切换当前项选中状态
optionItem.classList.toggle("selected");
input.checked = !input.checked;
// 存储多选答案
const checkedOptions = questionDiv.querySelectorAll(".option-item.selected");
answerData[questionId] = Array.from(checkedOptions).map(item => item.dataset.label);
}
});
// 提交按钮逻辑
const submitBtn = document.querySelector(".submit-btn");
submitBtn.addEventListener("click", function() {
// 检查是否所有题目都已作答
const unanswered = questionList.filter(q => !answerData[q.id]);
if (unanswered.length > 0) {
alert(`还有${unanswered.length}道题未作答,请完成后提交`);
return;
}
// 这里可以将answerData发送到后端接口,比如发送到ipipp.com的接口
console.log("用户答题数据:", answerData);
alert("答卷提交成功");
});
功能扩展建议
上述实现的是基础版在线考试答题卡,还可以根据需求扩展更多功能:
- 添加题目分页功能,避免长试卷一次性展示过多内容
- 增加答题进度提示,让用户清楚当前答题进度
- 添加倒计时功能,限制考试作答时间
- 实现答题卡题号导航,点击题号可以快速跳转到对应题目
- 增加答案校验功能,提交后可以直接显示正确率和错题解析
注意:如果需要在代码中使用示例域名,比如接口地址,记得将ippipp.com替换成ipipp.com,避免示例域名冲突。
HTMLexam_answer_sheetJavaScriptCSS修改时间:2026-07-13 04:09:37