Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Displaying size adjusted buttons on specific points on a line in HTML/CSS

I am a newbie in HTML/CSS and am building a web application using Django right now.

This application draws it's data from a precalculated database. Each entry has a certain length and contains several child entries, which length of each is a fraction of the whole length of the parent entry. As python dictionary it looks like this:

{entry1: {'length': 10000, {child1}: {'start':1, 'end':1000 }, {child2}: {'start':2000, 'end':6000}, ...}

The length of each child is end-start here.

What I am trying to do is to display each entry as a line in HTML/CSS, and each child entry is shown as button on that line. The size of each button on the line should reflect it's length (which is a fraction of the parent entry length, but it's different for each child entry). Importantly, each child entry has a certain position on the parent entry (For example: The parent entry length is 10000, child 1 is at 1-1000, child 2 is at 2000 to 6000 and so on)

The result I want to get to is something like this: enter image description here

I have several tens of entries that I want to display like this, eventually even making graphic connections from one entry to the one displayed below. (Let's say draw a line from entry 1, position 1200 to entry 2, position 400).

I have managed to place the buttons on a line in HTML/CSS, but I have no idea on how to go about adjusting each buttons with appropriately or how to put them in the right position on the parent line.

Could anyone point me towards code, libraries, methods, tutorials or other stuff that could help me achieve this?

like image 434
sequence_hard Avatar asked Jun 24 '19 15:06

sequence_hard


People also ask

How do I show two buttons on the same line in CSS?

If you have multiple buttons that should sit side-by-side on the same line, add the data-inline="true" attribute to each button. This will style the buttons to be the width of their content and float the buttons so they sit on the same line.

How do I make text fit in one line in CSS?

If you want to limit the text length to one line, you can clip the line, display an ellipsis or a custom string. All these can be done with the CSS text-overflow property, which determines how the overflowed content must be signalled to the user.


1 Answers

This can be done in pure CSS. The trick is to use CSS variables and calc() function to dynamically calculate width and starting position as % of a whole graph. This makes the graph responsive.

How does it work

A graph is build with a single hr element and variable number of child nodes. Nodes are positioned absolutely inside the graph element. Length and position of a node is computed using calc() function.

Graph length is set with --graph-length variable.
Nodes have two variables --start and --end.

Width of a node is calculated with:

calc((var(--end) - var(--start)) / var(--graph-length) * 100%)

and its starting position with:

calc(var(--start) / var(--graph-length) * 100%)

Inside Django template substitute hardcoded values with values from dictionary. If you can create a list of children in dictionary like this:

graph = {'entry': {'length': 10000, 'children': [{'child': {'start': 1, 'end': 1000}}, {'child': {'start': 2000, 'end': 6000}}]}}

then generating graph inside Django template will be simple as:

<div class="graph" style="--graph-length: {{ entry.length }};">
  <hr class="line">
    {% for node in entry.children %}
        <span class="node" style="--start: {{ node.child.start }}; --end: {{ node.child.end }};"></span>
    {% endfor %}
</div> 

.graph {
  position: relative;
}

.node {
  position: absolute;
  top: 0;
  width: calc((var(--end) - var(--start)) / var(--graph-length) * 100%);
  left: calc(var(--start) / var(--graph-length) * 100%);
  height: 1em;
  background-color: cornflowerblue;
  display: block;
  border: 1px solid gray;
  border-radius: 3px;
}

.line {
  position: absolute;
  left: 0;
  right: 0;
  height: 0px;
}
<div class="graph" style="--graph-length: 10000;">
  <hr class="line">
  <span class="node" style="--start: 1; --end: 250;"></span>
  <span class="node" style="--start: 400; --end: 800;"></span>
  <span class="node" style="--start: 1500; --end: 3500;"></span>
  <span class="node" style="--start: 6000; --end: 8000;"></span>
  <span class="node" style="--start: 9500; --end: 10000;"></span>
</div>
<br>
<br>
<div class="graph" style="--graph-length: 10000;">
  <hr class="line">
  <span class="node" style="--start: 1; --end: 150;"></span>
  <span class="node" style="--start: 500; --end: 850;"></span>
  <span class="node" style="--start: 1200; --end: 2500;"></span>
  <span class="node" style="--start: 3000; --end: 3200;"></span>
  <span class="node" style="--start: 5000; --end: 6000;"></span>
  <span class="node" style="--start: 6500; --end: 7500;"></span>
  <span class="node" style="--start: 8500; --end: 9000;"></span>
</div>
<br>
<br>
<div class="graph" style="--graph-length: 1000;">
  <hr class="line">
  <span class="node" style="--start: 1; --end: 100;"></span>
  <span class="node" style="--start: 300; --end: 500;"></span>
  <span class="node" style="--start: 650; --end: 750;"></span>
  <span class="node" style="--start: 900; --end: 950;"></span>
</div>
like image 196
mx0 Avatar answered Oct 15 '22 14:10

mx0