CSS简单甘特图(紧凑型)

时间:2018-08-24 09:01:03

标签: javascript html css

我正在尝试使用html和css生成一个简单的甘特图,我需要弄清楚如何使其紧凑,这意味着如果存在空白,则该栏应尝试在保持行距的同时适合上一行相同的x距离。

上下文:

  • X轴是以月为单位的时间轴
  • 每个项目在给定的月份开始和结束
  • 每个元素的宽度和边距都是通过JS生成的

当前输出: enter image description here

所需的输出: enter image description here

约束

  • 使用JS解决方案是可以的,但理想情况下,该解决方案不需要使用过大的现有js库,因为代码将在浏览器扩展上运行,这会暴露出很多兼容性问题。
  • 这些项目不需要动态移动,因为在大多数情况下,这类似于渲染的图像。
  • 最多可以渲染30个项目。

当前实施摘要: [编辑]我稍微更改了代码段,以证明需要与x保持固定距离。

.timeline div {
    height: 10px;
    background: black;
    margin: 2px;
}
<div class="timeline">
  <div style="width: 80px; margin-left: 0px;"></div>
  <div style="width: 40px; margin-left: 35px;"></div>
  <div style="width: 45px; margin-left: 40px;"></div>
  <div style="width: 100px; margin-left: 135px;"></div>
  <div style="width: 160px; margin-left: 270px;"></div>
  <div style="width: 185px; margin-left: 385px;"></div>
</div>

我尝试过的其他解决方案:

最初,我首先在JS中渲染一个每月的正方形矩阵,然后为每个匹配的月份添加一个元素,然后使用一些复杂的逻辑来帮助进行渲染,但是我意识到它变得越来越复杂,所以我回溯了一下以检查是否绝对确定没有更简单的解决方案。

2 个答案:

答案 0 :(得分:1)

步骤

  • 将时间轴设置为inline-flex
  • 使用双倍高度可使子元素上下排列

    • 高度:20px;
  • 偶数子元素与底部对齐

    • align-self:flex-end;
  • 使用绝对进行定位,以左边缘
  • 获得动态起始位置

.timeline {
  display: inline-flex;
  height: 20px;
  position : relative;
}

.timeline div {
  height: 10px;
  background-color: black;
  position : absolute;
}

.timeline div:nth-child(even) {
  align-self: flex-end;
}
<div class="timeline">
 <div style="width: 80px; margin-left: 0px;"></div>
  <div style="width: 20px; margin-left: 75px;"></div>
  <div style="width: 45px; margin-left: 90px;"></div>
  <div style="width: 100px; margin-left: 135px;"></div>
  <div style="width: 160px; margin-left: 270px;"></div>
  <div style="width: 185px; margin-left: 385px;"></div>
</div>


三个元素平行重叠

您可以将align-items设置为flex-start,并将margin-top更改为从上方偏移位置

步骤

  • 一个元素的高度*元素的数量
    • 高度:30像素(10 * 3)
  • 使用默认对齐项:flex-start重设偏移位置
  • margin-top更改为从上方偏移位置
    • 高一个元素*级别
    • 秒:10 * 2
    • 第三名:10 * 3

.timeline {
  display: inline-flex;
  height: 30px;
  position : relative;
}

.timeline div {
  height: 10px;
  background-color: black;
  position : absolute;
}

.second{
  margin-top : 10px;
}

.third {
  margin-top : 20px;
}
<div class="timeline">
 <div style="width: 80px; margin-left: 0px;"></div>
  <div style="width: 20px; margin-left: 75px;" class="second"></div>
  <div style="width: 45px; margin-left: 90px;" class="third" ></div>
  <div style="width: 100px; margin-left: 135px;"></div>
  <div style="width: 160px; margin-left: 270px;"></div>
  <div style="width: 185px; margin-left: 385px;"></div>
</div>

答案 1 :(得分:0)

最终,最终的解决方案是使用具有以下CSS的容器来使用css-grid:

.timeline_container {
    display: inline-grid; // all contents of the container will be treated as grid elements
    grid-auto-columns: 40px; // defines the default width of each column
    grid-auto-rows: 40px; // defines the height of each row

    /* the line below is the key part to making it compact/dense */
    grid-auto-flow: row dense; // keeps rows compact by filling available row whitespace
}

每个子元素都具有以下CSS:

.timeline_item {
    grid-column: 3 / 5; // defines start and end column where the item
}

因此以下HTML可以完全按照我需要的方式呈现:

<div class='timeline_container'>
    <div class='timeline_item'></div>
    <div class='timeline_item'></div>
    <div class='timeline_item'></div>
</div>

我撰写了有关该解决方案的更详细的文章:https://www.cvtimeline.com/creating-a-gantt-timeline-with-css-grid/

css-grid岩石!!!