【问题标题】:Creating CSS3 Circles connected by lines创建由线条连接的 CSS3 圆圈
【发布时间】:2023-03-11 04:40:01
【问题描述】:

我必须在 CSS 中实现以下圆和线组合,我正在寻找有关如何有效实现这一点的指针。圆圈和线条应如下所示:

我可以这样实现圈子:

span.step {
  background: #ccc;
  border-radius: 0.8em;
  -moz-border-radius: 0.8em;
  -webkit-border-radius: 0.8em;
  color: #1f79cd;
  display: inline-block;
  font-weight: bold;
  line-height: 1.6em;
  margin-right: 5px;
  text-align: center;
  width: 1.6em; 
}

但这些台词我很难理解。

圆圈的大小会根据是否为活动步骤而变化,连接圆圈的线的颜色也会根据状态而变化。我将如何做到这一点?

【问题讨论】:

  • 可能重复? stackoverflow.com/questions/17686986/…>
  • 要求代码的问题必须表明对所解决问题的最低理解。包括尝试过的解决方案、它们为什么不起作用以及预期的结果
  • @NamelessOne - 我不相信不是重复的
  • @HGandhi:您对使用 SVG 的解决方案持开放态度吗?对于这种类型的界面,我认为 SVG 比纯 CSS 更好。
  • @TylerEich - 我愿意接受这个建议。

标签: css css-float sass


【解决方案1】:

仅限 CSS3、Flex、响应式、动态、可定制

好吧...我有点过火了 - 就是这样。

(已在 Chrome、Firefox、Safari 上测试并运行 - 截至 2020 年 7 月)

/* custom stylings */
:root {
  --active-bg-color: #1975CF;
  --active-text-color: white;
  --inactive-bg-color: #C4DDF4;
  --inactive-text-color: #3480D2;
  --line-width: 5%;
  --active-circle-diam: 30px;
  --inactive-circle-diam: 20px;
}
ul {
  font-family: Arial;
  border: 1px solid magenta;
}


/* --- breadcrumb component --- */
ul {
  position:relative;
  display:flex;
  justify-content: space-between;
  align-items: center;
   padding: 0;
}
li:only-child {
  margin: auto;
}

/* lines */
li:not(:last-child):after {
  content: '';
  position: absolute;
  top: calc((100% - var(--line-width)) / 2);
  height: var(--line-width);
  z-index: -1;
}
/* circles */
li {
  overflow: hidden;
  text-align:center;
  border-radius: 50%;
  text-indent: 0;
  list-style-type: none;
}

/* active styling */
li,
li:not(:last-child):after {
  background: var(--active-bg-color);
  color: var(--active-text-color);
}

/* inactive styling */
li.active:after,
li.active ~ li,
li.active ~ li:not(:last-child):after {
  background: var(--inactive-bg-color);
  color: var(--inactive-text-color);
}

/* circle sizing */
li.active {
  width: var(--active-circle-diam);
  height: var(--active-circle-diam);
  line-height: calc(var(--active-circle-diam) + 0.1rem);
  font-size: calc(var(--active-circle-diam) / 1.6);
}
li:not(.active) {
  width: var(--inactive-circle-diam);
  height: var(--inactive-circle-diam);
  line-height: calc(var(--inactive-circle-diam) + 0.1rem);
  font-size: calc(var(--inactive-circle-diam) / 1.6);
}

/* 
Calculate ddynamic width using css3 only.
N.B. if you know the total count, hardcode away!
*/

li:first-child:nth-last-child(2):not(:last-child):after,
li:first-child:nth-last-child(2) ~ li:not(:last-child):after {
    width: calc((100% - 2rem) / 1);
}
li:first-child:nth-last-child(3):not(:last-child):after,
li:first-child:nth-last-child(3) ~ li:not(:last-child):after {
    width: calc((100% - 2rem) / 2);
}
li:first-child:nth-last-child(4):not(:last-child):after,
li:first-child:nth-last-child(4) ~ li:not(:last-child):after {
    width: calc((100% - 2rem) / 3);
}
li:first-child:nth-last-child(5):not(:last-child):after,
li:first-child:nth-last-child(5) ~ li:not(:last-child):after {
    width: calc((100% - 2rem) / 4);
}
li:first-child:nth-last-child(6):not(:last-child):after,
li:first-child:nth-last-child(6) ~ li:not(:last-child):after {
    width: calc((100% - 2rem) / 5);
}
li:first-child:nth-last-child(7):not(:last-child):after,
li:first-child:nth-last-child(7) ~ li:not(:last-child):after {
    width: calc((100% - 2rem) / 6);
}

