chart bar-chart line-chart dual-axis chart-js analytics ad-performance dual axis bar line chart impressions percentage two scales dual y axis chart two y axes chart bar and line different scales
Dual Y-Axis Chart
Fetch pattern JSON:
curl https://webspire.de/patterns/chart/dual-axis.json dual-axis.html
<section class="ws-chart bg-[var(--ws-chart-card-bg)] py-10">
<div class="mx-auto max-w-2xl px-6">
<div class="overflow-hidden rounded-2xl border border-[var(--ws-chart-card-border)] bg-[var(--ws-chart-card-bg)] p-6 shadow-sm">
<div class="mb-5 flex items-start justify-between">
<div>
<p class="text-xs font-semibold uppercase tracking-widest text-[var(--ws-chart-card-text-soft)]">Ad Performance</p>
<h2 class="text-lg font-bold text-[var(--ws-chart-card-text)]">Impressions & Top Rate</h2>
</div>
<div class="flex items-center gap-4 text-xs text-[var(--ws-chart-card-text-soft)]">
<span class="flex items-center gap-1.5"><span class="inline-block h-2.5 w-2.5 rounded-sm bg-indigo-300"></span>Impressions</span>
<span class="flex items-center gap-1.5"><span class="inline-block h-0.5 w-4 bg-teal-400"></span>Top %</span>
</div>
</div>
<!-- Dual-axis layout: left y-label | chart | right y-label -->
<div class="flex gap-2" role="img" aria-label="Dual axis chart for impressions (left) and top rate % (right)">
<!-- Left Y axis: impressions -->
<div class="flex shrink-0 flex-col justify-between pb-5 text-right text-[10px] text-indigo-500">
<span>3.5K</span>
<span>2.5K</span>
<span>1.5K</span>
<span>0</span>
</div>
<!-- Chart area -->
<div class="relative min-w-0 flex-1">
<div class="flex h-44 items-end gap-2">
<div class="flex flex-1 flex-col items-center gap-1.5">
<div class="w-full rounded-t-md bg-indigo-200" style="height:62%"></div>
<span class="text-xs text-[var(--ws-chart-card-text-soft)]">Mon</span>
</div>
<div class="flex flex-1 flex-col items-center gap-1.5">
<div class="w-full rounded-t-md bg-indigo-200" style="height:68%"></div>
<span class="text-xs text-[var(--ws-chart-card-text-soft)]">Tue</span>
</div>
<div class="flex flex-1 flex-col items-center gap-1.5">
<div class="w-full rounded-t-md bg-indigo-200" style="height:74%"></div>
<span class="text-xs text-[var(--ws-chart-card-text-soft)]">Wed</span>
</div>
<div class="flex flex-1 flex-col items-center gap-1.5">
<div class="w-full rounded-t-md bg-indigo-200" style="height:100%"></div>
<span class="text-xs text-[var(--ws-chart-card-text-soft)]">Thu</span>
</div>
<div class="flex flex-1 flex-col items-center gap-1.5">
<div class="w-full rounded-t-md bg-indigo-200" style="height:69%"></div>
<span class="text-xs text-[var(--ws-chart-card-text-soft)]">Fri</span>
</div>
<div class="flex flex-1 flex-col items-center gap-1.5">
<div class="w-full rounded-t-md bg-indigo-200" style="height:58%"></div>
<span class="text-xs text-[var(--ws-chart-card-text-soft)]">Sat</span>
</div>
<div class="flex flex-1 flex-col items-center gap-1.5">
<div class="w-full rounded-t-md bg-indigo-200" style="height:29%"></div>
<span class="text-xs text-[var(--ws-chart-card-text-soft)]">Sun</span>
</div>
</div>
<!-- SVG teal line: % data [1.5,2.0,0.5,3.0,1.2,4.0,3.4] / max 4.0 -->
<!-- y = 176*(1 - v/4): 110, 88, 154, 44, 123, 0, 26 -->
<svg class="pointer-events-none absolute inset-x-0 top-0" style="height:calc(100% - 1.375rem)" viewBox="0 0 700 176" preserveAspectRatio="none" aria-hidden="true">
<polyline
points="50,110 150,88 250,154 350,44 450,123 550,0 650,26"
fill="none"
stroke="#14b8a6"
stroke-width="2.5"
stroke-linecap="round"
stroke-linejoin="round"
vector-effect="non-scaling-stroke"
/>
<circle cx="50" cy="110" r="3.5" fill="#14b8a6" vector-effect="non-scaling-stroke"/>
<circle cx="150" cy="88" r="3.5" fill="#14b8a6" vector-effect="non-scaling-stroke"/>
<circle cx="250" cy="154" r="3.5" fill="#14b8a6" vector-effect="non-scaling-stroke"/>
<circle cx="350" cy="44" r="3.5" fill="#14b8a6" vector-effect="non-scaling-stroke"/>
<circle cx="450" cy="123" r="3.5" fill="#14b8a6" vector-effect="non-scaling-stroke"/>
<circle cx="550" cy="0" r="3.5" fill="#14b8a6" vector-effect="non-scaling-stroke"/>
<circle cx="650" cy="26" r="3.5" fill="#14b8a6" vector-effect="non-scaling-stroke"/>
</svg>
</div>
<!-- Right Y axis: % -->
<div class="flex shrink-0 flex-col justify-between pb-5 text-[10px] text-teal-500">
<span>4%</span>
<span>3%</span>
<span>2%</span>
<span>1%</span>
</div>
</div>
</div>
</div>
</section>
Details
Responsive Tailwind Only SSR Safe Copy & Paste
Stable Published
chartbar-chartline-chartdual-axischart-jsanalyticsad-performance
Bars bound to the left Y axis (impressions, indigo) and a line bound to the right Y axis (absolute top %, teal). The right grid is hidden to avoid visual noise — only the left grid lines show. Tick colors match their respective dataset.