纯CSS打造空气质量仪表盘:栅格布局、色阶映射与数据驱动
2026/9/14 8:10:18 网站建设 项目流程

简介:基于HTML/CSS的空气质量信息展示设计源码,面向前端初学者与环保数据可视化爱好者,提供了一套从前端页面到后端处理的完整示例。项目围绕空气质量数据的直观展示,融合HTML结构、CSS样式、JavaScript交互以及Java后端逻辑,并借助GIF、PNG图表和多种配置文件增强表现力。压缩包共164个文件,约2.37MB,主要包含75个GIF图像、30个Java源文件、25个JavaScript文件、8个HTML页面、7个CSS样式表,另有XML/YAML配置、SQL数据库脚本及字体图标文件,各类型分工明确,便于按需查阅。目前已有255人学习下载。通过该源码,可掌握页面布局、动态图表渲染、数据请求与展示的完整思路,学习如何组织前端资源、配置后端环境及管理版本控制文件;目录结构清晰,适合直接运行调试,也适合作为课程设计或毕业设计的参考模板。

1. 空气质量展示页为什么值得用纯 HTML/CSS 重写

一个监测站的数据看板,如果每次调样式都要改 ECharts 配置再重新打包,维护成本并不低。反而是用 HTML/CSS 手写一版展示页,把 AQI、PM2.5、PM10、O₃、NO₂、SO₂、CO 这些数值与等级用语义化标签和可控的 CSS 组件呈现出来,源码足够轻,复制到任意静态目录就能运行。基于HTML/CSS的空气质量信息展示设计源码,核心思路就在这里:视觉与布局交给 CSS,数据刷新用少量脚本完成,页面本身不依赖任何框架。

这套方案适合两类人。一类是前端入门者,想理解一个真实网页从结构到样式的完整组织方式;另一类是物联网或嵌入式工程师,需要把传感器数据快速变成一张能看的大屏页面。沿着「布局 → 组件 → 数据 → 排错」的路径,下面会给出可以照抄的栅格结构、AQI 色阶变量、环形仪表与浓度条代码,并说明每个参数为什么这样设。

2. 页面骨架与栅格:搭建空气质量仪表盘的信息层级

2.1 用 CSS Grid 规划大屏三区块布局

空气质量展示页要回答的问题无非三个:当前空气质量怎么样(AQI 数值与等级)、哪项污染物超标(六项浓度明细)、过去几小时怎么变化(趋势)。这三块信息的重要程度不同,页面层级就应该区分开。常见做法是头部放站点名与更新时间,左侧放 AQI 环形仪表和大数字,右侧放六项污染物卡片,底部放趋势条。这样一个 HTML 骨架可以支撑起全部需求:

<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>空气质量实时展示</title> <link rel="stylesheet" href="css/aqi.css"> </head> <body> <main class="dashboard"> <header class="dash-header"> <h1>站点:高新区监测站</h1> <time class="update-time">更新:10:32</time> </header> <section class="dash-hero"> <!-- AQI 环形仪表与等级卡片 --> </section> <section class="dash-grid"> <!-- 六项污染物浓度卡片 --> </section> <section class="dash-trend"> <!-- 24 小时 AQI 迷你趋势条 --> </section> </main> </body> </html>

骨架里用main作为栅格容器,headersectiontime这些语义化标签保证了展示页在没有加载 CSS 时依然有清晰的文档结构。meta viewport这一行不要省,空气质量页面经常会被投到不同分辨率的屏幕上,没有它移动端会把页面缩放得很小。

CSS 栅格用grid-template-columns把横向空间分成左固定、右自适应两列:

:root { --gap: 16px; } .dashboard { display: grid; grid-template-columns: 280px 1fr; grid-template-rows: auto auto auto; gap: var(--gap); max-width: 1200px; margin: 0 auto; padding: var(--gap); } .dash-header { grid-column: 1 / -1; } .dash-hero { grid-column: 1; grid-row: 2; } .dash-grid { grid-column: 2; grid-row: 2; display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--gap); } .dash-trend { grid-column: 1 / -1; }

参数说明:280px 1fr把左侧 AQI 主卡片固定为 280px,右侧污染物网格占据剩余空间,适合 1024px 以上的屏幕;repeat(3, 1fr)让右侧网格变成三列,六项污染物自动排成两行三列。主题区域放在grid-row: 2,趋势条跨满整行。屏幕低于 768px 时,应该把grid-template-columns切成单列,让所有区块纵向堆叠:

@media (max-width: 768px) { .dashboard { grid-template-columns: 1fr; } .dash-hero, .dash-grid { grid-column: 1; grid-row: auto; } .dash-grid { grid-template-columns: repeat(2, 1fr); } }

