There are a lot of excellent front-end chart libraries around. In fact, I wrote several articles on one such library named PlotKit. Any library worth its salt provides a number of options for configuring plot (or marker) lines. Be that as it may, there are times where you might want to design your own. For example, very few of the plot lines that I have come across have line that connects the tick marks. I also encountered a situation just recently where I wanted to display a horizontal marker line under a graphic. In such a situation where you want to create a timeline or any other plot line without a chart above it, you might was well build your own. In fact, once you see how easy it is to do using nothing more than CSS, I’m sure that you’ll agree.
Anatomy of a Plot Line
The exact makeup of a plot line to an extent depends on the content above it, but for the purposes of this tutorial, we’ll construct one that has the following structure:
The relevant parts to be aware of are the two tick types and that the labels are centered below the ticks.
Drawing a Plot Line Below the Content DIV
I was considering going with a Horizontal Rule to depict the plot line, that was until I discovered the CSS ::after pseudo-element. It inserts some content after an element such as an image, text, or, as in this instance, an empty space:
<head> <title>X-axis Chart Marker Line Demo</title> <style type="text/css"> .chart { width:900px; height: 600px; margin: 20px 10px 50px 10px; position: relative; border: 2px solid blue; } .chart:after { content:' '; display:block; border:1px solid black; position:relative; top:608px; left: -2px; } </style> </head> <body> <h1>X-axis Chart Marker Line Demo</h1> <p>this is some content</p> <div class="chart"> </div> <p>more content...</p> </body>
The line is created by the border of one pixel. The :after content is positioned relatively to the main chart area and assigned a top value that is a little larger than the height of the chart so that it sits slightly below it. For this selector to work in IE8, a DOCTYPE must be declared, and you must use the old, single-colon CSS2 syntax (:after instead of ::after).
Don’t be overly concerned about the plot line not spanning the entire length of the chart DIV above it. Once we add the tick marks, it will widen appropriately. Speaking of which…
Adding Tick Marks
Much like the plot line, the ticks will be rendered by the left border of a DIV element. They are assigned a position of absolute so that they span horizontally underneath the plot line.
We still have to set each tick’s position or they’ll just stack on top of each other. To do that, I utilized the :nth-child pseudo-element. This saves me from having to declare an ID for each tick; a common class will do.
.tick { border-left: 2px solid black; height: 18px; top: 608px; position: absolute; } .tick:nth-child(1) { left: -2px; } .tick:nth-child(2) { left: 98px; } .tick:nth-child(3) { left: 198px; } .tick:nth-child(4) { left: 298px; } .tick:nth-child(5) { left: 398px; } .tick:nth-child(6) { left: 498px; } .tick:nth-child(7) { left: 598px; } .tick:nth-child(8) { left: 698px; } .tick:nth-child(9) { left: 798px; } .tick:nth-child(10) { left: 898px; }
Here’s the chart HTML with all of the ticks:
<div class="chart"> <div class="tick"></div> <div class="tick"></div> <div class="tick"></div> <div class="tick"></div> <div class="tick"></div> <div class="tick"></div> <div class="tick"></div> <div class="tick"></div> <div class="tick"></div> <div class="tick"></div> </div>
Now we’re getting somewhere!
Assigning Major and Minor Tick Marks
I wanted certain tick marks to stand out as major tick marks. Rather than select individual ticks, I found that using the nth-child selector with a formula to be far more economical. Formatted as a “an + b” expression, the “a” represents a cycle size and b is an offset value.
.tick:nth-child(3n+1) { border-left: 4px solid darkred; height: 24px; }
Adding Labels
Semantically, I wanted to include the labels as children of each tick DIV. That’s all fine and well, but the reality is that the labels are not within the tick DIVs at all, but rather, centered underneath each tick’s left border. This could also have been accomplished using the :after pseudo-element, but I scrapped that idea because it would have necessitated generating the labels using the :after’s content attribute, thus placing content in the CSS file, something that I’m not overly fond of.
.tick > span { position:relative; left: -5px; top: 26px; font: 1em Arial, Helvetica, sans-serif; }
You can see in the above code that setting the left attribute to a negative number does the trick.
Labels are contained within SPAN elements because you can’t select text nodes using plain CSS.
<div class="chart"> <div class="tick"><span>0</span></div> <div class="tick"><span>1</span></div> <div class="tick"><span>2</span></div> <div class="tick"><span>3</span></div> <div class="tick"><span>4</span></div> <div class="tick"><span>5</span></div> <div class="tick"><span>6</span></div> <div class="tick"><span>7</span></div> <div class="tick"><span>8</span></div> <div class="tick"><span>9</span></div> </div>
The nth-child pseudo-element may again be employed to set a different font weight and adjust the spacing accordingly.
.tick:nth-child(3n+1) > span { left: -6px; font-weight: bold; }
Here is the finished product:
Conclusion
I have included the full demo on CodePen. If anyone has ideas for improving the design or code feel free to submit a comment or email me. I’d love to hear from you! In a future article, I’ll show you how using JavaScript can make the chart creation more dynamic.