summaryrefslogtreecommitdiff
path: root/posts/flexbox-bar-graphs.md
diff options
context:
space:
mode:
authorBradley Taunt <brad@bt.ht>2023-11-27 12:25:51 -0500
committerBradley Taunt <brad@bt.ht>2023-11-27 12:25:51 -0500
commit14d227d46a2177a8928333894252d6299f531097 (patch)
treed41d48383d012f53823c9816a820e4e88c572c41 /posts/flexbox-bar-graphs.md
parentf6eed1a8c2f4fbf91fac9edd11e50f5c0ec939a2 (diff)
Trying to render posts all at once
Diffstat (limited to 'posts/flexbox-bar-graphs.md')
-rw-r--r--posts/flexbox-bar-graphs.md304
1 files changed, 304 insertions, 0 deletions
diff --git a/posts/flexbox-bar-graphs.md b/posts/flexbox-bar-graphs.md
new file mode 100644
index 0000000..5862d86
--- /dev/null
+++ b/posts/flexbox-bar-graphs.md
@@ -0,0 +1,304 @@
+# Pure CSS Bar Graphs with Graceful Mobile Fallbacks
+
+2020-12-08
+
+I recently published a new open source project, <a target="_blank" href="https://flexbox-bar-graphs.netlify.app/">Flexbox Bar Graphs</a>, and wanted to share a simple breakdown of how it was built. It isn't anything mind-blowing, but I like the idea of placing bar graphs in a web page with *zero* Javascript.
+
+So in the end, this is what our bar graphs will look like on desktop:
+
+<figure>
+ <img src="/public/images/flexbox-bar-graph-1.webp" alt="Flexbox Bar Graph">
+ <figcaption>The flexbox bar graph in desktop view (<a href="/public/images/flexbox-bar-graph-1.webp">direct link to image</a>)</figcaption>
+</figure>
+
+And this is how it will look on smaller devices:
+
+<figure>
+ <img src="/public/images/flexbox-bar-graph-2.webp" alt="Flexbox Bar Graph Table">
+ <figcaption>The flexbox bar graph on mobile devices (<a href="/public/images/flexbox-bar-graph-2.webp">direct link to image</a>)</figcaption>
+</figure>
+
+Let's get into the details!
+
+## The HTML
+
+The main "secret" of this project is that our graphs are constructed out of HTML *tables*. Now before you freak out - this is perfectly fine and works in our favor quite well.
+
+1. If the user has JS disabled --> they will still see our graphs
+2. If the user has CSS disabled --> they will see a standard data table set
+
+All bases are covered!
+
+
+ <!-- Using a basic table with our custom data-id -->
+ <table data-id="flexbox-bar-graph">
+ <caption>Web Performance Results</caption>
+ <thead>
+ <tr>
+ <th>Test Performed</th>
+ <th>Before</th>
+ <th>After</th>
+ <th>Difference</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <th>Initial Load Time</th>
+ <td>
+ <!--
+ WTF are these CSS variables?
+ See the CSS section below
+ -->
+ <span style="--data-set:4.7/5;"></span>
+ <p>4.7</p>
+ </td>
+ <td>
+ <span style="--data-set:2.7/5;"></span>
+ <p>2.7</p>
+ </td>
+ <td>
+ <span style="--data-set:2/5;"></span>
+ <p>2</p>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+
+
+Nothing crazy is happening here - just your standard HTML table structure. The one main thing to notice is the `--data-set` CSS variable placed inline on each data point. This will be important for our CSS to configure the individual bar graphs properly.
+
+## The CSS
+
+This might look overwhelming if I just dumped the whole CSS file in one big code block, so instead I'm going to break them down into two parts:
+
+1. Baseline styling (mobile)
+2. Desktop styling
+
+### Baseline
+
+Here we target just our table elements with the `data-id` of `flexbox-bar-graph`. This allows us to avoid worrying about adding classes or IDs and also avoids conflicts with other non-graph styled tables in our projects.
+
+The base `:root` element holds all of our bar graph colors. Change these as you see fit!
+
+
+ /* Bar Graph color variables */
+ :root {
+ --bar-color-1: #357EC7;
+ --bar-color-2: #E42217;
+ --bar-color-3: #4CC417;
+ --bar-color-4: #7D0541;
+ --bar-color-5: #FFD801;
+ }
+
+ [data-id="flexbox-bar-graph"] {
+ border-collapse: collapse;
+ margin: 4rem 0 6rem;
+ width: 100%;
+ }
+ [data-id="flexbox-bar-graph"] caption {
+ text-align: left;
+ }
+ [data-id="flexbox-bar-graph"] thead th {
+ text-align: right;
+ }
+ [data-id="flexbox-bar-graph"] thead th:nth-child(1),
+ [data-id="flexbox-bar-graph"] tbody th {
+ text-align: left;
+ }
+ [data-id="flexbox-bar-graph"] tbody th {
+ font-weight: normal;
+ font-style: italic;
+ }
+ [data-id="flexbox-bar-graph"] tbody td {
+ text-align: right;
+ }
+ [data-id="flexbox-bar-graph"] tbody td p {
+ margin: 0;
+ }
+
+
+### Desktop
+
+Now we set your "visual" bar graphs to show at a set width (in this example it is 1000px and above). That way the "default" styling can target the mobile device screen sizes.
+
+- The `thead tr th:nth-child(x):before` elements create the square "legends" beside each individual data point heading
+- The `tbody tr td:nth-of-type(x) span` elements are the bars themselves
+
+
+ @media(min-width: 1000px) {
+ [data-id="flexbox-bar-graph"] {
+ background: transparent;
+ display: block;
+ min-height: 400px;
+ padding: 0;
+ position: relative;
+ width: 100%;
+ }
+
+ [data-id="flexbox-bar-graph"] caption {
+ display: block;
+ font-size: 2rem;
+ text-align: center;
+ width: 100%;
+ }
+
+ [data-id="flexbox-bar-graph"] thead {
+ display: block;
+ margin: 2rem 0 3rem;
+ width: 100%;
+ }
+ [data-id="flexbox-bar-graph"] thead tr {
+ border-bottom: 1px solid lightgrey;
+ display: flex;
+ justify-content: center;
+ padding-bottom: 1rem;
+ }
+
+ [data-id="flexbox-bar-graph"] thead tr th {
+ display: inline-block;
+ margin: 0;
+ padding: 0;
+ position: relative;
+ text-align: right;
+ }
+ [data-id="flexbox-bar-graph"] thead tr th:before {
+ content:'';
+ display: inline-block;
+ height: 10px;
+ margin: 0 0.5rem 0 2rem;
+ position: relative;
+ width: 10px;
+ }
+ [data-id="flexbox-bar-graph"] thead tr th:nth-child(1),
+ [data-id="flexbox-bar-graph"] thead tr th:nth-child(1):before {
+ display: none;
+ }
+ [data-id="flexbox-bar-graph"] thead tr th:nth-child(2):before {
+ background: var(--bar-color-1);
+ }
+ [data-id="flexbox-bar-graph"] thead tr th:nth-child(3):before {
+ background: var(--bar-color-2);
+ }
+ [data-id="flexbox-bar-graph"] thead tr th:nth-child(4):before {
+ background: var(--bar-color-3);
+ }
+ [data-id="flexbox-bar-graph"] thead tr th:nth-child(5):before {
+ background: var(--bar-color-4);
+ }
+ [data-id="flexbox-bar-graph"] thead tr th:nth-child(6):before {
+ background: var(--bar-color-5);
+ }
+
+ [data-id="flexbox-bar-graph"] tbody {
+ display: flex;
+ justify-content: space-between;
+ min-height: 300px;
+ width: 100%;
+ }
+
+ [data-id="flexbox-bar-graph"] tbody tr {
+ display: flex;
+ flex-direction: column-reverse;
+ flex-wrap: wrap;
+ justify-content: flex-end;
+ padding: 0 50px;
+ position: relative;
+ width: 100%;
+ }
+ [data-id="flexbox-bar-graph"] tbody tr th {
+ font-size: 90%;
+ position: absolute;
+ text-align: center;
+ top: 100%;
+ width: calc(100% - 100px);
+ }
+ [data-id="flexbox-bar-graph"] tbody tr td {
+ align-items: center;
+ display: flex;
+ flex-direction: column;
+ height: 95%;
+ justify-content: flex-end;
+ }
+
+ [data-id="flexbox-bar-graph"] tbody tr td span {
+ display: block;
+ height: calc(var(--data-set) * 100%);
+ width: 20px;
+ }
+ [data-id="flexbox-bar-graph"] tbody tr td:nth-of-type(1) span {
+ background: var(--bar-color-1);
+ }
+ [data-id="flexbox-bar-graph"] tbody tr td:nth-of-type(2) span {
+ background: var(--bar-color-2);
+ }
+ [data-id="flexbox-bar-graph"] tbody tr td:nth-of-type(3) span {
+ background: var(--bar-color-3);
+ }
+ [data-id="flexbox-bar-graph"] tbody tr td:nth-of-type(4) span {
+ background: var(--bar-color-4);
+ }
+ [data-id="flexbox-bar-graph"] tbody tr td:nth-of-type(5) span {
+ background: var(--bar-color-5);
+ }
+
+ [data-id="flexbox-bar-graph"] tbody tr td p {
+ font-size: 90%;
+ margin: 0;
+ text-align: center;
+ }
+ }
+
+
+## Bonus Styling
+
+In the <a target="_blank" href="https://github.com/bradleytaunt/flexbox-bar-graphs">Flexbox Bar Graph</a> repo, I've also included the ability to display these bar graphs horizontally, like so:
+
+<figure>
+ <img src="/public/images/flexbox-bar-graph-3.webp" alt="Flexbox Bar Graph Horizontal">
+ <figcaption>The flexbox bar graph in the horizontal layout (<a href="/public/images/flexbox-bar-graph-3.webp">direct link to image</a>)</figcaption>
+</figure>
+
+The change in CSS is actually quite simple to pull this off - you just need to include the `data-layout` attribute on the table itself.
+
+
+ [data-layout="horizontal"] tbody {
+ min-height: auto;
+ }
+
+ [data-layout="horizontal"] tbody tr {
+ flex-direction: column;
+ padding: 0 40px;
+ }
+ [data-layout="horizontal"] tbody tr th {
+ width: calc(100% - 80px);
+ }
+
+ [data-layout="horizontal"] tbody tr th {
+ text-align: left;
+ top: calc(100% + 20px);
+ }
+
+ [data-layout="horizontal"] tbody tr td {
+ flex-direction: row;
+ height: auto;
+ justify-content: start;
+ margin: 10px 0;
+ }
+
+ [data-layout="horizontal"] tbody tr td span {
+ height: 20px;
+ width: calc(var(--data-set) * 100%);
+ }
+
+ [data-layout="horizontal"] tbody tr td p {
+ margin-left: 10px;
+ }
+
+
+## That's All Folks!
+
+That just about sums things up. Feel free to check out the Github repo itself, open any issues you find or fork it for your own!
+
+- Github: <a href="https://github.com/bradleytaunt/flexbox-bar-graphs">https://github.com/bradleytaunt/flexbox-bar-graphs</a>
+- Live Demo: <a href="https://flexbox-bar-graphs.netlify.app/">https://flexbox-bar-graphs.netlify.app/</a>
+