Reject Modernity, Embrace Tradition
Javascript sucks.

In an effort to eschew Javascript as much as possible but still have sortable tables, it requires a bit of CSS styling to get it to work. In addition there are some limitations. Using this as a starting guide, I adapted it to create these type of labels and stylings dynamically using Liquid.




Example Sortable Table

"Conditions for CSS Variables"2016-10-2110368
Controlling the Specificity2016-12-212431
Counters and Stones2018-01-044463
Flexible Overflow2017-11-286585
Keyboard-Only Focus2017-06-274597
Label-to-Input States2017-05-312829


Limitations:

What’s going on here?

Data is loaded from a .yaml file and the subsequent data is used to populate <style> tags and fill out the html table. Here’s what the data looks like:

Yaml Data

name: "TEST"
headers:
  name:
    name: Name
    sortable: False
    type: string
    text_align: left
  published:
    name: Published
    sortable: True
    type: date
    text_align: center
  views:
    name: Views
    sortable: True
    type: value
    text_align: right 
rows:
  - name: <a href="/">"Conditions for CSS Variables"</a>
    published: 2016-10-21
    views: 10368
  - name: <a href="https://kizu.ru/en/fun/controlling-the-specificity/">Controlling the Specificity</a>
    published: 2016-12-21
    views: 2431
  - name: <a href="https://kizu.ru/en/blog/counters-and-stones/">Counters and Stones</a>
    published: 2018-01-04
    views: 4463
  - name: <a href="https://kizu.ru/en/blog/flexible-overflow/">Flexible Overflow</a>
    published: 2017-11-28
    views: 6585
  - name: <a href="https://kizu.ru/en/blog/keyboard-only-focus/">Keyboard-Only Focus</a>
    published: 2017-06-27
    views: 4597
  - name: <a href="https://kizu.ru/en/blog/label-to-input/">Label-to-Input States</a>
    published: 2017-05-31
    views: 2829

Jekyll Include file using Liquid Templating

Inside a page, the data is then fed to a Jekyll include. This file uses Liquid templating quite extensively. The include creates the CSS styling tags specific to this table, making sure that they don’t conflict with other tables on the same page with similar names or headers. Then the table is created and each row has the appropriate inline styling to tell CSS how to sort the table.

<style> generated specifically for the table

{%-assign table_data = include.table_data -%}
{%-capture table_name-%}{%-if include.id -%}id_{{include.id|handleize}}-{%-endif-%}table_{{table_data.name|handleize}}{%-endcapture-%}

#sort-ascending-{{table_name}}:checked + .table .table-orderer[for=sort-ascending-{{table_name}}],
#sort-ascending-{{table_name}}:not(:checked) + .table .table-orderer[for=sort-descending-{{table_name}}] {
  display: none !important;
}

{%for header_kv in table_data.headers %}
  {%-assign header = header_kv[1]-%}
  {%-capture name-%}{{table_name}}-header_{{header_kv[0]|handleize}}{%-endcapture-%}
  {%-if header.hidden-%}{%-continue-%}{%-endif-%}
  .table-col-{{name}} {
    text-align:{%-if header.text_align and header.text_align!=empty-%}{{header.text_align}}{%-else-%}inherit{%-endif-%};
  }
  {%-unless header.sortable-%}{%-continue-%}{%-endunless-%}
  #sort-by-{{name}}:checked ~ .table > .table-body > .table-row {
    --order: var(--order-by-{{name}})
  }
  #sort-by-{{name}}:checked ~ .table .table-sorter[for=sort-by-{{name}}] ~ .table-orderer {
    display: inline;
  }
{%endfor%}
#sort-ascending-{{table_name}}:checked + .table {
  --sort-order: 1;
}

HTML div generated for the table