li:first-child:nth-last-child(8):not(:last-child):after,
li:first-child:nth-last-child(8) ~ li:not(:last-child):after {
    width: calc((100% - 2rem) / 7);
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li class="active">4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
</ul> 
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li class="active">4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
</ul> 
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li class="active">4</li>
  <li>5</li>
  <li>6</li>
</ul> 
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li class="active">4</li>
  <li>5</li>
</ul> 
<ul>
  <li>1</li>
  <li class="active">2</li>
  <li>3</li>
  <li>4</li>
</ul> 
<ul>
  <li>1</li>
  <li class="active">2</li>
  <li>3</li>
</ul> 
<ul>
  <li class="active">1</li>
  <li>2</li>
</ul> 
<ul>
  <li class="active">1</li>
</ul>

【讨论】:

  • 太棒了!非常感谢!
【解决方案2】:

您可以使用伪元素和相邻的兄弟选择器(~)来实现此效果,而无需额外的标记:

li {
  width: 2em;
  height: 2em;
  text-align: center;
  line-height: 2em;
  border-radius: 1em;
  background: dodgerblue;
  margin: 0 1em;
  display: inline-block;
  color: white;
  position: relative;
}

li::before{
  content: '';
  position: absolute;
  top: .9em;
  left: -4em;
  width: 4em;
  height: .2em;
  background: dodgerblue;
  z-index: -1;
}


li:first-child::before {
  display: none;
}

.active {
  background: dodgerblue;
}

.active ~ li {
  background: lightblue;
}

.active ~ li::before {
  background: lightblue;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li class="active">4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
</ul>  

Demo on CodePen

【讨论】:

  • 这是一个绝妙而优雅的解决方案。干得好。
  • 要增加每个圆圈之间的距离并引入响应行为,请进行 2 处修改:1) 代替 em,在 li 边距中使用 vw,如下所示:margin 0 5vw 0 5vw;,然后要拉伸每个圆圈之间的线条,请更新 li::before 属性:left: -11vw; width: 11vw;
  • @AaronDanielson 和其他正在寻找完全响应、有弹性和可定位(flexbox)版本的人,请参阅我对这个问题的回答:stackoverflow.com/a/42382589/504075
  • 在每个数字下方(圆圈外)添加标签如何?
  • 不幸的是,这个解决方案只有在容器的背景是透明的情况下才有效。如果容器具有彩色背景,则这些线将放置在容器的后面并且它们被隐藏。有解决办法吗?
【解决方案3】:

我使用 Bootstrap 4 和 FontAwesome 来制作我的版本。

这是代码笔:[a link]https://codepen.io/tr4c355/pen/roBjWV

HTML 和 CSS:

<style>
.line-btw { 
  height:3px;
  width:100px;
  background-color: orange;
}
</style>

<div class="fa-stack fa-lg text-center">
  <i class="fa fa-circle-o fa-stack-2x"></i>
  <div class=""><b>1</b></div>
</div>
<div class="line-btw"></div>
<div class="fa-stack fa-lg text-center" style="">
  <i class="fa fa-circle-o fa-stack-2x"></i>
  <div style=""><b>2</b></div>
</div>
<div class="line-btw"></div>
<div class="fa-stack fa-lg text-center" style="">
  <i class="fa fa-circle-o fa-stack-2x"></i>
  <div class=""><b>3</b></div>
</div>

【讨论】:

    【解决方案4】:

    我根据答案做的例子:https://codepen.io/Smakosh/pen/ZvvyMg

    Pug
    ul
      li.list.active 1
      li.list 2
      li.list 3
      li.list 4
    Sass
    ul
      list-style: none
        li
          display: inline-block
          width: 4rem
          height: 4rem
          line-height: 4rem
          border-radius: 100%
          background: #d8d8d8
          margin-right: 2rem
          position: relative
          &:first-child
            margin-left: unset
            &:before
              display: none
          &:before
            content: ''
            width: 2.4rem
            background-color: #d8d8d8
            height: 2px
            position: absolute
            top: 2rem
            right: 3.9rem
        .active
          background: #03A9F4
          color: #fff
          &:before
            background-color: #03A9F4
    

    【讨论】:

      【解决方案5】:

      这不是我自己的,但效果很好,看起来很优雅, 仅适用于 css,您可以对其进行更多的 perzonalize。来源http://jsfiddle.net/Misiu/y1Lo3qh1/

      var i = 1;
      $('.progress .circle').removeClass().addClass('circle');
      $('.progress .bar').removeClass().addClass('bar');
      setInterval(function () {
          $('.progress .circle:nth-of-type(' + i + ')').addClass('active');
          $('.progress .circle:nth-of-type(' + (i - 1) + ')').removeClass('active').addClass('done');
          $('.progress .circle:nth-of-type(' + (i - 1) + ') .label').html('&#10003;');
          $('.progress .bar:nth-of-type(' + (i - 1) + ')').addClass('active');
          $('.progress .bar:nth-of-type(' + (i - 2) + ')').removeClass('active').addClass('done');
          i++;
          if (i == 8) {
              $('.progress .circle').removeClass().addClass('circle');
              $('.progress .bar').removeClass().addClass('bar');
              i = 1;
          }
      }, 1000);
      *,
      *:after,
      *:before {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
        font-family: "Open Sans";
      }
      /* Form Progress */
      
      .progress {
      
        margin: 20px auto;
        text-align: center;
        padding-bottom: 80px;
      }
      .progress .circle,
      .progress .bar {
        display: inline-block;
        background: #fff;
        width: 40px;
        height: 40px;
        border-radius: 40px;
        border: 1px solid #d5d5da;
        vertical-align:top;
      }
      .progress .bar {
        position: relative;
        width: 80px;
        height: 6px;
        margin: 0 -5px 17px -5px;
        border-left: none;
        border-right: none;
        border-radius: 0;
        top:16px;
        vertical-align:top
      }
      .progress .circle .label {
        display: inline-block;
        width: 32px;
        height: 32px;
        line-height: 32px;
        border-radius: 32px;
        margin-top: 3px;
        color: #b5b5ba;
        font-size: 17px;
      }
      .progress .circle .title {
        color: #b5b5ba;
        font-size: 13px;
        line-height: 18px;
        margin-left: -30px;
        display: block;
        width: 100px;
        margin-top: 5px;
      }
      /* Done / Active */
      
      .progress .bar.done,
      .progress .circle.done {
        background: #eee;
      }
      .progress .bar.active {
        background: linear-gradient(to right, #EEE 40%, #FFF 60%);
      }
      .progress .circle.done .label {
        color: #FFF;
        background: #8bc435;
        box-shadow: inset 0 0 2px rgba(0, 0, 0, .2);
      }
      .progress .circle.done .title {
        color: #444;
      }
      .progress .circle.active .label {
        color: #FFF;
        background: #0c95be;
        box-shadow: inset 0 0 2px rgba(0, 0, 0, .2);
      }
      .progress .circle.active .title {
        color: #0c95be;
      }
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
      <link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
      <div class="progress">
        <div class="circle done"> <span class="label">1</span>
          <span class="title">Order</span>
      
        </div> <span class="bar done"></span>
      
        <div class="circle done"> <span class="label">2</span>
          <span class="title">Address</span>
      
        </div> <span class="bar active"></span>
      
        <div class="circle active"> <span class="label">3</span>
          <span class="title">Payment</span>
      
        </div> <span class="bar"></span>
      
        <div class="circle"> <span class="label">4</span>
          <span class="title">Review</span>
      
        </div> <span class="bar"></span>
      
        <div class="circle"> <span class="label">5</span>
          <span class="title">Finish</span>
      
        </div>
      </div>
      <div class="progress">
        <div class="circle done"> <span class="label">1</span>
          <span class="title">Order informations</span>
      
        </div> <span class="bar active"></span>
      
        <div class="circle active"> <span class="label">2</span>
          <span class="title">Order review</span>
      
        </div> <span class="bar"></span>
      
        <div class="circle"> <span class="label">3</span>
          <span class="title">Finish</span>
      
        </div>
      </div>

      【讨论】:

      • 这很漂亮!
      【解决方案6】:


      在出色的 answer from @bookcasey 的帮助下,我发现自己以相反的方式进行操作以使其响应;

      • 我将圆圈设置为 ::before 伪选择器(带有自动 css 计数器)。
      • 之间的线条是li 元素,因此它们可以被弹性框拉伸。

      它现在伸展以填充父级,并自动处理不同数量的步骤。您还可以对父级ul 执行调整font-size 之类的操作,并让整个事情适应。

      我相信它可以改进,所以请随时贡献:)


      交互式 CodePen:带有步骤的 Flexbox 时间线: http://codepen.io/ccondrup/pen/bqbGWB?editors=1100


      ul {
        align-content: center;
        align-items: center;
        counter-reset: stepCount;
        display: flex;
        justify-content: space-around;
        margin: 10vh auto 20vh;  /* for codepen */
      }
      
      li {
        background: dodgerblue;
        color: white;
        content: ' ';
        display: flex;
        flex-grow: 1;
        height: .3em;
        line-height: 1em;
        margin: 0;
        position: relative;
        text-align: right;
        z-index: -1;
      }
      
      li::before {
        background: dodgerblue;
        border-radius: 50%;
        color: white;
        content: counter(stepCount);
        counter-increment: stepCount;
        height: 2em;
        left: -2em;
        line-height: 2em;
        position: absolute;
        text-align: center;
        top: -.85em;
        width: 2em;
      }
      
      li.active {
        background-color: lightblue;
      }
      
      li.active~li {
        background-color: lightblue;
      }
      
      li.active~li::before {
        background-color: lightblue;
      }
      
      li:last-child {
        flex-grow: 0;
        flex-shrink: 1;
        flex-basis: 0;
      /* Shorthand: flex: 0 1 0; */
      }
      
      ul.bigger {
        font-size: 1.3em;
      }
      
      ul.highlight-active li.active::before {
        font-size: 1.6em;
        background: navy;
      }
      
      ul.roman li::before {
        content: counter(stepCount, upper-roman);
      }
      
      ul.triangle li::before {
        width: 0;
        height: 0;
        border-radius: 0;
        border-left: 1em solid white;
        border-right: 1em solid white;
        border-bottom: .8em solid dodgerblue;
        content: '';
        top: -.65em;
      }
      
      ul.triangle li:first-child::before {
        left: 0;
      }
      
      ul.triangle li.active~li::before {
        border-bottom-color: lightblue;
      }
      <ul>
        <li></li>
        <li></li>
        <li class="active"></li>
        <li></li>
        <li></li>
        <li></li>
      </ul>
      
      
      <ul class="bigger highlight-active">
        <li></li>
        <li></li>
        <li class="active"></li>
        <li></li>
      </ul>
      
      
      <ul class="roman">
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li class="active"></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
      </ul>
      
      
      <ul class="triangle">
        <li></li>
        <li></li>
        <li class="active"></li>
        <li></li>
        <li></li>
      </ul>

      【讨论】:

      【解决方案7】:

      虽然这可以通过 CSS3 实现,但我认为 SVG 是用于复杂界面的更好工具。

      我用 SVG 制作了这个(使用 CSS 样式):

      这里是a Plunk to demonstrate

      【讨论】:

        【解决方案8】:

        嗯,这是一大堆标记,但你可以这样做:

        使用display: table-cell;,因为它会自动调整项目的宽度以填充空间。

        然后,有一组圆形元素和一组线条元素。线条元素只是有一个底部边框,而圆形元素只是相对向下定位以与线条对齐。

        请注意,圆圈需要有一个额外的容器,否则table-cell 会将所有圆圈拉伸到相同的高度,而您不希望这样。这将要求您将这些容器的宽度设置为 1px,这将强制它为其子容器的大小。

        看看这个演示:

        http://jsfiddle.net/Sjdm4/

        【讨论】:

        • 我认为它可以做得更简单,无需使用伪元素进行额外标记。
        猜你喜欢
        • 2016-04-25
        • 1970-01-01
        • 1970-01-01
        • 2016-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多