@PaulOB ,
Hi there. Sorry for the delay. Have spent the last two days looking at your latest code.
After tweaking things to my liking, I would say that this responsive bar chart is about 95% doneā¦
The only nagging problem I have with my latest code is that the spacing of the Y-axis marker numbers is dodgy.
Maybe some context will help my concernā¦
My end goal is to create a PHP function - using this HTML/CSS code - where I can grab data from my database, feed it to the PHP function, and have it generate a really cool - and responsive - bar chart.
In order to make it worth the effort, my bar chart needs to be 100% responsive to dynamic data.
For one bar chart, the Y-axis might be a ācountā going from 1 to 10 (e.g. āBicycles Ownedā) with increments of ā1ā.
For another bar chart, the Y-axis might be ātotalā going from $1 to $125 (e.g. āWeekly Meal Costsā), with increments of $25.
And for another bar chart, the Y-axis might be ātotalā going from $1 to $1,800 (e.g. āMonthly Salesā) with increments of $100.
The point being, is that I really need a way to āsynch upā/āanchorā the Y-axis numbers with the gridlines, because if the numbers ādriftā from the gridlines, then the Y-axis numbers are useless. 
(Iām thinking that if I can create different CSS styles for splitting the chart up into either 4, 5, 6, 7, 8, 9, 10 increments, then that would cover all future scenarios. Since I can use a percentage on the gridlines, Iām okay there, but it is aligning the numbers up to different scenarios that has me worried, if that makes sense?!)
Below is my latest code - which incorporates your really neat Y-axis labels/number-scale - but is cleaned up some and which has the final look that I am afterā¦
<!DOCTYPE HTML>
<html lang="en">
<!-- ************************* HTML HEAD ********************************* -->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1">
<title>sp_bar-chart_v07.html</title>
<!-- CSS STYLES -->
<style media="screen">
/**************************************************************************/
/* GENERIC */
/**************************************************************************/
* {
margin: 0;
padding: 0;
}
*,
*:before,
*:after {
box-sizing: border-box;
}
body{
font-family: Helvetica, Arial, Sans-Serif;
font-weight: normal;
line-height: 1.4em;
font-size: 0.9em;
color: #000;
}
.chart .jan span{
background: green;
}
.chart .feb span{
background: orange;
}
.chart .mar span{
background: teal;
}
.chart .apr span{
background: cyan;
}
.chart .may span{
background: lightblue;
}
.chart .jun span{
background: red;
}
.chart .jul span{
background: magenta;
}
.chart .aug span{
background: yellow;
}
.chart .sep span{
background: skyblue;
}
.chart .oct span{
background: gray;
}
.chart .nov span{
background: aquamarine;
}
.chart .dec span{
background: white;
}
/**************************************************************************/
/* DESKTOP (Horizontal) */
/**************************************************************************/
/* TABLE */
.chart{
table-layout: fixed;
width: 90%;
max-width: 1240px;
height: 60vh;
border-collapse: collapse;
margin: auto;
}
/* CAPTION */
caption{
padding: 20px 0 10px 0;
font-size: 1rem;
font-weight: bold;
text-align: center;
line-height: 1.4;
}
caption > small{
display: block;
font-size: 0.8rem;
font-weight: normal;
}
/* THEAD */
.chart thead th{
border-right: 2px solid #000;
}
.chart thead td{
height: 20px;
background: #F9F9F9;
}
/* TFOOT */
.chart tfoot th{
padding: 5px 0 0 0;
vertical-align: top;
font-size: 0.9rem;
font-weight: normal;
background-color: #FFF;
}
.chart tfoot td.x-axis{
padding: 0.4rem 0 0 0;
font-size: 0.9rem;
font-weight: bold;
text-align: center;
}
/* TBODY */
.chart tbody{
background: #F9F9F9;
background-image: linear-gradient(rgba(0,0,0,0.1) 1px, transparent 1px);
background-size: 98% 10%;
}
/* TD */
.chart tbody td{
vertical-align: bottom;
height: 100%;
padding: 0 10px;
border-bottom: 2px solid #000;
}
/* BARS */
.chart tbody td span{
position: relative;
display: block;
background: #99FFFF;
border-top: 1px solid #000;
border-right: 1px solid #000;
border-bottom: none;
border-left: 1px solid #000;
box-shadow: 5px 0px 5px rgba(0, 0, 0, 0.3);
}
/* BAR-VALUES */
.chart tbody td span b{
position: absolute;
display: block;
bottom: 100%;
left: 0;
right: 0;
text-align: center;
font-weight: normal;
}
/* Y-AXIS LABEL + MARKERS */
.chart tbody th.y-axis{
position: relative;
border-right: 2px solid #000;
background: #FFF;
}
/* Transform Y-axis Label */
.rotate {
position: relative;
-ms-writing-mode: tb-lr;
z-index: 3;
margin: 1rem 1rem 0 0;
font-size: 1rem;
font-weight: bold;
}
@supports (writing-mode: vertical-lr) {
.rotate {
display: inline-block;
writing-mode: vertical-lr;
white-space: nowrap;
transform: rotate(180deg) translateX(20px);
line-height: 0;
}
}
.rotate > small{
font-size: 0.8rem;
font-weight: normal;
}
/* Y-axis Markers */
ol.segments{
position: absolute;
top: -27px; /* LOOK */
bottom: 0;
right: 3px;
margin: 0;
padding: 0;
list-style: none;
font-size: 0.9rem;
font-weight: normal;
display: flex;
flex-direction: column;
transform: translateY(6%); /* LOOK */
}
ol.segments li{
flex: 1 0 0;
}
/**************************************************************************/
/* MOBILE (Vertical) */
/**************************************************************************/
@media screen and (max-width:601px){
/* TABLE */
.mobile-optimised{
display: block;
height: auto;
width: 100%;
overflow-wrap: break-word;
border-spacing: 0;
}
/* CAPTION */
.mobile-optimised caption{
display: block;
padding: 1rem 0;
}
/* THEAD + TFOOT */
.mobile-optimised thead,
.mobile-optimised tfoot{
display: none
}
/* TBODY */
.mobile-optimised tbody,
.mobile-optimised tr{
display: block
}
.mobile-optimised tbody:after,
.mobile-optimised tr:after{
content: "";
display: block;
clear: both;
height: 0;
}
.mobile-optimised tbody{
margin: 0 4rem 2rem 2rem;
border-left: none;
background: #F9F9F9;
}
/* TR */
.mobile-optimised tbody tr{
background-image: linear-gradient(to right, #DDD 1px, transparent 1px);
background-size: 10% 100%;
border-right: 1px solid #DDD;
}
/* TD */
.mobile-optimised tbody td:before{
content: attr(data-th);
display: block;
font-weight: bold;
margin: 0 0 0 5px;
}
.mobile-optimised tbody td{
display: block;
float: left;
height: auto;
width: 100%;
clear: both;
margin: 0;
padding: 1rem 0 0 0;
white-space: nowrap;
border-bottom: none;
border-left: 2px solid #000;
background: transparent;
}
.mobile-optimised tbody td:nth-child(2){
padding: 1.5rem 0 0 0;
}
.mobile-optimised tbody td:last-child{
padding: 1rem 0 1.5rem 0;
}
/* BARS */
.mobile-optimised tbody td span{
position: relative;
height: 25px!important;
line-height: 25px;
border-top: 1px solid #000;
border-right: 1px solid #000;
border-bottom: 1px solid #000;
border-left: none;
box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.3);
}
/* BAR-VALUES */
.mobile-optimised tbody td span b{
position: absolute;
left: 100%;
top: 0;
right: auto;
bottom: 0;
padding: 0 0 0 5px;
}
/* Y-AXIS LABEL + MARKERS */
.mobile-optimised tbody th.y-axis{
display: block;
width: calc(100% + 2px); /* hide right border */
padding-bottom: 1.4rem;
border-right: none;
border-bottom: 2px solid #000;
border-left: none;
background-color: #FFF;
}
/* Y-axis Label */
.mobile-optimised tbody .rotate{
display: block;
-ms-writing-mode: initial;
writing-mode: initial;
white-space: nowrap;
transform: none;
margin: 0;
line-height: normal;
font-size: 0.9rem;
}
/* Y-axis Markers */
.mobile-optimised tbody ol.segments{
position: absolute;
top: auto;
bottom: 0;
right: 0;
left: -37px; /* LOOK */
font-size: 0.9rem;
flex-direction: row-reverse;
transform: translateX(1rem); /* LOOK */
}
.mobile-optimised tbody ol.segments li{
flex: 1 0 0;
text-align: right;
}
}/* End of MOBILE Styles. */
/* ANIMATION */
.chart span{
opacity: 1;
animation: barchart 2s ease reverse;
}
@keyframes barchart{
to{
height: 0%;
opacity: 0;
}
}
</style>
</head>
<!-- ************************* HTML BODY ********************************* -->
<body>
<table class="chart mobile-optimised">
<caption>
Total Monthly Widget Sales
<small>(1/1 - 12/31/2020)</small>
</caption>
<!-- Used to establish equal column-widths. -->
<thead>
<tr>
<th></th>
<td colspan="12"></td>
</tr>
</thead>
<tbody>
<!-- inline styles used so values can be entered more easily from the backend (php etc). e.g. width and height match the percentage data value. -->
<!-- Note the use of the data-th attributes which are used to display headings for the mobile version. Therefore the Normal heading text must be duplicated in the data-th values as shown below. -->
<tr>
<th class="y-axis">
<div class="rotate">Revenue <small>(US Dollars)</small></div>
<ol class="segments">
<li>$100k</li>
<li></li>
<li>$80k</li>
<li></li>
<li>$60k</li>
<li></li>
<li>$40k</li>
<li></li>
<li>$20k</li>
<li></li>
<li>$0k</li>
</ol>
</th>
<!-- Classes below serve as styling "hooks"... -->
<td style="width:70%" data-th="January" class="jan"><span style="height:70%"><b>$70k</b></span></td>
<td style="width:10%" data-th="February" class="feb"><span style="height:10%"><b>$10k</b></span></td>
<td style="width:20%" data-th="March" class="mar"><span style="height:20%"><b>$20k</b></span></td>
<td style="width:40%" data-th="April" class="apr"><span style="height:40%"><b>$40k</b></span></td>
<td style="width:100%" data-th="May" class="may"><span style="height:100%"><b>$100k</b></span></td>
<td style="width:15%" data-th="June" class="jun"><span style="height:15%"><b>$15k</b></span></td>
<td style="width:60%" data-th="July" class="jul"><span style="height:60%"><b>$60k</b></span></td>
<td style="width:55%" data-th="August" class="aug"><span style="height:55%"><b>$55k</b></span></td>
<td style="width:35%" data-th="September" class="sep"><span style="height:35%"><b>$35k</b></span></td>
<td style="width:90%" data-th="October" class="oct"><span style="height:90%"><b>$90k</b></span></td>
<td style="width:20%" data-th="November" class="nov"><span style="height:20%"><b>$20k</b></span></td>
<td style="width:50%" data-th="December" class="dec"><span style="height:50%"><b>$50k</b></span></td>
</tr>
</tbody>
<tfoot>
<tr>
<th class="empty"></th>
<th scope="col">Jan</th>
<th scope="col">Feb</th>
<th scope="col">Mar</th>
<th scope="col">Apr</th>
<th scope="col">May</th>
<th scope="col">Jun</th>
<th scope="col">Jul</th>
<th scope="col">Aug</th>
<th scope="col">Sep</th>
<th scope="col">Oct</th>
<th scope="col">Nov</th>
<th scope="col">Dec</th>
</tr>
<tr>
<td class="emptyfoot"></td>
<td class="x-axis" colspan="12">Month</td>
</tr>
</tfoot>
</table>
</body>
</html>
(I added āLOOKā comments in my code to draw your attention to where I need help.)
What I have now looks pretty good, but if you change device size, OR we change the number of gridlines, i think my code will fall apart pretty quickā¦
This is frustrating, because I feel like this is so close to being a near-perfect solution, and am hoping that you being a CSS guru, that you can offer some help figuring out how to make this work in any, and all, situations?!
P.S. I like how you changed to using percentages (versus pixels) for the gradient as belowā¦
background-size: 10% 100%;
Using percentages all but guarantees that the gridlines will adapt to however many increments I need, as well as to any device.
If I could apply a similar technique to the Y-axis numbers then they would always synch up/anchor to the gridlines and I would be golden!!
Hope all of this makes sense?
Thanks!
