From 6b742c459266b18e2b375b35205ce8a6c02f0452 Mon Sep 17 00:00:00 2001 From: Bradley Taunt Date: Thu, 6 Jun 2024 08:05:12 -0400 Subject: Initial commit --- posts/flexbox-bar-graphs.md | 304 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 posts/flexbox-bar-graphs.md (limited to 'posts/flexbox-bar-graphs.md') 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, Flexbox Bar Graphs, 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: + +
+ Flexbox Bar Graph +
The flexbox bar graph in desktop view (direct link to image)
+
+ +And this is how it will look on smaller devices: + +
+ Flexbox Bar Graph Table +
The flexbox bar graph on mobile devices (direct link to image)
+
+ +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! + + + + + + + + + + + + + + + + + + + + + +
Web Performance Results
Test PerformedBeforeAfterDifference
Initial Load Time + + +

4.7

+
+ +

2.7

+
+ +

2

+
+ + +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 Flexbox Bar Graph repo, I've also included the ability to display these bar graphs horizontally, like so: + +
+ Flexbox Bar Graph Horizontal +
The flexbox bar graph in the horizontal layout (direct link to image)
+
+ +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: https://github.com/bradleytaunt/flexbox-bar-graphs +- Live Demo: https://flexbox-bar-graphs.netlify.app/ + -- cgit v1.2.3-54-g00ecf