Skip to content

CSS file for making railroad diagrams using simple minimal html markup. https://daniel-abrecht.github.io/railroad-css/

License

Notifications You must be signed in to change notification settings

Daniel-Abrecht/railroad-css

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 

Repository files navigation

<!doctype html>
<html class="rr-root">
  <head>
    <meta charset="utf-8" />
    <link rel="stylesheet" type="text/css" href="css/railroad.css" />
    <style>
body {
  max-width: 60em;
  margin: auto;
  margin-bottom: 5em;
}

/* I'm pretty sure this tag existed at some point but was removed for some reason. */
nowrap {
  white-space: nowrap;
  font-family: monospace;
}

.m pre {
displaz: block;
  margin: 0;
  padding: 0;
  line-height: 1.3;
}

tr > td:first-child {
  white-space: nowrap;
}

.tabs {
  margin: 1em 0;
}

.tabs > input[type="radio"], .tabs > div > * {
  display: none;
}

.tabs > input[type="radio"], .tabs > div {
  border: 1px solid;
  padding: 1em;
}

.tabs > nav > label {
  position: relative;
  top: 1px;
  margin-top: -1px;
  background-color: var(--rr-bgcolor);
  display: inline-block;
  padding: 0.5em;
  border: 1px solid #999;
  border-bottom-color: var(--rr-color);
  color: var(--rr-color-rule-ref);
  cursor: pointer;
}

.tabs > input[type="radio"]:nth-of-type(1):checked ~ div > :nth-child(1),
.tabs > input[type="radio"]:nth-of-type(2):checked ~ div > :nth-child(2),
.tabs > input[type="radio"]:nth-of-type(3):checked ~ div > :nth-child(3),
.tabs > input[type="radio"]:nth-of-type(4):checked ~ div > :nth-child(4),
.tabs > input[type="radio"]:nth-of-type(5):checked ~ div > :nth-child(5),
.tabs > input[type="radio"]:nth-of-type(6):checked ~ div > :nth-child(6) {
  display: unset;
}

.tabs > input[type="radio"]:nth-of-type(1):checked ~ nav > label:nth-child(1),
.tabs > input[type="radio"]:nth-of-type(2):checked ~ nav > label:nth-child(2),
.tabs > input[type="radio"]:nth-of-type(3):checked ~ nav > label:nth-child(3),
.tabs > input[type="radio"]:nth-of-type(4):checked ~ nav > label:nth-child(4),
.tabs > input[type="radio"]:nth-of-type(5):checked ~ nav > label:nth-child(5),
.tabs > input[type="radio"]:nth-of-type(6):checked ~ nav > label:nth-child(6) {
  border-color: var(--rr-color);
  border-bottom-color: var(--rr-bgcolor);
  color: var(--rr-color);
  cursor: unset;
}

