ApexCharts Mixed Bar and Line Chart with Dual Y-Axes — Free Snippet

ApexCharts Mixed Bar and Line Chart with Dual Y-Axes · Charts · Plain HTML, CSS & JS · Live preview

CategoryCharts

What's included

Features

True mixed chart
Column and line series share one plot area via per-series type.
Dual y-axes
Dollars on the left, percentages on the right, bound with seriesName.
Shared tooltip
Both values for a month appear together on hover.
Per-series formatting
Currency and percentage formatting chosen by seriesIndex.
Atomic range switch
updateOptions changes categories and data in a single render.
Rounded columns
borderRadius with borderRadiusApplication: 'end' rounds only the top.
Accessible toggle
Range buttons expose their state with aria-pressed.
Responsive width
The chart fills its card and redraws when the window resizes.

About this UI Snippet

ApexCharts Mixed Bar and Line Chart — Two Units, Two Axes, One Chart

Screenshot of the ApexCharts Mixed Bar and Line Chart with Dual Y-Axes snippet rendered live

Revenue and margin belong on the same chart because they explain each other: a month with record revenue and a sagging margin tells a very different story from a month where both climb. They do not belong on the same axis, though. Revenue is measured in tens of thousands of dollars and margin in percentage points, so plotting both against one scale flattens the margin line into a straight line along the bottom. This snippet gives each series its own axis.

The series type decides the shape, not the chart type

ApexCharts builds a mixed chart when individual series declare their own type. The chart-level type: 'line' is only the default; the revenue series overrides it with type: 'column'. Because of that, stroke.width and markers.size are passed as arrays — [0, 3] means no outline on the columns and a 3px stroke on the line.

seriesName binds each axis to its series

yaxis is an array of two axis objects. Each one names the series it measures with seriesName, and the second sets opposite: true to draw on the right. The margin axis also pins min: 30 and max: 50 so small margin movements are visible instead of being squashed into a 0–100 range. Pinning bounds is a deliberate choice worth questioning in your own data — a range that is too tight exaggerates noise.

One tooltip for both series

tooltip.shared: true with intersect: false shows revenue and margin together when hovering anywhere in a month's column, which is the comparison people actually want. The y.formatter checks seriesIndex so dollars and percentages each get their own formatting.

Updating without a mismatch frame

The 6M/12M toggle calls updateOptions once with the new categories and both series. Calling updateSeries and then a separate x-axis update would briefly render 12 bars against 6 labels.

Reusing it

Swap in any pair of related measures with different units: sessions and conversion rate, orders and average order value, tickets and resolution time.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Paste this snippet into an AI coding assistant like Claude and ask it to explain how per-series type values turn a line chart into a mixed chart, and how seriesName connects each y-axis to the right series. It can also help you adapt the chart: ask it to add a third series such as a revenue target line on the left axis, to annotate the month with the lowest margin, or to load the data from a JSON endpoint and refresh it on an interval. Ask whether the fixed 30–50% margin range is honest for your data, or whether automatic bounds would tell the story better.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a mixed bar and line chart with ApexCharts (loaded from a CDN) using plain HTML, CSS and JavaScript.

Requirements:
- Show twelve months of revenue as columns and gross margin percentage as a smooth line in the same plot area.
- Put revenue on a left y-axis formatted in thousands of dollars and margin on a right y-axis formatted as a percentage, binding each axis to its series by name.
- Use a shared tooltip that shows both values for the hovered month, with currency formatting for revenue and one decimal place for margin.
- Round only the top corners of the columns, hide data labels, and use a light dashed grid.
- Add a 6-month / 12-month toggle that updates the x-axis categories and both series in a single update call, and exposes its state with aria-pressed.
- Keep the chart responsive to its container width.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Source Code

Requires
<div class="amx-wrap">
  <div class="amx-card">
    <div class="amx-head">
      <div>
        <div class="amx-title">Revenue vs Gross Margin</div>
        <div class="amx-sub">Bars use the left axis (USD), the line uses the right axis (%)</div>
      </div>
      <div class="amx-toggle" role="group" aria-label="Range">
        <button type="button" data-range="6" aria-pressed="false">6M</button>
        <button type="button" data-range="12" aria-pressed="true">12M</button>
      </div>
    </div>
    <div id="amxChart"></div>
  </div>
</div>

Step by step

How to Use

  1. 1
    Load ApexChartsInclude apexcharts.min.js from the CDN before the snippet's script.
  2. 2
    Paste the HTML, CSS and JSTwelve months of revenue columns and a margin line render in one card.
  3. 3
    Hover a monthThe shared tooltip shows revenue and margin for that month together.
  4. 4
    Switch the rangeUse the 6M/12M toggle; categories and both series update in one call.
  5. 5
    Replace the dataEdit the MONTHS, REVENUE and MARGIN arrays with your own values.
  6. 6
    Tune the right axisAdjust min and max on the margin axis to fit your real range.

Real-world uses

Common Use Cases

Finance dashboards
Revenue against margin, spend against ROI, or cost against unit price.
Marketing reports
Sessions as columns with conversion rate as a line.
E-commerce analytics
Order count with average order value on its own axis.
Support operations
Ticket volume with median resolution time.
Learning ApexCharts
A compact reference for mixed series and multiple y-axes.
Related: ApexCharts Sparkline KPI Cards
Pair this chart with ApexCharts Sparkline KPI Cards for a compact summary row above it.
Related: ECharts Revenue Line with Zoom Brush
Compare the ECharts approach in ECharts Animated Revenue Line with Zoom Brush.

Got questions?

Frequently Asked Questions

Give each series its own type property — for example type: 'column' for bars and type: 'line' for the line — inside the series array. ApexCharts then renders a mixed chart. Options that differ per series, such as stroke.width and markers.size, accept arrays with one value per series.

Pass yaxis as an array of axis objects instead of a single object. Set seriesName on each axis to the name of the series it measures, and set opposite: true on the axis that should appear on the right side of the chart.

Margin moves by a few percentage points month to month. With automatic 0-100 bounds those changes would look flat. Fixing the range makes movement visible, but a range that is too narrow exaggerates noise, so choose bounds from the realistic spread of your own data.

The categories on the x-axis and the data in both series must change together. updateOptions accepts xaxis and series in one call and redraws once, while separate calls can render a frame where the data and labels do not match.

Yes. The official react-apexcharts and vue3-apexcharts wrappers take the same options and series objects. Keep the series array in state and pass new arrays when the range changes; the wrapper calls the update methods for you.