Как создать изогнутый датчик с линейным градиентом в качестве фона?

#html #css #border #linear-gradients

#HTML #css #граница #линейные градиенты

Вопрос:

Я хочу создать адаптивную калибровку 0-100% с чистым css, с градиентом цвета от зеленого до красного. Я нашел несколько примеров, но ни в одном из них не смог заставить градиент работать правильно. После некоторого тестирования мне удалось заставить его работать. По сути, это фоновый div с линейным градиентным фоном и белым div на переднем плане с полупрозрачными границами, использующими border-radius, чтобы сделать их круглыми. Когда я поворачиваю div переднего плана, он показывает или скрывает части div градиентного фона.

Но у меня есть этот визуальный сбой, который я не знаю, как исправить:

CSS датчик с градиентом

Белые границы div переднего плана не полностью скрывают div градиента.

Это мой тестовый код (он может содержать ненужные правила css из всех предыдущих тестов, которые я проводил):

https://jsfiddle.net/fLtzrg3w/

HTML:

   <div class="c">
    <div class="go">
      <div class="g"></div>
      <div class="gbg"></div>
    </div>
  </div>
  

CSS:

 .c{
  position: relative;
  float:left;
  text-align: center;
  width: 50%;
  padding: 25% 5px 0 5px;
  height: 1rem;
  overflow:hidden;
}

.go{
  position: relative;
  width: 100%;
  overflow: hidden;
  padding-top:100%;
  margin-top: -50%;
}

.g{
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  border-radius: 50%;
  box-sizing: border-box;
  border: 40px solid transparent;
  border-bottom-color: #fff;
  border-right-color: #fff;
  transform: rotate(20deg);
  background: white;
  background-clip: padding-box;
  z-index: 2;
}

.gbg{
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  border-radius: 50%;
  box-sizing: border-box;
  background: linear-gradient(to right, green 0%, yellow 50%, red 100%);
  z-index: 1;
}
  

Как я могу сделать так, чтобы белый div полностью закрывал фоновый градиент div?

Комментарии:

1. Это может помочь: codepen.io/xgh/pen/ExaXgbb

2. @Mech Я думаю, что видел это, но после преобразования его из фиксированной ширины / высоты в% возникла та же проблема, повторю попытку позже, ty.

3. NP. Удачи! 🙂

Ответ №1:

Я бы сделал это по-другому, используя несколько фонов:

 .box {
  width:250px;
  border-radius:500px 500px 0 0;
  background:
     /* a linear gradient to control the progress. Adjust the angle from 0deg to 180deg*/
     linear-gradient(160deg,transparent 50%,#fff 0) top/100% 200%,
     /* a radial gradient to show only a part of the gradient (20px here)*/
     radial-gradient(farthest-side at bottom,#fff calc(100% - 20px),transparent 0),
     /* the main gradient */
     linear-gradient(to right, green , yellow , red);
}
.box::before {
  content:"";
  display:block;
  padding-top:50%;
}  
 <div class="box"></div>  

Которую вы можете оптимизировать с помощью переменных CSS:

 .box {
  --p:160deg;
  --b:20px;
  
  width:250px;
  display:inline-block;
  border-radius:500px 500px 0 0;
  background:
     /* a linear gradient to control the progress. Adjust the angle from 0deg to 180deg*/
     linear-gradient(var(--p),transparent 50%,#fff 0) top/100% 200%,
     /* a radial gradient to show only a part of the gradient (20px here)*/
     radial-gradient(farthest-side at bottom,#fff calc(100% - var(--b) - 1px),transparent calc(100% - var(--b))),
     /* the main gradient */
     linear-gradient(to right, green , yellow , red);
}
.box::before {
  content:"";
  display:block;
  padding-top:50%;
}  
 <div class="box"></div>
<div class="box" style="--b:30px;--p:90deg"></div>
<div class="box" style="--b:10px;--p:40deg"></div>  

Другой синтаксис:

 .box {
  --p:160deg;
  --b:20px;
  
  width:250px;
  display:inline-block;
  border-radius:500px 500px 0 0;
  padding:var(--b) var(--b) 0;
  background:
     linear-gradient(var(--p),transparent 50%,#fff 0) top/100% 200%,
     linear-gradient(#fff,#fff) content-box,
     linear-gradient(to right, green , yellow , red);
}
.box::before {
  content:"";
  display:block;
  padding-top:50%;
}  
 <div class="box"></div>
<div class="box" style="--b:30px;--p:90deg"></div>
<div class="box" style="--b:10px;--p:40deg"></div>  

И использование маски для прозрачности:

 .box {
  --p:160deg;
  --b:20px;
  
  width:250px;
  display:inline-block;
  border-radius:500px 500px 0 0;
  background: linear-gradient(to right, green , yellow , red);
  -webkit-mask:
     radial-gradient(farthest-side at bottom,transparent calc(100% - var(--b) - 1px),#fff calc(100% - var(--b))),
     linear-gradient(var(--p),#fff 50%,transparent 0) top/100% 200%;
  -webkit-mask-composite:destination-in;
          mask-composite:intersect;
}
.box::before {
  content:"";
  display:block;
  padding-top:50%;
}

body {
  background:#f3f3f3;
}  
 <div class="box"></div>
<div class="box" style="--b:30px;--p:90deg"></div>
<div class="box" style="--b:10px;--p:40deg"></div>  

Комментарии:

1. Вы знаете, как сделать ширину .box в процентах, например, 50% от родительского? Поскольку вы использовали радиус границы 500 пикселей для ширины 250 пикселей .box, я попытался использовать 100% радиус для ширины 50% .box, но не работал правильно: jsfiddle.net/c39w2u5z

2. @Mark используйте очень большое значение, например, 5000px или даже 100vmax. Это должна быть длина, а не процент jsfiddle.net/zowv4k1u