:root { --hover-color: red; }
@media (prefers-color-scheme: dark) { :root { --hover-color: #F80; } }

.m pre {
  color: var(--rr-color);
}

.ex1:hover ~ p .t1,
.ex2:hover ~ p .t2,
.ex3:hover ~ p .t3,
.ex4:hover ~ p .t4,
.ex5:hover ~ p .t5,
.ex6:hover ~ p .t6,
.ex7:hover ~ p .t7,
.ex8:hover ~ p .t8,
.ex9:hover ~ p .t9,
.exA:hover ~ p .tA,
.exB:hover ~ p .tB,
.exC:hover ~ p .tC,
.exD:hover ~ p .tD,
.exE:hover ~ p .tE {
  --rr-color: var(--hover-color);
}

:root:has(.ex1:hover) .ex1, :root:has(.ex2:hover) .ex2, :root:has(.ex3:hover) .ex3, :root:has(.ex4:hover) .ex4,
:root:has(.ex5:hover) .ex5, :root:has(.ex6:hover) .ex6, :root:has(.ex7:hover) .ex7, :root:has(.ex8:hover) .ex8,
:root:has(.ex9:hover) .ex9, :root:has(.exA:hover) .exA, :root:has(.exB:hover) .exB, :root:has(.exC:hover) .exC,
:root:has(.exD:hover) .exD, :root:has(.exE:hover) .exE,
:root:has(.t1:hover):not(:has(.t1 > :hover)) .ex1, :root:has(.t2:hover):not(:has(.t2 > :hover)) .ex2,
:root:has(.t3:hover):not(:has(.t3 > :hover)) .ex3, :root:has(.t4:hover):not(:has(.t4 > :hover)) .ex4,
:root:has(.t5:hover):not(:has(.t5 > :hover)) .ex5, :root:has(.t6:hover):not(:has(.t6 > :hover)) .ex6,
:root:has(.t7:hover):not(:has(.t7 > :hover)) .ex7, :root:has(.t8:hover):not(:has(.t8 > :hover)) .ex8,
:root:has(.t9:hover):not(:has(.t9 > :hover)) .ex9, :root:has(.tA:hover):not(:has(.tA > :hover)) .exA,
:root:has(.tB:hover):not(:has(.tB > :hover)) .exB, :root:has(.tC:hover):not(:has(.tC > :hover)) .exC,
:root:has(.tD:hover):not(:has(.tD > :hover)) .exD, :root:has(.tE:hover):not(:has(.tE > :hover)) .exE,
.t1:hover:not(:has(>:hover)), .t2:hover:not(:has(>:hover)),
.t3:hover:not(:has(>:hover)), .t4:hover:not(:has(>:hover)),
.t5:hover:not(:has(>:hover)), .t6:hover:not(:has(>:hover)),
.t7:hover:not(:has(>:hover)), .t8:hover:not(:has(>:hover)),
.t9:hover:not(:has(>:hover)), .tA:hover:not(:has(>:hover)),
.tB:hover:not(:has(>:hover)), .tC:hover:not(:has(>:hover)),
.tD:hover:not(:has(>:hover)), .tE:hover:not(:has(>:hover))
{
  --rr-color: var(--hover-color);
}

tr:empty {
  height: 1.2em;
}

    </style>
  </head>
  <body>
<h1>Railroad CSS</h1>
This is still a work in progress.

<h2>Tags</h2>
<table cellspacing="10">
  <tr><td>&lt;rr-rr></td><td>Every railroad diagram must be inside this tag, and it must immediatly contain an &lt;rr-a> &lt;rr-o> tag. This tag shouldn't be nested.</td></tr>
  <tr><td>&lt;rr-a></td><td>A "serial" / "and" railroad part. The containing parts are one after another.</td></tr>
  <tr><td>&lt;rr-o></td><td>A "parallel" / "or" railroad part. The containing parts are stacked, the line goes to and from all of them.</td></tr>
  <tr><td>&lt;rr-t></td><td>Meant for Terminals (sequences of characters). Shouldn't contain other railroad parts.</td></tr>
  <tr><td>&lt;rr-c></td><td>Meant for character lists. Shouldn't contain other railroad parts.</td></tr>
  <tr><td>&lt;a></td><td>Meant for referencing other rules. They're essentially just links, so the href="#rule" attribute can be used as normal.</td></tr>
</table>

<h2>Attribute &amp; classes</h2>
<table cellspacing="10">
  <tr><td>data-min</td><td>A number. Minimum amount of repetitions, can be 0. It won't actually repeat anything. It'll draw an optional line if 0, and a loop line if > 1. The number isn't indicated yet.</td></tr>
  <tr><td>data-max</td><td>A number or "inf". Maximum amount of repetitions, shouldn't be 0. It won't actually repeat anything. It'll draw a loop line if > 1. The number isn't indicated yet.</td></tr>
  <tr><td>class="opt"</td><td>Just shows the optional line.</td></tr>
</table>


<div class="m">
  <h2>Example: Number</h2>

  <p>Hover an item using the mouse to highlight a part of the railroad.</p>

  <pre>&lt;rr-rr></pre>
  <pre class="ex1">  &lt;rr-a></pre>
  <pre class="ex2">    &lt;rr-t data-min="0">"-"&lt;/rr-t></pre>
  <pre class="ex3">    &lt;rr-o></pre>
  <pre class="ex4">      &lt;rr-a></pre>
  <pre class="ex5">        &lt;rr-c>1-9&lt;/rr-c></pre>
  <pre class="ex6">        &lt;rr-c data-min="0" data-max="inf">0-9&lt;/rr-c></pre>
  <pre class="ex4">      &lt;/rr-a></pre>
  <pre class="ex7">      &lt;rr-t>"0"&lt;/rr-t></pre>
  <pre class="ex3">    &lt;/rr-o></pre>
  <pre class="ex8">    &lt;rr-a data-min="0"></pre>
  <pre class="ex9">      &lt;rr-t>"."&lt;/rr-t></pre>
  <pre class="exA">      &lt;rr-c data-max="inf">0-9&lt;/rr-c></pre>
  <pre class="ex8">    &lt;/rr-a></pre>
  <pre class="exB">    &lt;rr-a data-min="0"></pre>
  <pre class="exC">      &lt;rr-c>Ee&lt;/rr-c></pre>
  <pre class="exD">      &lt;rr-c data-min="0">+-&lt;/rr-c></pre>
  <pre class="exE">      &lt;rr-c data-max="inf">0-9&lt;/rr-c></pre>
  <pre class="exB">    &lt;/rr-a></pre>
  <pre class="ex1">  &lt;/rr-a></pre>
  <pre>&lt;/rr-rr></pre>

  <p style="text-align: center;"><rr-rr>
    <rr-a class="t1">
      <rr-t class="t2" data-min="0">"-"</rr-t>
      <rr-o class="t3">
        <rr-a class="t4">
          <rr-c class="t5">1-9</rr-c>
          <rr-c class="t6" data-min="0" data-max="inf">0-9</rr-c>
        </rr-a>
        <rr-t class="t7">"0"</rr-t>
      </rr-o>
      <rr-a class="t8" data-min="0">
        <rr-t class="t9">"."</rr-t>
        <rr-c class="tA" data-max="inf">0-9</rr-c>
      </rr-a>
      <rr-a class="tB" data-min="0">
        <rr-c class="tC">Ee</rr-c>
        <rr-c class="tD" data-min="0">+-</rr-c>
        <rr-c class="tE" data-max="inf">0-9</rr-c>
      </rr-a>
    </rr-a>
  </rr-rr></p>

</div>

<div>
  <h2>Table with Diagrams</h2>
  There are also a few tags for putting the syntax disgrams in a table &amp; to make sure the names on the left side align nicely with the diagrams on the right.
  Those tags are &lt;rr-root> for the table, &lt;rr-r> for the table row, and &lt;rr-n> for the diagram names.

  <div class="tabs">
    <input type="radio" name="tabs-1" id="tabs-1-1" autocomplete="off" checked />
    <input type="radio" name="tabs-1" id="tabs-1-2" autocomplete="off" />

    <nav>
      <label for="tabs-1-1">Diagram</label>
      <label for="tabs-1-2">Code</label>
    </nav>

    <div>
      <div><rr-root style="font-size: 1.4em;">
        <rr-r id="rr-number">
          <rr-n>Number</rr-n>
          <rr-rr>
            <rr-a>
              <a href="#rr-integer">Integer</a>
              <a href="#rr-fraction" data-min="0">Fraction</a>
              <a href="#rr-exponent" data-min="0">Exponent</a>
            </rr-a>
          </rr-rr>
        </rr-r>
        <rr-r id="rr-integer">
          <rr-n>Integer</rr-n>
          <rr-rr>
            <rr-a>
              <rr-t data-min="0">"-"</rr-t>
              <rr-o>
                <rr-a>
                  <rr-c>1-9</rr-c>
                  <rr-c data-min="0" data-max="inf">0-9</rr-c>
                </rr-a>
                <rr-t>"0"</rr-t>
              </rr-o>
            </rr-a>
          </rr-rr>
        </rr-r>
        <rr-r id="rr-fraction">
          <rr-n>Fraction</rr-n>
          <rr-rr>
            <rr-a>
              <rr-t>"."</rr-t>
              <rr-c data-max="inf">0-9</rr-c>
            </rr-a>
          </rr-rr>
        </rr-r>
        <rr-r id="rr-exponent">
          <rr-n>Exponent</rr-n>
          <rr-rr>
            <rr-a>
              <rr-c>Ee</rr-c>
              <rr-c data-min="0">+-</rr-c>
              <rr-c data-max="inf">0-9</rr-c>
            </rr-a>
          </rr-rr>
        </rr-r>
      </rr-root></div>

<pre>&lt;rr-root>

  &lt;rr-r id="rr-number">
    &lt;rr-n>Number&lt;/rr-n>
    &lt;rr-rr>
      &lt;rr-a>
        &lt;a href="#rr-integer">Integer&lt;/a>
        &lt;a href="#rr-fraction" data-min="0">Fraction&lt;/a>
        &lt;a href="#rr-exponent" data-min="0">Exponent&lt;/a>
      &lt;/rr-a>
    &lt;/rr-rr>
  &lt;/rr-r>

  &lt;rr-r id="rr-integer">
    &lt;rr-n>Integer&lt;/rr-n>
    &lt;rr-rr>
      &lt;rr-a>
        &lt;rr-t data-min="0">"-"&lt;/rr-t>
        &lt;rr-o>
          &lt;rr-a>
            &lt;rr-c>1-9&lt;/rr-c>
            &lt;rr-c data-min="0" data-max="inf">0-9&lt;/rr-c>
          &lt;/rr-a>
          &lt;rr-t>"0"&lt;/rr-t>
        &lt;/rr-o>
      &lt;/rr-a>
    &lt;/rr-rr>
  &lt;/rr-r>

  &lt;rr-r id="rr-fraction">
    &lt;rr-n>Fraction&lt;/rr-n>
    &lt;rr-rr>
      &lt;rr-a>
        &lt;rr-t>"."&lt;/rr-t>
        &lt;rr-c data-max="inf">0-9&lt;/rr-c>
      &lt;/rr-a>
    &lt;/rr-rr>
  &lt;/rr-r>

  &lt;rr-r id="rr-exponent">
    &lt;rr-n>Exponent&lt;/rr-n>
    &lt;rr-rr>
      &lt;rr-a>
        &lt;rr-c>Ee&lt;/rr-c>
        &lt;rr-c data-min="0">+-&lt;/rr-c>
        &lt;rr-c data-max="inf">0-9&lt;/rr-c>
      &lt;/rr-a>
    &lt;/rr-rr>
  &lt;/rr-r>

&lt;/rr-root></pre>
    </div>
  </div>

<div>
  <h2>Customization</h2>
  <h3>Dark Mode</h3>
  Per default, the diagram has a dark mode used depending on a media query which checks for <nowrap>"prefers-color-scheme:dark"</nowrap>.
  The dark mode can be disabled by setting the <nowrap>"rr-no-dark"</nowrap> class on the &lt;html> tag.

  <h3>Size</h3>
  All lines and paddings are specified in "em". Changing the font size will scale the whole diagram.

  <h3>Custom CSS Variables</h3>
  <table cellspacing="10">
    <tr><td>--rr-color-terminal</td><td>Color for &lt;rr-t> elements.<td></tr>
    <tr><td>--rr-color-rule-ref</td><td>Color for &lt;a> elements.<td></tr>
    <tr><td>--rr-color-byterange</td><td>Color for &lt;rr-c> elements.<td></tr>
    <tr><td>--rr-color</td><td>The color of the railroad line</td></tr>
    <tr><td>--rr-bgcolor</td><td>The background color</td></tr>
    <tr></tr>
    <tr><td>--rr-line-size</td><td>The size / thickness of the railroad line</td></tr>
    <tr><td>--rr-radius</td><td>The radius where the railroad line bends</td></tr>
    <tr><td>--rr-line-height</td><td>This sets the line-height property. It's used whenever the height of some text containign elements has to be calculated.</td></tr>
    <tr><td>--rr-spacing</td><td>Default for all margins</td></tr>
    <tr><td>--rr-spacing-y</td><td>Default for vertical margins</td></tr>
    <tr></tr>
    <tr><td>--rr-t-border-width</td><td>All boxes with a border have this width</td></tr>
    <tr><td>--rr-t-padding-vertical</td><td>The vertical padding of all the boxes</td></tr>
    <tr><td>--rr-t-padding-horizontal</td><td>The horizontal padding of all the boxes</td></tr>
    <tr><td>--rr-lr-loop-inner-margin</td><td>If there is a loop line, this adds extra horizontal space on the inside.</td></tr>
    <tr><td>--rr-lr-loop-outer-margin</td><td>If there is a loop line, this adds extra horizontal space on the outside.</td></tr>
    <tr><td>--rr-lr-alt-margin</td><td>Extra spacing for every text box.</td></tr>
    <tr></tr>
    <tr><td>--rr-opt-line-spacing-y</td><td>If there is an optional line, this is the distance to that line.</td></tr>
    <tr><td>--rr-loop-line-spacing-y</td><td>If there is a loop line, this is the distance to that line.</td></tr>
    <tr><td>--rr-line-top-displacement</td><td>Where the line meets the box, the default is in the middle.</td></tr>
  </table>
</div>

</div>

  </body>
</html>

About

CSS file for making railroad diagrams using simple minimal html markup. https://daniel-abrecht.github.io/railroad-css/

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published