这里有个容易忽略的点:grid-row: auto不是多余写法。栅格项目在单列下如果不重置行号,grid-row: 2的显式声明可能让 hero 区块与 header 重叠。显示声明auto可以强制项目回到文档流顺序。

2.2 AQI 色阶映射:把国标转成 CSS 变量

空气质量展示页的颜色不能随便定,业内通行的依据是 HJ 633-2012 环境空气质量指数技术规定。AQI 分六级,每一级对应一个主色。把这套标准落成 CSS 变量表,后续所有组件共享同一份颜色语义,就不会出现「卡片说良、进度条却是橙色」的颜色打架问题。

等级AQI 范围参考主色CSS 变量名
0-50#00E400--aqi-good
51-100#FFFF00--aqi-moderate
轻度污染101-150#FF7E00--aqi-light
中度污染151-200#FF0000--aqi-heavy
重度污染201-300#8F3F97--aqi-severe
严重污染301+#7E0023--aqi-hazard

:root里定义变量后,组件里通过var(--aqi-light)引用,切换主题时只需要改一处:

:root { --aqi-good: #00e400; --aqi-moderate: #ffff00; --aqi-light: #ff7e00; --aqi-heavy: #ff0000; --aqi-severe: #8f3f97; --aqi-hazard: #7e0023; --aqi-text-dark: #333333; --aqi-text-light: #ffffff; }

黄色#FFFF00属于亮色,在浅色卡片上配深色文字可读性更好;紫色和褐红色是暗色,配白色文字。所以后面的等级卡片在取文字色时不能统一用#fff,应该给亮色等级单独切到深色文字。这一步做好,整页的对比度问题就少了一半。

3. 纯 CSS 组件实现:浓度条、等级卡与环形仪表

3.1 AQI 等级卡片:状态色与文字可读性联动

等级卡片是展示页里信息密度最高的小组件:左上角是 AQI 大数字,下方是等级名称,右侧可以放一句简单的健康提示。纯 CSS 实现它的关键是让边框、数字颜色都跟随当前等级自动变化,而不是写死。

<article class="aqi-card" id="aqiCard"> <div class="aqi-value"> <span class="aqi-num" id="aqiNum">86</span> <span class="aqi-level" id="aqiLevel">良</span> </div> <p class="aqi-tip" id="aqiTip">敏感人群减少外出</p> </article>
.aqi-card { padding: 24px; border-radius: 16px; border: 2px solid var(--aqi-moderate); background: linear-gradient(145deg, color-mix(in srgb, var(--aqi-moderate) 12%, #ffffff) 0%, #ffffff 70%); transition: border-color 0.3s ease; } .aqi-num { font-size: 56px; font-weight: 700; line-height: 1.2; } .aqi-level { font-size: 18px; padding: 2px 12px; border-radius: 999px; color: var(--aqi-text-dark); background: var(--aqi-moderate); }

color-mix(in srgb, ...)是比rgba()更灵活的取色方式,它把等级主色与白色按比例混合,得到一张以等级色为基调的极浅背景。需要注意color-mix需要较新的浏览器版本,如果目标环境是老旧内核,退路是用rgba()手动写六个半透明背景色。border-radius: 999px用在等级标签上,让文字胶囊两侧变成半圆,比固定20px更能适配不同长度的文本。

这类卡片在源码里通常作为模板循环渲染,页面有多少个监测站点就复制多少个article.aqi-card。站点多时建议把渲染逻辑交给脚本,而不是在 HTML 里手工粘贴几十份结构,否则后期加一个字段会改到手软。

3.2 污染物浓度条:百分比宽度与溢出省略

六项污染物的浓度展示适合用横向条形图。条形图虽然用一个div就能画,但要注意两个细节:浓度值相对标准限值的比例超过 100% 时条要封顶,比例太小(比如低于 2%)时条要有一个最小可见宽度,否则视觉上像是数据缺失。

<div class="poll-item"> <div class="poll-head"> <span class="poll-name">PM2.5</span> <span class="poll-value">38 μg/m³</span> </div> <div class="poll-bar"> <div class="poll-fill" style="width: 38%;"></div> </div> <span class="poll-label">二级 · 良</span> </div>
.poll-bar { height: 10px; border-radius: 5px; background: #e9ecef; overflow: hidden; } .poll-fill { height: 100%; border-radius: 5px; min-width: 4px; background: linear-gradient(90deg, #00e400, #ffff00); transition: width 0.6s ease-out; }

min-width: 4px是面积小但浓度不为零时的兜底值。width由脚本按浓度 / 标准限值计算,但展示层不需要知道具体限值是 75 还是 35,它只消费脚本算好的百分比。这里有个细节:对颗粒物和气体使用同一套渐变,视觉上确实统一,但会误导读者以为它们用的是同一套限值。更严谨的做法是按照污染物类型定义两组渐变:颗粒物用暖色渐变,气态污染物用蓝色渐变,让颜色承载浓度高低之外的信息。

浓度值与标准限值的换算如果放在 CSS 里做不现实,attr()目前不支持复杂计算,所以百分比必须事先在脚本里算好。

3.3 环形仪表:不用图表库读出 AQI 数值

AQI 大数字旁边配一个环形仪表,能让人一眼判断当前污染程度。用conic-gradient画一个 270 度或 360 度的圆环,再把圆环中心挖空,视觉上就是一个仪表盘。完整实现需要两层div叠加:

<div class="gauge" id="gauge"> <div class="gauge-inner"> <span class="gauge-num" id="gaugeNum">86</span> </div> </div>
.gauge { --percent: 86%; width: 180px; height: 180px; border-radius: 50%; background: conic-gradient( var(--aqi-moderate) 0 var(--percent), #e9ecef var(--percent) 100% ); display: grid; place-items: center; } .gauge-inner { width: 140px; height: 140px; border-radius: 50%; background: #ffffff; display: grid; place-items: center; } .gauge-num { font-size: 40px; font-weight: 700; }

conic-gradient的百分比段用来表达 AQI 当前值在满量程(比如 300)中的位置。--percent用 CSS 变量传入,脚本更新数据时直接改这个变量即可,不需要重复刷新整个节点的背景。圆环内层的place-items: center让数字始终居中。这里有一个进阶可选项:把圆环缺口留在正下方,做成真正的仪表风格,做法是让渐变覆盖 270 度,再把外层div旋转 135 度。视觉上更接近汽车仪表,但旋转后的文本方向也会受影响,如果缺口上方不打算放文字,这个方案才划算。

4. 数据接入与动态渲染:JSON 驱动 CSS 变量

4.1 数据层设计:模拟接口与一次渲染

页面写完静态结构后,要接真实数据。最常见的做法不是让 HTML 里写死数值,而是把数据集中放在一个 JSON 对象里,渲染函数读 JSON 后回填 DOM。不依赖框架时,用模板字符串拼接并innerHTML赋值是通用实现:

const apiData = { aqi: 86, level: '良', tip: '敏感人群减少外出', pollutants: { pm25: { value: 38, percent: 38, level: '良' }, pm10: { value: 52, percent: 45, level: '良' }, o3: { value: 120, percent: 75, level: '轻度' }, no2: { value: 30, percent: 30, level: '优' }, so2: { value: 12, percent: 24, level: '优' }, co: { value: 0.8, percent: 8, level: '优' } } }; function renderAQI(data) { document.getElementById('aqiNum').textContent = data.aqi; document.getElementById('aqiLevel').textContent = data.level; document.getElementById('aqiTip').textContent = data.tip; const gauge = document.getElementById('gauge'); const maxAQI = 300; const percent = Math.min(100, (data.aqi / maxAQI) * 100); gauge.style.setProperty('--percent', percent + '%'); gauge.style.background = `conic-gradient( ${levelColor(data.level)} 0 ${percent}%, #e9ecef ${percent}% 100% )`; } function levelColor(level) { const map = { '优': 'var(--aqi-good)', '良': 'var(--aqi-moderate)', '轻度': 'var(--aqi-light)', '中度': 'var(--aqi-heavy)', '重度': 'var(--aqi-severe)', '严重': 'var(--aqi-hazard)' }; return map[level] || 'var(--aqi-moderate)'; } renderAQI(apiData);

Math.min(100, ...)的作用是防止 AQI 超过 300 时百分比溢出圆环。style.setProperty直接改写 CSS 变量,比逐个修改 background 字符串更干净,因为conic-gradient的色标由等级颜色确定,必须由脚本先查表再组合成整个字符串。数据不落在 DOM 属性上,而是通过变量传递,这样后续做主题切换时就有一条清晰的调用链:数据层 → 等级映射 → CSS 变量 → 组件颜色。

4.2 定时刷新与状态色联动

空气质量数据通常每小时更新一次,但你不可能要求用户每小时手动刷新页面。标准做法是前端定时拉取新 JSON。演示环境里可以直接用一个setInterval模拟数据变化:

function startPolling() { setInterval(() => { fetch('/api/aqi.json') .then(res => res.json()) .then(data => { renderAQI(data); renderPollutants(data.pollutants); updateLevelBadge(data.level); }) .catch(err => console.error('数据拉取失败', err)); }, 60 * 1000); }

60 * 1000表示一分钟请求一次。真实环境建议用 15 分钟或 1 小时,太频繁的轮询对后端没有价值。请求失败时不要清空页面上的旧数据,保留上次成功渲染的结果,在头部提示「数据更新时间较早」,避免大屏上一片空白。renderPollutants循环处理六项污染物,把每一项的百分比写进对应的poll-fill元素,同时更新数值文本。整个过程只改 DOM 的样式属性和文本,没有重建整棵节点树,性能开销很小。

4.3 鼠标移入事件与过渡动画的控制

展示页不只有静态展示,交互反馈也很关键。鼠标移入事件在 CSS 与 JavaScript 里有不同分工:纯视觉反馈(比如卡片浮起、边框变色)用:hover实现;需要联动其他元素(比如移入一个污染物标签、同时高亮另一处的数据卡片)则用脚本监听mouseenter/mouseleave

.poll-item:hover { transform: translateY(-4px); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08); } .poll-item { transition: transform 0.25s ease, box-shadow 0.25s ease; }

translateY(-4px)的幅度是刻意控制的:4px 位移在小卡片上能提供清晰的浮起感,又不至于像弹窗一样产生视觉跳动。transition时长 0.25s 是悬停反馈的舒适区间,短于 0.15s 会觉得生硬,长于 0.4s 会拖沓。脚本联动的场景通常是查看站点详情,例如:

document.querySelectorAll('.poll-item').forEach(item => { item.addEventListener('mouseenter', function () { const name = this.dataset.pollutant; document.querySelectorAll(`[data-related="${name}"]`).forEach( el => el.classList.add('is-highlight') ); }); });

mouseentermouseover的区别在于它不会冒泡,子元素进入时不会重复触发父级事件。在列表型组件里优先用mouseenter,可以减少大量无谓的事件回调。高亮样式类is-highlight只负责增加一个描边或放大透明度,真正的联动规则仍留在结构层。

5. 从能显示到有细节:排错、验证与三个进阶技巧

5.1 高频故障:变量传参、字体单位与渐变失效

第一类高频坑是 CSS 变量在行内传入时失效。有人习惯把--percent: 86%写在style属性里,但脚本更新时忘了加单位,86会被当成无单位数字,conic-gradient直接报错。赋值时统一拼上%,并养成分数值统一走变量的习惯。

第二类坑是字体单位。空气质量大屏常用超大数字,px固定在移动端会溢出卡片。建议大数字用clamp()动态缩放:font-size: clamp(40px, 8vw, 64px),小字用rem。这样页面从手机横屏切换到电视盒子时,层级不会散。

第三类坑是rgba叠加渐变时颜色发灰。当等级色是亮黄、亮绿时,rgba(255, 255, 0, 0.3)与白色叠加会得到一种脏黄色。换用color-mix(in srgb, var(--aqi-moderate) 12%, #fff)可以保住色相。浏览器不支持时,可读退路是直接用纯色浅背景。

5.2 本地验证:起服务与性能面板

双击打开 HTML 文件时,fetch会被同源策略拦截,所以本地调试不要直接双击文件。在项目目录跑一条命令起个静态服务:

cd aqi-dashboard python3 -m http.server 8080

浏览器访问http://localhost:8080。验证重点看 Chrome DevTools 的 Performance 面板:Performance 里录一段滚动与 hover 操作,观察有没有连续超过 50ms 的长任务。CSS 组件本身不会造成性能瓶颈,真正的问题是频繁改变几何属性(宽度、高度、间距)导致大量重排。浓度条动画只改widthtransform,前者会触发重排,卡片数量少时无感,超过几十张时改造成由scaleX驱动更划算。

5.3 三个进阶技巧:返回顶部、暗色模式与打印样式

页面高度超过一屏后,放一个返回顶部按钮是性价比最高的小功能。不需要 JavaScript 计算滚动位置,纯 CSS 的scroll-behavior配合锚点即可:

<a class="back-top" href="#top">回到顶部</a>
html { scroll-behavior: smooth; } .back-top { position: fixed; right: 24px; bottom: 32px; }

scroll-behavior: smooth让点击锚点时滚动过程平滑,原生实现无抖动。这个方案没有复杂的节流滚动逻辑,也不涉及计算 scrollTop,适合展示型页面。

暗色模式方面,既然全页颜色都收敛到了 CSS 变量,切换主题只需要在根节点加一个切变量值的入口:

@media (prefers-color-scheme: dark) { :root { --card-bg: #1f2430; --poll-bar-bg: #2a2f3a; --aqi-text-dark: #f0f0f0; } }

prefers-color-scheme是操作系统级媒体查询,用户系统切了暗色,页面自动跟随。需要手动切换时,在<html>上加>@media print { .dashboard { max-width: none; background: #fff; color: #000; } .aqi-card, .poll-item { box-shadow: none; border: 1px solid #ccc; break-inside: avoid; } }

break-inside: avoid保证一张污染物卡片不会被打印成跨页截断。这三个技巧加在一起,展示页在投屏、打印、夜间值班三种场景下都能保持基本可用,这套由 CSS 变量统一管理的结构,也让后续维护成本明显低于直接改死样式。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询