纯 CSS 的太阳系





5.00/5 (15投票s)
用纯 CSS 制作的太阳系网页
引言
这个项目没有实际用途,仅仅是我尝试使用 CSS 玩耍,学习不同 CSS 技巧的尝试。我不是网页设计师,也只接触过几次 CSS——换句话说,我对 CSS 是个彻头彻尾的新手,所以请您记住这一点。
话虽如此——正如标题所示——这是一个纯 CSS 的太阳系模型,包含太阳、行星,模拟了自转、行星倾斜、纹理等。也许可以做得更好,但正如我所说,我是一个新手,我认为这是一个不错的工作。
大小、距离和倾斜度都是近似值,并不代表太阳系的真实外观。我试图保持距离的比例,但为了能够让页面正常显示,我在一定程度上使用了指数比例。行星的大小也是如此——当然,除了太阳,它要大得多。我从 Google 和 Wikipedia 获取了信息,但数据也可能存在一些错误,所以请随时指出。此外,我也乐于接受任何关于如何改进此项目或添加新功能的建议。
重要提示:我使用的纹理和背景图片是在互联网上随意找到的,这意味着我并不拥有这些图片的版权,也无法控制它们的 URL。换句话说,如果图片消失或 URL 失效,页面可能会最终失效,届时可以通过代码中的其他 URL 轻松替换。
背景
我一直很钦佩那些仅用纯 CSS 就能创造奇迹的 CSS 艺术家,他们能够克服 CSS 的简单性和诸多限制。所以,我也想自己尝试一下。我不会称之为艺术品,但它无疑是对 CSS 功能的一次很好的介绍。
Using the Code
HTML 部分
HTML 代码基本是最小化的,因为想法是大部分或全部的魔术都通过 CSS 来实现。
每个行星(加上太阳)都表示为一个 span
元素,以 id
作为名称,并带有 class=“planet“
。纹理表示为嵌入式 div
元素,class=“texture“
。在每个 span
旁边还有一个 div
元素,class=“text“
,其中包含一些关于行星的基本信息;这些 text 类元素也具有与 span
元素相同的 id
——它们通过 id 和类名来引用。
此外,土星还有一个额外的 div
,用于表示土星环。
<body>
<span class="planet" id="sun"><div class="texture"></div></span><div class="text" id="sun">
Sun<br>Diameter: 1,392,700 km<br>Rotation cycle: 27 days</div>
<span class="planet" id="mercury"><div class="texture"></div></span>
<div class="text" id="mercury">Mercury<br>Diameter: 4,879 km<br>
Rotation cycle: 59 days<br>Distance from Sun: 67,062,000 km</div>
<span class="planet" id="venus"><div class="texture"></div></span>
<div class="text" id="venus">Venus<br>Diameter: 12,104 km<br>
Rotation cycle: 243 days<br>Distance from Sun: 108,000,000 km</div>
<span class="planet" id="earth"><div class="texture"></div></span>
<div class="text" id="earth">Earth<br>Diameter: 12,742 km<br>
Rotation cycle: 24 hours<br>Distance from Sun: 147,120,000 km</div>
<span class="planet" id="mars"><div class="texture"></div></span>
<div class="text" id="mars">Mars<br>Diameter: 6,779 km<br>
Rotation cycle: 25 hours<br>Distance from Sun: 226,028,000 km</div>
<span class="planet" id="jupiter"><div class="texture"></div></span>
<div class="text" id="jupiter">Jupiter<br>Diameter: 139,820 km<br>
Rotation cycle: 10 hours<br>Distance from Sun: 763,000,000 km</div>
<span class="planet" id="saturn"><div class="texture"></div></span>
<div class="ring" id="saturn"></div><div class="text" id="saturn">Saturn<br>
Diameter: 116,460 km<br>Rotation cycle: 11 hours<br>
Distance from Sun: 1,4914,000,000 km</div>
<span class="planet" id="uranus"><div class="texture"></div></span>
<div class="text" id="uranus">Uranus<br>Diameter: 50,724 km<br>
Rotation cycle: 17 hours<br>Distance from Sun: 2,957,700,000 km</div>
<span class="planet" id="neptune"><div class="texture"></div></span>
<div class="text" id="neptune">Neptune<br>Diameter: 49,244 km<br>
Rotation cycle: 16 hours<br>Distance from Sun: 4,476,000,000 km</div>
</body>
CSS 部分
全局变量
所有行星(和太阳)的大小、距离、自转速度和倾斜度都在 :root
伪类中定义,它代表 HTML 文档,主要用于定义全局可见的变量。
:root {
/*sizes*/
--size-sun:485px;
--size-earth:21px;
--size-jupiter:72px;
--size-neptune:51px;
--size-mercury:9px;
--size-venus:21px;
--size-mars:11px;
--size-saturn:69px;
--size-uranus:51px;
/*distances*/
--distance-mercury:525px;
--distance-venus:555px;
--distance-earth:585px;
--distance-mars:635px;
--distance-jupiter:1005px;
--distance-saturn:1435px;
--distance-uranus:2405px;
--distance-neptune:3505px;
/*rotations*/
--rotation-sun: 600s;
--rotation-earth:24s;
--rotation-jupiter:10s;
--rotation-neptune:16s;
--rotation-mercury:1404s;
--rotation-venus:2808s;
--rotation-mars:24s;
--rotation-saturn:11s;
--rotation-uranus:17s;
/*tilts*/
--tilt-sun: -0.1265364;
--tilt-earth: -0.40910518;
--tilt-jupiter: -0.05462881;
--tilt-neptune: -0.49427724;
--tilt-mercury: -0.0005235988;
--tilt-venus: -0.04607669;
--tilt-mars: -0.43964844;
--tilt-saturn: -0.46652651;
--tilt-uranus: -1.4351842;
}
这样做是为了在必要时可以更方便地进行更改。
数据来自互联网上的各种来源——距离和大小是基于指数比例的粗略近似值;倾斜度以弧度定义。
形状、大小和位置
所有元素的(类)位置都定义为 absolute
,这意味着它们相对于其最近的祖先进行定位。它们从顶部定位 50%,并向上偏移自身大小的 50%,以确保它们在垂直方向上居中。border-radius
设置为 50% 以表示圆形。溢出被隐藏,以确保纹理仅在圆形(它们的 span
祖先)内可见。
.planet {
border-radius: 50%;
}
.planet, .text, .ring {
position: absolute;
top: 50%;
margin: auto;
overflow: hidden;
transform: translateY(-50%);
}
阴影效果
每个行星都在与太阳相对的一侧设置了阴影。为了添加阴影,我们在每个 span
上使用了 :after
伪元素。
再次,位置是 absolute
。我们使用 top
/bottom
/left
/right
距离为 0,以确保阴影从祖先的边框开始。border-radius
再次设置为 50% 以确保圆形外观。
这里最重要的部分是 box-shadow
属性
box-shadow: none|h-offset v-offset blur spread color |inset|initial|inherit;
h-offset
是阴影的水平偏移量,在这种情况下我们需要它是负数,以便将阴影放在内部。我为此目的使用了行星大小的 20%。
v-offset
(垂直偏移量)是不需要的,因此等于 0
。
blur
标记阴影的模糊程度,数字越高,模糊程度越高。我对此进行了反复试验,发现 span
大小的一半最适合。
spread
标记阴影的大小。我也尝试了几种不同的值,最终确定 span
大小的 1/10 最适合。
我们使用的 color
自然是黑色 (#000)。inset
属性使阴影在内部而不是外部。
box-shadow
在太阳上稍有不同,因为这里的意图只是制造 3D 效果。因此,我使用了一种四周都有的、稍窄的阴影。
box-shadow: 0 0 calc(var(--size-sun) / 5) 10px #000 inset;
此外,我在太阳 span
元素周围使用了一个额外的阴影,用于制造太阳的光辉效果。
box-shadow:
0 0 60px 30px #ffffff, /* inner white */
0 0 60px 30px #ff8c00, /* middle orange */
0 0 60px 30px #ffff00; /* outer yellow */
原理相同,只是这里结合了多个阴影,产生了渐变效果。
大小和距离(行星的水平定位)
大小是通过设置 span
元素的 height
和 width
为其相应的“size”变量来实现的,水平位置是通过将所有 span
元素(行星)水平平移“distance”变量(该变量已包含太阳的直径)来实现的。
#mercury.planet {
height: var(--size-mercury);
width: var(--size-mercury);
transform: translate(var(--distance-mercury), -50%);
}
transform
的 -50% 部分用于实现垂直居中位置。
纹理 - 旋转和倾斜效果
为了实现旋转效果,使用了纹理元素的无限重复线性平移——动画的最终位置定义为唯一的关键帧。
.texture {
width: 400%;
height: 100%;
}
@keyframes spin {
to {
background-position: -200% 0;
}
}
#mercury .texture {
background: url(https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/
e0763947-6f42-4d09-944f-c2d6f41c415b/dcaig77-18800e1e-24aa-43e5-9dd0-3dff9bcf8d0c.jpg?
token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOiIsImlzcyI6InV
ybjphcHA6Iiwib2JqIjpbW3sicGF0aCI6IlwvZlwvZTA3NjM5NDctNmY0Mi00ZDA5LTk0NGYtYzJkN
mY0MWM0MTViXC9kY2FpZzc3LTE4ODAwZTFlLTI0YWEtNDNlNS05ZGQwLTNkZmY5YmNmOGQwYy5qcGc
ifV1dLCJhdWQiOlsidXJuOnNlcnZpY2U6ZmlsZS5kb3dubG9hZCJdfQ.vigtUwmhB5u_KrjxZcgE04
UH7OoC16HyLTD5pulA4OA);
background-size: auto 100%;
animation: spin var(--rotation-mercury) linear infinite;
transform: rotateZ(calc(var(--tilt-mercury) * 1rad));
transform-origin: calc(var(--size-mercury) / 2) calc(var(--size-mercury) / 2);
}
(背景)纹理向左平移;使用 400% 的宽度来确保在平移过程中我们不会“用完”纹理(我们将平移设置为 200%,这是它的一半);linear
关键字确保关键帧之间平滑的线性过渡,infinite
关键字意味着动画不断重复。
为了实现倾斜效果,我们使用 rotateZ
变换,并使用适当的全局变量;transform-origin
属性确保旋转中心与 span
(行星)的中心匹配。
关注点
土星环
土星环的定位方式与所有行星相同。为了使其看起来呈椭圆形,我将 width
乘以了 2.5
。我们使用额外的平移来精确地定位它,以产生期望的效果。(注意,我也使用了与行星本身相同的 rotateZ
。)
棘手的部分是让它看起来像一个围绕行星的环——为此,我为背景使用了 radial-gradient
——内 50% 完全透明,允许下方的土星 span
可见;其余部分为白色——从而代表了环。
#saturn.ring {
height: calc(var(--size-saturn));
width: calc(var(--size-saturn) * 2.5);
transform: translate(calc(var(--distance-saturn) - var(--size-saturn) * 0.78), -60%)
rotateZ(calc(var(--tilt-saturn) * 1rad));
background: radial-gradient(transparent 50%, white);
border-radius: 50%;
}
历史
- 2021 年 1 月 2 日:初始版本