If you're viewing on github, see the html version at here.
Likewise, if you're viewing the website, you can see the github page here
- Charts directly from markdown lists via
pandoc
- Retains accessible, semantic HTML
- No javascript or other frameworks, no external dependencies, uses only a small .css file
- Use html templates to directly create charts, or convert from markdown
The point of C💚SS.css is to allow easy creation of simple charts for documentation, data storytelling / journalism, etc. It features plots of 1-D lists, and has a custom markdown filter that converts suitably formatted lists directly to charts. It has no dependencies (other than a modern browser), and is very small compared to javascript based charting tools. The html is based on <ul>
lists and will collapse back to readible lists in the absence of css support, making it accessible to all readers. It is open source and easily configurable according to project needs.
The non-chart elements on the html version of this page were styled with mvp.css. MVP.css was one of the inspirations for C💚SS.css. Although C💚SS.css turned out very differently, MVP.css got me on to the idea of having a simple, self-contained .css file that could easily transform a text page into something nice.
Requirements
A modern browser that supports css
is required. It has been tested on chrome and firefox.
To write html directly, all you need is the C💚SS.css style file.
See below or view source for usage.
To convert directly from markdown to html charts, you will need pandoc
installed. Even if you never use C💚SS.css, you should still get pandoc
. You can find information on how to install it here. There is good information on markdown syntax here.
Pandoc works with chartss.lua
to parse markdown into html that uses C💚SS.css.
Running chartss.lua
The following command creates a stand alone html file out of a markdown file. Markdown lists conforming to the syntax discussed below will automatically be converted into charts.
$ pandoc -t chartss.lua infile.md > outfile.html
Syntax
(*|-) category: value
Example
- Dogs: 39
- Cats: 7
- Lions: 36
- Tigers: 55
- Bears: 33
- Walruses: 30
Output (see html version)
- Dogs: 39
- Cats: 7
- Lions: 36
- Tigers: 55
- Bears: 33
- Walruses: 30
Syntax
(*|-) (xi,yi)
Example
- (15,12)
- (0.25,6.78)
- (-.7,9)
- (-4,-6)
Output (see html version)
- (15,12)
- (0.25,6.78)
- (-.7,9)
- (-4,-6)
Syntax
(*|-) List Item
Example
* Cats
* Dogs
* Mice
* Men
* Lambs
* Lions
Output (if C💚SS.css cannot chart it, a normal list is displayed)
- Cats
- Dogs
- Mice
- Men
- Lambs
- Lions
Syntax (constant spacing indicates a line)
(*|-) x1 : y1
(*|-) x1+dx : y2
(*|-) x1+2dx : y3
...
Example
* 1.5 : 3.3
* 3 : -1.2
* 4.5 : 0
* 6 : 0
* 7.5 : 1.5
* 9 : 4
* 10.5 : 8
Output (see html version)
- 1.5 : 3.3
- 3 : -1.2
- 4.5 : 0
- 6 : 0
- 7.5 : 1.5
- 9 : 4
- 10.5 : 8
Syntax (add a plus sign to the end of labels)
(*|-) category: label+
Example
* Dogs : 20+
* Cats : 10+
* Lions : 30+
* Tigers : 15+
* Bears : 20+
Output (see html version)
- Dogs : 20+
- Cats : 10+
- Lions : 30+
- Tigers : 15+
- Bears : 20+
Syntax
(*|-) total: value=
(*|-) category1: value1+
(*|-) category2: value2+
...
Output (see html version)
- Animals: 95=
- Dogs : 20+
- Cats : 10+
- Lions : 30+
- Tigers : 15+
- Bears : 20+
Note: this html was generated using the defaults of chartss.lua
. This means that 1. More or fewer ticks can be added on the axes and 2. There has been som autoscaling applied to the chart areas. If you are creating manual charts, you will have to scale between the label values and the percentage values that the charting functions use.
<ul class="BarList">
<div class="PlotOuterContainer">
<div class="YTicks">
<span class="TickLabel" style="--tick-label:'99.8'"></span>
<span class="TickLabel" style="--tick-label:'79.8'"></span>
<span class="TickLabel" style="--tick-label:'59.9'"></span>
<span class="TickLabel" style="--tick-label:'39.9'"></span>
<span class="TickLabel" style="--tick-label:'20.0'"></span>
<span class="TickLabel" style="--tick-label:'0.0'"></span>
</div>
<div class="FlexColumn StackFlexColumn">
<li class="BarBlock" style="--stack-height:20.1%">Dogs: 20</li>
<li class="BarBlock" style="--stack-height:10.0%">Cats: 10</li>
<li class="BarBlock" style="--stack-height:30.1%">Lions: 30</li>
<li class="BarBlock" style="--stack-height:15.0%">Tigers: 15</li>
<li class="BarBlock" style="--stack-height:20.1%">Bears: 20</li>
</div></div>
</ul>
<div class="PlotOuterContainer">
<div class="YTicks">
<span class="TickLabel" style="--tick-label:'12.9'"></span>
<span class="TickLabel" style="--tick-label:'9.0'"></span>
<span class="TickLabel" style="--tick-label:'5.0'"></span>
<span class="TickLabel" style="--tick-label:'1.0'"></span>
<span class="TickLabel" style="--tick-label:'-3.0'"></span>
<span class="TickLabel" style="--tick-label:'-6.9'"></span>
</div>
<div class="FlexColumn"> <div class="ScatterMainContainer">
<div class="ScatterPoint" style="--pixel-x-percent:95%;--pixel-y-percent:95%"><li class="ScatterValue">(15,12)</li></div>
<div class="ScatterPoint" style="--pixel-x-percent:25%;--pixel-y-percent:69%"><li class="ScatterValue">(0.25,6.78)</li></div>
<div class="ScatterPoint" style="--pixel-x-percent:20%;--pixel-y-percent:80%"><li class="ScatterValue">(-0.7,9)</li></div>
<div class="ScatterPoint" style="--pixel-x-percent:5%;--pixel-y-percent:5%"><li class="ScatterValue">(-4,-6)</li></div>
</div><div class="BarLi"> <span class="XTicks">
<span class="TickLabel" style="--tick-label:'-5.0'"></span>
<span class="TickLabel" style="--tick-label:'-0.8'"></span>
<span class="TickLabel" style="--tick-label:'3.4'"></span>
<span class="TickLabel" style="--tick-label:'7.6'"></span>
<span class="TickLabel" style="--tick-label:'11.8'"></span>
<span class="TickLabel" style="--tick-label:'15.9'"></span>
</span></div></div></div>
(For line plots, the lower y-value of each line segment always has to come first, as --line-y-from
, with the direction specified by --line-slope
. Also note that a zero slope line needs its border-top-style:solid
property set as shown below as a hack to show the line.
<div class="PlotOuterContainer">
<div class="YTicks">
<span class="TickLabel" style="--tick-label:'8.4'"></span>
<span class="TickLabel" style="--tick-label:'6.4'"></span>
<span class="TickLabel" style="--tick-label:'4.4'"></span>
<span class="TickLabel" style="--tick-label:'2.4'"></span>
<span class="TickLabel" style="--tick-label:'0.4'"></span>
<span class="TickLabel" style="--tick-label:'-1.7'"></span>
</div>
<div class="FlexColumn"> <div class="LineOuterContainer">
<li class="InvisibleListItem">1.5 : 3.3</li>
<div class="SegmentContainer" style="--line-y-from:4.5%;--line-y-to:49.0%;--line-slope:to top right">
<li class="LineSegment">3 : -1.2</li>
<div class="LineBlock"></div> </div>
<div class="SegmentContainer" style="--line-y-from:4.5%;--line-y-to:16.3%;--line-slope:to top left">
<li class="LineSegment">4.5 : 0</li>
<div class="LineBlock"></div> </div>
<div class="SegmentContainer" style="--line-y-from:16.3%;--line-y-to:16.3%;--line-slope:to top left">
<li class="LineSegment" style="border-top-style:solid">6 : 0</li>
<div class="LineBlock"></div> </div>
<div class="SegmentContainer" style="--line-y-from:16.3%;--line-y-to:31.2%;--line-slope:to top left">
<li class="LineSegment">7.5 : 1.5</li>
<div class="LineBlock"></div> </div>
<div class="SegmentContainer" style="--line-y-from:31.2%;--line-y-to:55.9%;--line-slope:to top left">
<li class="LineSegment">9 : 4</li>
<div class="LineBlock"></div> </div>
<div class="SegmentContainer" style="--line-y-from:55.9%;--line-y-to:95.5%;--line-slope:to top left">
<li class="LineSegment">10.5 : 8</li>
<div class="LineBlock"></div> </div>
</div><div class="BarLi"> <span class="XTicks">
<span class="TickLabel" style="--tick-label:'1.1'"></span>
<span class="TickLabel" style="--tick-label:'3.0'"></span>
<span class="TickLabel" style="--tick-label:'5.0'"></span>
<span class="TickLabel" style="--tick-label:'7.0'"></span>
<span class="TickLabel" style="--tick-label:'9.0'"></span>
<span class="TickLabel" style="--tick-label:'10.9'"></span>
</span></div></div></div>
<ul class="BarList">
<div class="PlotOuterContainer">
<div class="YTicks">
<span class="TickLabel" style="--tick-label:'99.8'"></span>
<span class="TickLabel" style="--tick-label:'79.8'"></span>
<span class="TickLabel" style="--tick-label:'59.9'"></span>
<span class="TickLabel" style="--tick-label:'39.9'"></span>
<span class="TickLabel" style="--tick-label:'20.0'"></span>
<span class="TickLabel" style="--tick-label:'0.0'"></span>
</div>
<div class="FlexColumn StackFlexColumn">
<li class="BarBlock" style="--stack-height:20.1%">Dogs: 20</li>
<li class="BarBlock" style="--stack-height:10.0%">Cats: 10</li>
<li class="BarBlock" style="--stack-height:30.1%">Lions: 30</li>
<li class="BarBlock" style="--stack-height:15.0%">Tigers: 15</li>
<li class="BarBlock" style="--stack-height:20.1%">Bears: 20</li>
</div></div>
</ul>
(You need to account for the bar height as well as the padding that uses a LineBlock
)