使radial-gradient() 跨越两个元素

Posted

技术标签:

【中文标题】使radial-gradient() 跨越两个元素【英文标题】:Make radial-gradient() span two elements 【发布时间】:2019-10-18 08:52:46 【问题描述】:

我有一个由两个半圆形 div 组成的圆圈。我想使用 background:radial-gradient() 使圆看起来是球形的。如何在不使用一个圆形 div 覆盖两个半圆形 div 的情况下做到这一点?

[有两个半圆形 div 的原因是因为圆形分成两部分的过渡。不想用单个 div 覆盖的原因是类似的]

.top-semi-circle, .bottom-semi-circle 
  width: 10em;
  height: 5em;
  background: radial-gradient(circle at 100px 100px, red, #000);

.top-semi-circle 
  border-radius: 10em 10em 0 0;

.bottom-semi-circle 
  border-radius: 0 0 10em 10em;

.full-circle 
  width: 10em;
  height: 10em;
  border-radius: 10em;
  background: radial-gradient(circle at 100px 100px, red, #000);
Make this:
<div class="top-semi-circle"></div>
<div class="bottom-semi-circle"></div>
Look like this:
<div class="full-circle"></div>

【问题讨论】:

更新了我的答案,添加了更多不需要担心渐变位置的方法:***.com/a/58447712/8620333 【参考方案1】:

调整第二个渐变位置,最重要的是为两个渐变指定一个半径,以避免产生一个相同的自动值,因为我们将有不同的位置并且大小的默认值是@ 987654322@

.top-semi-circle, .bottom-semi-circle 
  width: 10em;
  height: 5em;

.top-semi-circle 
  border-radius: 10em 10em 0 0;
  background: radial-gradient(circle 10em at 100px 100px, red, #000);

.bottom-semi-circle 
  border-radius: 0 0 10em 10em;
  background: radial-gradient(circle 10em at 100px 20px, red, #000);


.bottom-semi-circle:hover 
  transform:translateY(10px);
<div class="top-semi-circle"></div>
<div class="bottom-semi-circle"></div>

径向渐变语法是:

radial-gradient() = radial-gradient(
  [ <ending-shape> || <size> ]? [ at <position> ]? ,
  <color-stop-list>

&lt;size&gt;

确定渐变结束形状的大小。如果省略,则默认为 farthest-cornerref

如果您想保持渐变的定义相同,您也可以使用background-size/background-position。只需给出与整体形状相同的尺寸(上半部分 + 下半部分)。

.top-semi-circle, .bottom-semi-circle 
  width: 10em;
  height: 5em;
  background-image: radial-gradient(circle at 100px 100px, red, #000);
  background-size:10em 10em;

.top-semi-circle 
  border-radius: 10em 10em 0 0;
  background-position:top;

.bottom-semi-circle 
  border-radius: 0 0 10em 10em;
  background-position:bottom;


.bottom-semi-circle:hover 
  transform:translateY(10px);
<div class="top-semi-circle"></div>
<div class="bottom-semi-circle"></div>

另一个想法是考虑与clip-path重叠:

.top-semi-circle, .bottom-semi-circle 
  width: 10em;
  height: 10em;
  border-radius: 10em;
  background: radial-gradient(circle at 100px 100px, red, #000);

.top-semi-circle 
  clip-path:polygon(0 0,100% 0,100% 50%,0 50%);

.bottom-semi-circle 
  margin-top:-10em;
  clip-path:polygon(0 100%,100% 100%,100% 50%,0 50%);

.bottom-semi-circle:hover 
  transform:translateY(10px);
<div class="top-semi-circle"></div>
<div class="bottom-semi-circle"></div>

同样的逻辑使用mask:

.top-semi-circle, .bottom-semi-circle 
  width: 10em;
  height: 10em;
  border-radius: 10em;
  background: radial-gradient(circle at 100px 100px, red, #000);

.top-semi-circle 
  -webkit-mask:linear-gradient(to bottom,white 50%,transparent 0);
  mask:linear-gradient(to bottom,white 50%,transparent 0);

.bottom-semi-circle 
  margin-top:-10em;
  -webkit-mask:linear-gradient(to top,white 50%,transparent 0);
  mask:linear-gradient(to top,white 50%,transparent 0);

.bottom-semi-circle:hover 
  transform:translateY(10px);
<div class="top-semi-circle"></div>
<div class="bottom-semi-circle"></div>

【讨论】:

【参考方案2】:

这可以使用 calc() 将径向定位在底部半圆的第二个位置。 我使用的是 calc(100px - 5em),因为 100px 是上半部分渐变中心的偏移量,而 5em 是一个半圆的高度。

编辑:我还必须指定渐变的大小以使它们匹配,默认情况下大小不同,可能是因为到中心和各个边的距离不同。

.top-semi-circle 
  width: 10em;
  height: 5em;
  background: radial-gradient(10em at 100px 100px, red, #000);

.bottom-semi-circle 
width: 10em;
  height: 5em;
  background: radial-gradient(10em at 100px calc(100px - 5em), red, #000);

.top-semi-circle 
  border-radius: 10em 10em 0 0;

.bottom-semi-circle 
  border-radius: 0 0 10em 10em;

.full-circle 
  width: 10em;
  height: 10em;
  border-radius: 10em;
  background: radial-gradient(circle at 100px 100px, red, #000);
Make this:
<div class="top-semi-circle"></div>
<div class="bottom-semi-circle"></div>
Look like this:
<div class="full-circle"></div>

【讨论】:

【参考方案3】:

使用overflow hidden 和pseudo elements

*box-sizing: border-box
[class$=circle] 
  width: 10em;
  height: 10em; 
  overflow: hidden;
  position: relative; 
  display: block;
  will-change: transform;
  transition: transform .2s ease

[class$=circle]:before 
  content: "";
  position: absolute;
  left: 0;
  width: 10em;
  height: 10em;
  border-radius: 50%;
  background: radial-gradient(circle at 100px 100px, red, #000);

[class^=top]:before  
  top: 50%;

[class^=bottom]:before  
  bottom: 50%;

figure
  width: 10rem;
  height: 10rem;

figure:hover [class^=top] 
  transform: translate3d(0, -10px, 0)

figure:hover [class^=bottom] 
  transform: translate3d(0, 10px, 0)
<figure>
  <div class="top-semi-circle"></div>
  <div class="bottom-semi-circle"></div>
</figure>

【讨论】:

以上是关于使radial-gradient() 跨越两个元素的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 GridPane JavaFX 使按钮跨越多个列/行?

为啥部分无效跨越整个视图?

CSS3 radial-gradient径向渐变语法

使 HTML 表格的列跨越所有列

如何使组件跨越 GridBagLayout 中的多个单元格

以编程方式使 dojo 数据网格单元跨越多列