<div class="table-wrapper">
  {%-for header_kv in table_data.headers -%}
    {%-assign header = header_kv[1]-%}
    {%-if header.hidden-%}{%-continue-%}{%-endif-%}
    {%-unless header.sortable-%}{%-continue-%}{%-endunless-%}
    {%-capture name-%}{{table_name}}-header_{{header_kv[0]|handleize}}{%-endcapture-%}
    <input type="radio" name="sort" id="sort-by-{{name}}" checked="checked" />
  {%-endfor-%}
  <input type="radio" name="sort-order" id="sort-descending-{{table_name}}" checked="checked" />
  <input type="radio" name="sort-order" id="sort-ascending-{{table_name}}" />
  <table class="table">
    <thead class="table-head">
      <tr class="table-row" style="text-align: center;">
        {%-for header_kv in table_data.headers -%}
          {%-assign header = header_kv[1]-%}
          {%-if header.hidden-%}{%-continue-%}{%-endif-%}
          {%-capture name-%}{{table_name}}-header_{{header_kv[0]|handleize}}{%-endcapture-%}
          <th class="table-cell" style="text-align: center;">
            <label class="table-sorter" for="sort-by-{{name}}">
              {{header.name}}
            </label>
            <label class="table-orderer" for="sort-ascending-{{table_name}}"></label>
            <label class="table-orderer" for="sort-descending-{{table_name}}"></label>
          </th>
        {%-endfor-%}
      </tr>
    </thead>
    <tbody class="table-body">
      {%-for row in table_data.rows-%}
        {%-capture row_style-%}
          {%-for item_kv in row-%}
            {%-assign item_name = item_kv[0]-%}
            {%-assign header = table_data.headers[item_name]-%}
            {%-if header.hidden-%}{%-continue-%}{%-endif-%}
            {%-unless header.sortable-%}{%-continue-%}{%-endunless-%}
            {%-capture order_by -%}
              {% case header.type %}
              {% when 'value' %}
                {{item_kv[1]}}
              {% when 'date' %}
                {{item_kv[1] | date: "%s" }}
              {% else %}
                0
              {% endcase %}
            {%-endcapture-%}
            {%-capture name-%}{{table_name}}-header_{{item_name|handleize}}{%-endcapture-%}
            --order-by-{{name}}: {{order_by}};
          {%-endfor-%}
        {%-endcapture-%}
        <tr class="table-row" style="{{row_style}}">
          {%-for item_kv in row-%}
            {%-assign header_key = item_kv[0]-%}
            {%-assign header = table_data.headers[header_key]-%}
            {%-if header.hidden-%}{%-continue-%}{%-endif-%}
            {%-capture name-%}{{table_name}}-header_{{header_key|handleize}}{%-endcapture-%}
            <td class="table-cell table-col-{{name}}">{{item_kv[1]}}</td>
          {%-endfor-%}
        </tr>
      {%-endfor-%}
    </tbody>
  </table>
</div>


More Examples

Example Table Duplicates

This table is here to show that the same table doesn’t confuse the CSS sorting of the other table. However sorting one table does remove focus from the other table column header. This could probably be fixed using some CSS magic, however CSS is not my strong suit.

"Conditions for CSS Variables"2016-10-2110368
Controlling the Specificity2016-12-212431
Counters and Stones2018-01-044463
Flexible Overflow2017-11-286585
Keyboard-Only Focus2017-06-274597
Label-to-Input States2017-05-312829

Duplicate Table

"Conditions for CSS Variables"2016-10-2110368
Controlling the Specificity2016-12-212431
Counters and Stones2018-01-044463
Flexible Overflow2017-11-286585
Keyboard-Only Focus2017-06-274597
Label-to-Input States2017-05-312829


Table of Chemical Elements

This is more of a stress test for the table sorting using CSS. Note that unfortunately, the CSS does not sort the scientific notation values properly (see Abundance column).

