沿着一条线定位点

时间:2016-08-27 13:08:48

标签: html css

我正在尝试使用CSS构建以下组件,但是我无法获得第一个和最后一个点来对齐行的末尾。

它必须能够支持任意数量的点(1到4之间),我也不能依赖于flexbox。

我有一个生成HTML的React组件,如下所示:

<div class="row">
  <div class="col first" style="width:33%">
    <div class="marker complete"></div>
    <label>Feedback</label>
  </div>
  <div class="col" style="width:33%">
    <div class="marker partial"></div>
    <label>Observation</label>
  </div>
  <div class="col last" style="width:33%">
    <div class="marker review"></div>
    <label>Documentation</label>
  </div>
</div>

JavaScript会在呈现前计算列大小,in my codepen implementation,我只是将每列中的所有内容都集中在一起。

我可以通过使用firstlast类来相对定位最终项目来破解解决方案,但是当屏幕大小发生变化时,我总是会开始寻找线条的边缘从分数后面出来。

有没有人知道一个更合理的布局来开始构建它?

3 个答案:

答案 0 :(得分:1)

我的想法是将row设置为display: table-row,然后使用伪元素生成水平条。但是,您遇到了单独使用CSS和HTML无法知道的问题,即第一个和最后一个圆的位置相对于容器的大小。因此,无法使用全宽项目。

另一种方法是使用标签作为伪元素的根项。它们总是列的整个宽度,因此它们可以很好地指示需要使用的内容。

following proposed solution应该适用于IE9。唯一使用的特殊事物是calcafter。 (如果您愿意,也可以使用calc代替transform: translate。)

基本思想是使用一个表行,它会自动缩放,然后使用标签作为根,您可以在其上构建进度条。

label:after {
  content: "";
  height: .5em;
  background: #e2e2e2;
  width: 100%;
  position: absolute;
  top: calc((100% - 1.5em) / 2); /* -1 to compensate text, -.5 for height bar */
  left: 0;
  z-index: -1;
}

.first label:after, .last label:after {
  width: 50%;
}

.first label:after {
  left: auto; 
  right: 0;
}

.single label:after {content: none;}

答案 1 :(得分:0)

你去吧。我认为这就是你要找的东西。

<div class="row">
  <div class="col" style="width:33%">
    <div class="marker marker1 complete"></div>
    <label>Feedback</label>
  </div>
<div class="col2" style="width:33%">
    <div class="marker marker2 partial"></div>
    <label>Observation</label>
</div>
<div class="col3" style="width:33%">
   <div class="marker marker3 review"></div>
     <label>Documentation</label>
   </div>
</div>

https://jsfiddle.net/norcaljohnny/e6nm2rbv/

*如果允许使用JS,我可以根据数字和字长添加一些条件并调整标记缩进。

基本上我为每个块使用了显示块,边距和辅助标记类。

答案 2 :(得分:-1)

&#13;
&#13;
.row {
  display: table;
  margin: 0 auto;
  position: relative;
  width: 100%;
}
.col {
  display: table-cell;
  width: 33%;
  text-align: center;
}
.marker {
  width: 30px;
  height: 30px;
  background-color: lightgray;
  border-radius: 30px;
  margin: 0 auto;
}
.complete {
  background-color: blue;
}
.partial {
  background-color: blue;
  box-sizing: border-box;
  border: 8px solid lightgray;
}
.review {
  background-color: lightblue;
}
.col:not(:last-child) > .marker:after {
  content: '';
  display: inline-block;
  width: 67%;
  height: 0;
  border: 3px solid lightgray;
  position: absolute;
  left: 16.5%;
  top: 12.5px;
  z-index: -10;
}
/* ------------------------------------------- */

.wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 100px;
}
.point {
  height: 30px;
  background-color: lightgray;
  border-radius: 30px;
  flex: 0 0 30px;
  position: relative;
}
.line {
  height: 0;
  border: 3px solid lightgray;
  flex: 1 0;
}
.blue {
  background-color: blue;
}
.lightblue {
  background-color: lightblue;
}
.border {
  background-color: lightgray;
  background-image: radial-gradient(at center center, blue 0, blue 8px, transparent 8px, transparent 100%);
}
.point label {
  position: absolute;
  left: -50%;
  top: 100%;
  text-align: center;
}
&#13;
<h1>Non flex</h1>
<div class="row">
  <div class="col first">
    <div class="marker complete"></div>
    <label>Feedback</label>
  </div>
  <div class="col">
    <div class="marker partial"></div>
    <label>Observation</label>
  </div>
  <div class="col last">
    <div class="marker review"></div>
    <label>Documentation</label>
  </div>
</div>
<h1>Flex</h1>
<div class="wrapper">
  <div class="point blue">
    <label>Feedback</label>
  </div>
  <div class="line"></div>
  <div class="point blue border">
    <label>Observation</label>
  </div>
  <div class="line"></div>
  <div class="point lightblue">
    <label>Documentation</label>
  </div>
</div>
&#13;
&#13;
&#13;