在纯CSS场景下实现椭圆内精准定位的响应式点阵图案,核心是利用CSS的几何属性和相对单位,结合伪元素和定位规则完成点阵的排布,不需要任何JavaScript参与计算。

实现基础:椭圆容器搭建
首先需要创建一个椭圆形状的容器,使用border-radius属性设置椭圆的纵横半径,同时用相对单位保证容器本身的响应式特性。
/* 椭圆容器基础样式 */
.ellipse-container {
/* 宽度使用视口宽度的50%,最小300px,最大800px,实现响应式 */
width: min(800px, max(300px, 50vw));
/* 高度为宽度的60%,形成椭圆比例 */
height: 60%;
/* 水平垂直居中 */
position: relative;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
/* 设置椭圆形状,50% 60% 分别对应水平、垂直方向的半径 */
border-radius: 50% 60%;
/* 给容器加个浅色背景方便观察 */
background-color: #f0f0f0;
/* 溢出隐藏,避免点阵超出椭圆范围 */
overflow: hidden;
}
点阵定位的核心逻辑
点阵的精准定位需要结合极坐标的思路,通过calc()函数计算每个点相对于椭圆中心的位置,同时用--自定义属性存储动态参数,方便统一调整。
自定义属性定义
在容器上定义椭圆的半轴长度、点的数量、点的大小等参数,后续所有计算都基于这些属性,修改时只需要调整一处。
.ellipse-container {
/* 椭圆水平半轴长度,为容器宽度的一半 */
--a: calc(var(--container-width, 50vw) / 2);
/* 椭圆垂直半轴长度,为容器高度的一半 */
--b: calc(var(--container-height, 30vh) / 2);
/* 水平方向点的数量 */
--cols: 10;
/* 垂直方向点的数量 */
--rows: 8;
/* 单个点的直径 */
--dot-size: 8px;
/* 点的颜色 */
--dot-color: #333;
}
点阵元素生成与定位
使用伪元素::before和::after配合CSS网格或者循环生成点阵,这里采用网格布局简化排布,每个网格项对应一个点,通过绝对定位调整到椭圆内的对应位置。
.ellipse-container {
display: grid;
/* 按照定义的行列数生成网格 */
grid-template-columns: repeat(var(--cols), 1fr);
grid-template-rows: repeat(var(--rows), 1fr);
/* 网格占满整个容器 */
width: 100%;
height: 100%;
position: relative;
}
/* 每个网格项作为点的容器 */
.ellipse-container > .dot-item {
position: relative;
/* 让点相对于网格项居中 */
display: flex;
justify-content: center;
align-items: center;
}
/* 点本身的样式 */
.ellipse-container > .dot-item::before {
content: '';
width: var(--dot-size);
height: var(--dot-size);
border-radius: 50%;
background-color: var(--dot-color);
/* 绝对定位,基于椭圆中心计算偏移 */
position: absolute;
/* 计算水平偏移:网格项的水平位置映射到椭圆的x坐标 */
left: calc(50% + (var(--col-index) - (var(--cols) - 1) / 2) * (100% / (var(--cols) - 1)) * var(--a) / var(--a));
/* 计算垂直偏移:网格项的垂直位置映射到椭圆的y坐标 */
top: calc(50% + (var(--row-index) - (var(--rows) - 1) / 2) * (100% / (var(--rows) - 1)) * var(--b) / var(--b));
transform: translate(-50%, -50%);
}
响应式适配处理
响应式的关键在于所有尺寸相关的属性都使用相对单位,并且通过媒体查询调整点阵的行列数和点的尺寸,保证不同屏幕下点阵分布均匀且不会超出椭圆范围。
/* 小屏幕适配 */
@media (max-width: 768px) {
.ellipse-container {
--cols: 6;
--rows: 5;
--dot-size: 6px;
/* 小屏幕下容器宽度为视口宽度的80% */
width: min(500px, 80vw);
}
}
/* 大屏幕适配 */
@media (min-width: 1200px) {
.ellipse-container {
--cols: 14;
--rows: 10;
--dot-size: 10px;
}
}
完整可运行示例
以下是整合了所有逻辑的完整HTML和CSS代码,直接复制到文件中即可运行查看效果。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>纯CSS椭圆点阵示例</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background-color: #fff;
}
.ellipse-container {
--cols: 10;
--rows: 8;
--dot-size: 8px;
--dot-color: #2c3e50;
width: min(800px, max(300px, 50vw));
height: 60vh;
border-radius: 50% 60%;
background-color: #ecf0f1;
overflow: hidden;
position: relative;
display: grid;
grid-template-columns: repeat(var(--cols), 1fr);
grid-template-rows: repeat(var(--rows), 1fr);
}
.dot-item {
position: relative;
}
.dot-item::before {
content: '';
width: var(--dot-size);
height: var(--dot-size);
border-radius: 50%;
background-color: var(--dot-color);
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
@media (max-width: 768px) {
.ellipse-container {
--cols: 6;
--rows: 5;
--dot-size: 6px;
width: min(500px, 80vw);
}
}
@media (min-width: 1200px) {
.ellipse-container {
--cols: 14;
--rows: 10;
--dot-size: 10px;
}
}
</style>
</head>
<body>
<div class="ellipse-container">
<!-- 生成对应数量的dot-item,这里用JS生成仅为了方便演示,实际纯CSS可以用循环预处理器生成 -->
<script>
const container = document.querySelector('.ellipse-container');
const cols = parseInt(getComputedStyle(container).getPropertyValue('--cols'));
const rows = parseInt(getComputedStyle(container).getPropertyValue('--rows'));
for (let i = 0; i < cols * rows; i++) {
const dot = document.createElement('div');
dot.className = 'dot-item';
container.appendChild(dot);
}
</script>
</div>
</body>
</html>
注意事项
- 椭圆容器的
border-radius值需要根据实际宽高比例调整,保证呈现正确的椭圆形状 - 点阵的行列数不要设置过大,避免生成过多DOM元素影响性能
- 如果不需要动态生成DOM,可以使用Sass、Less等预处理器循环生成
dot-item的样式,实现完全无JS的纯CSS方案 - 自定义属性的兼容性需要注意,如果需要支持老旧浏览器,可以将自定义属性替换为具体的固定值