1HHydrogen8.988e-0514.0114.3041400
2HeHelium0.00017855.1930.008
3LiLithium0.534453.693.58220
4BeBeryllium1.8515601.8252.8
5BBoron2.3423491.02610
6CCarbon2.267>4000 (pressure dependent)0.709200
7NNitrogen0.001250663.151.0419
8OOxygen0.00142954.360.918461000
9FFluorine0.00169653.530.824585
10NeNeon0.000899924.561.030.005
11NaSodium0.971370.871.22823600
12MgMagnesium1.7389231.02323300
13AlAluminium2.698933.470.89782300
14SiSilicon2.329616870.705282000
15PPhosphorus1.82317.30.7691050
16SSulfur2.067388.360.71350
17ClChlorine0.003214171.60.479145
18ArArgon0.001783783.80.523.5
19KPotassium0.862336.530.75720900
20CaCalcium1.5411150.64741500
21ScScandium2.98918140.56822
22TiTitanium4.5419410.5235650
23VVanadium6.1121830.489120
24CrChromium7.1521800.449102
25MnManganese7.4415190.479950
26FeIron7.87418110.44956300
27CoCobalt8.8617680.42125
28NiNickel8.91217280.44484
29CuCopper8.961357.770.38560
30ZnZinc7.134692.880.38870
31GaGallium5.907302.91460.37119
32GeGermanium5.3231211.40.321.5
33AsArsenic5.77610900.3291.8
34SeSelenium4.8094530.3210.05
35BrBromine3.122265.80.4742.4
36KrKrypton0.003733115.790.2481e−4
37RbRubidium1.532312.460.36390
38SrStrontium2.6410500.301370
39YYttrium4.46917990.29833
40ZrZirconium6.50621280.278165
41NbNiobium8.5727500.26520
42MoMolybdenum10.2228960.2511.2
43TcTechnetium11.524303e−9
44RuRuthenium12.3726070.2380.001
45RhRhodium12.4122370.2430.001
46PdPalladium12.021828.050.2440.015
47AgSilver10.5011234.930.2350.075
48CdCadmium8.69594.220.2320.159
49InIndium7.31429.750.2330.25
50SnTin7.287505.080.2282.3
51SbAntimony6.685903.780.2070.2
52TeTellurium6.232722.660.2020.001
53IIodine4.93386.850.2140.45
54XeXenon0.005887161.40.1583e−5
55CsCaesium1.873301.590.2423
56BaBarium3.59410000.204425
57LaLanthanum6.14511930.19539
58CeCerium6.7710680.19266.5
59PrPraseodymium6.77312080.1939.2
60NdNeodymium7.00712970.1941.5
61PmPromethium7.2613152e−19
62SmSamarium7.5213450.1977.05
63EuEuropium5.24310990.1822
64GdGadolinium7.89515850.2366.2
65TbTerbium8.22916290.1821.2
66DyDysprosium8.5516800.175.2
67HoHolmium8.79517340.1651.3
68ErErbium9.06618020.1683.5
69TmThulium9.32118180.160.52
70YbYtterbium6.96510970.1553.2
71LuLutetium9.8419250.1540.8
72HfHafnium13.3125060.1443
73TaTantalum16.65432900.142
74WTungsten19.2536950.1321.3
75ReRhenium21.0234590.1377e−4
76OsOsmium22.5933060.130.002
77IrIridium22.5627190.1310.001
78PtPlatinum21.462041.40.1330.005
79AuGold19.2821337.330.1290.004
80HgMercury13.5336234.430.140.085
81TlThallium11.855770.1290.85
82PbLead11.342600.610.12914
83BiBismuth9.807544.70.1220.009
84PoPolonium9.325272e−10
85AtAstatine75753e−20
86RnRadon0.009732020.0944e−13
87FrFrancium1.872811e−18
88RaRadium5.59730.0949e−7
89AcActinium10.0713230.125.5e−10
90ThThorium11.7221150.1139.6
91PaProtactinium15.3718411.4e−6
92UUranium18.951405.30.1162.7
93NpNeptunium20.459173e−12
94PuPlutonium19.85912.53e−11
95AmAmericium13.6914490
96CmCurium13.5116130
97BkBerkelium14.7912590
98CfCalifornium15.111730
99EsEinsteinium8.8411330
100FmFermium9.711250
101MdMendelevium10.311000
102falseNobelium9.911000
103LrLawrencium15.619000
104RfRutherfordium23.224000
105DbDubnium29.30
106SgSeaborgium35.00
107BhBohrium37.10
108HsHassium40.70
109MtMeitnerium37.40
110DsDarmstadtium34.80
111RgRoentgenium28.70
112CnCopernicium14.02830
113NhNihonium167000
114FlFlerovium9.9282000
115McMoscovium13.57000
116LvLivermorium12.97000
117TsTennessine7.27000
118OgOganesson73250