仅用 CSS 实现元素圆形排列的方法

说在前面,别怪我没提醒你。在这个卷生卷死的前端圈,用纯CSS把一堆元素死死摁在环形布局上,其实早就分化出了两条截然不同的路子。

一条是稳如老狗的"工业级"方案,全浏览器通吃,我每天都在靠它混饭吃;

另一条则是刚出炉不久的"实验性"黑魔法,代码干净得让人直呼内行,可惜有的浏览器就是死活不买账。

这两种环形布局手段,鄙人皆有涉猎。可是呢,它们在我心里的定位,却有着天壤之别。

今天,我就大发慈悲,把这层窗户纸给你彻底捅破。

套路一:可以直接拉去摇钱的"工业级"CSS大法

谈及能够在生产环境里无脑上的环形布局,这套经典方案简直就是我的救命稻草。不论是需要制作花里胡哨的按钮、精致的图标,还是团队大屏里的环状头像,这套逻辑永远是我的第一顺位选择。

之所以这么偏爱它,原因无他:极度靠谱。并且,这种被广泛接纳的环形布局逻辑,其实傻白甜得可爱。

到底有多简单?我一般是这样给自己洗脑的:

  • 先把所有元素统统塞到正中间。

  • 接着,让每个子元素按比例稍微转个身。

  • 然后,一脚把它踹离中心点(利用位移)。

  • 最后,为了不让里面的文字可怜巴巴地倒立着,再把它给反向转回来。

这套把戏,说破天也就这么点东西。既然CSS本就精通旋转之道,我们不过是顺水推舟,将这种力量发挥到极致罢了。

基础的HTML长这样:

go 复制代码
<div class="circle">
  <div style="--i:0">A</div>
  <div style="--i:1">B</div>
  <div style="--i:2">C</div>
  <div style="--i:3">D</div>
  <div style="--i:4">E</div>
  <div style="--i:5">F</div>
</div>

凭借CSS变量 --i,每一个元素都被赋予了一个专属序号。正是这个不起眼的数字,残忍地决定了它在环形布局里的最终宿命。

真正在背后出大力的CSS代码如下:

go 复制代码
:root {
  --total: 6; /* 元素总数 */
  --radius: 150px; /* 圆的半径 */
}

/* 环形容器 */
.circle {
  position: relative;
  width: calc(var(--radius) * 2);
  height: calc(var(--radius) * 2);
  margin: 3rem auto;
}

/* 环形元素 */
.circle > div {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 60px;
  height: 60px;
  margin: -30px;
  border-radius: 50%;
  background: #6c5ce7;
  color: white;
  display: grid;
  place-items: center;

  --angle: calc(360deg / var(--total) * var(--i));

  transform:
    rotate(var(--angle))
    translateX(var(--radius))
    rotate(calc(-1 * var(--angle)));
}

清清爽爽,半句JavaScript的废话都没有。间距、角度、定位,统统被CSS一手包办。一旦你悟透了这个套路,天下所有的环形布局你都可以横着走。

实战演练

实不相瞒,这种环形布局,我早就用它在实际业务里大杀四方了。闭上眼睛想想:那些手机App里一按就弹出的"+"号菜单,或是悬浮在页面角落的快捷操作面板。

go 复制代码
<div class="circle menu">
  <button style="--i:0">编辑</button>
  <button style="--i:1">分享</button>
  <button style="--i:2">保存</button>
  <button style="--i:3">删除</button>
</div>
go 复制代码
.menu {
  --total: 4;
  --radius: 120px;
}

.menu button {
  border: none;
  background: #00b894;
  color: white;
  cursor: pointer;
}

用户点得爽,看着也高级,更关键的是它绝对不会崩。不仅仅是菜单,音乐播放器的周边控件、团队看板的环状头像,我全是用它扛下来的。每一次,这种环形布局都稳稳当当,从不掉链子。

适配屏幕?一行代码教做人

最让我爽到头皮发麻的,是它的响应式处理机制。为了让整个环形布局能大能小,游刃有余,我只需要轻描淡写地改动一行代码:

go 复制代码
.circle {
  --radius: 30vw;
}

搞定。没用什么劳什子的媒体查询,也不需要硬生生地去设什么断点。

至于这套方案是否被所有浏览器接纳?答案是肯定的。毕竟它利用的不过是 transformrotate()calc() 和 CSS变量这些老面孔。Chrome、Firefox、Safari、Edge,这些主流大佬统统绿灯放行。

套路二:让人又爱又恨的"实验性"CSS黑科技

接下来,我要给你看点刺激的了。提前声明:这段环形布局代码,我是坚决不敢直接扔到生产环境里去的。即便如此,这玩意儿绝对能让你看湿了眼眶。

在这个方案里,一种名为 CSS Motion Path(运动路径) 的新锐技术被引入了进来。我们不再去死磕什么恶心的角度计算,而是像霸道总裁一样直接命令浏览器:"看到这个圆了吗?把这些亲兄弟给我均匀地摆上去!"

Motion Path 的惊艳代码:

go 复制代码
.container {
  display: inline-grid;
}

.container > div {
  width: 150px;
  aspect-ratio: 1;
  border-radius: 50%;
  background: purple;

  offset-path: circle(180px);
  offset-distance: calc(
    100% * sibling-index() / sibling-count()
  );

  transition: 1s;
}

发现盲点了没?没有CSS变量,没有伪类,不需要JS帮忙,更没有那些让人头秃的角度数学题。CSS自己就把活儿全干了,聪明得让人心疼。

为什么这套方法让人如此上头?

原因无他,这种环形布局的处理方式,完全颠覆了以往的认知。代码极其优雅,动画丝滑得要命。更重要的是,你的大脑被彻底释放了------你再也不用被那些复杂的旋转逻辑折磨得死去活来。显然,这才是CSS未来该有的狂傲姿态。

然而,现实总是喜欢在你最兴奋的时候泼冷水。

这套绝美的技术,偏偏重度依赖于几个还处于实验阶段的属性:offset-pathsibling-index()sibling-count()。测试结果相当残酷:Chrome和Edge?完美运行。

Safari?勉勉强强。

Firefox?直接半身不遂,得靠手动开启隐藏标识才能强行续命。正因如此,这种实验性的环形布局,我目前只能把它死死锁在实验室里。

如何抉择?成年人不做选择题

关于这两种环形布局的取舍,我的规矩向来简单粗暴:真正要交差、拿去赚钱的项目,老老实实用第一种 transform 经典方案;自己偷偷搞的实验和Demo,果断上 Motion Path 爽一把。借由这种方式,我既保住了饭碗,又没被时代抛弃。

总而言之,环形布局从来都不只是个看着炫酷的杂耍把戏。在导航、菜单和视觉界面里,它是实打实的交互杀器。

基于 transform 的环形布局早已瓜熟蒂落,我也是高频使用。反之,Motion Path 虽然干净利落,却还没拿到属于它的通关文牒。所以我把它们都塞进工具箱,一个用来赚钱,一个用来拓宽眼界。

如果你今天就要把项目发出去,听我的,用 transform,先跑通再说。等到周末做个人项目时,再去试试 Motion Path,盯着浏览器的支持率。等到哪天绿灯全亮了,你自然知道该怎么将旧代码彻底替换。

能用现在的技术把活干得漂亮,同时又死死盯着明天的风向。坦白说,这才是咱们做开发最爽的瞬间啊。感谢你的阅读。

全栈AI·探索:涵盖动效、React Hooks、Vue 技巧、LLM 应用、Python 脚本等专栏,案例驱动实战学习,点击二维码了解更多详情。

最后:

CSS终极指南

Vue 设计模式实战指南

20个前端开发者必备的响应式布局

深入React:从基础到最佳实践完整攻略

python 技巧精讲

React Hook 深入浅出

CSS技巧与案例详解

vue2与vue3技巧合集

相关推荐
JosieBook2 小时前
【Vue】15 Vue技术——Vue计算属性简写:提升代码简洁性的高效实践
前端·javascript·vue.js
weixin199701080162 小时前
Lazada商品详情页前端性能优化实战
前端·性能优化
星火开发设计3 小时前
异常规范与自定义异常类的设计
java·开发语言·前端·c++
CappuccinoRose3 小时前
CSS 语法学习文档(十一)
前端·css·学习·表单控件
海兰4 小时前
Elastic Stack 9.3.0 日志探索
java·服务器·前端
输出输入5 小时前
Java Swing和JavaFX用哪个好
java·前端
铁甲前沿5 小时前
一个月玩转MQTT(篇五:开发自己的MQTT WEB页面)
前端·mqtt·asp.net·mqtt web开发
~央千澈~5 小时前
抖音弹幕游戏开发之第7集:识别不同类型的消息·优雅草云桧·卓伊凡
java·服务器·前端
拾荒李5 小时前
在 Vue 项目里“无痛”使用 React 组件:以 Veaury + Vite 为例
前端·vue.js·react.js