javascriptcssecharts

ECharts x-axis labels truncated with grid left/right 0: How to offset first/last labels without affecting spacing?


The Problem I am using ECharts and I need the chart to take up the full width of the container. Therefore, I set grid.left and grid.right to 0. However, this causes the first and last labels on the x-axis to be truncated (cut off) because they overflow the container.

What I tried I tried to solve this by using xAxis.axisLabel.formatter with rich text styles. I added left padding to the last label and right padding to the first label to push them "inwards."

While this fixes the truncation, it introduces a new problem: The visual spacing between the first label and the second label becomes smaller than the rest. The same happens for the last label. It seems that modifying the label style via padding visually shifts the text, but doesn't adjust the calculated distribution logic, leading to uneven gaps.

My Question Is there a proper way to prevent the first and last x-axis labels from being cut off when grid: { left: 0, right: 0 }, without breaking the automatic equidistant spacing of the labels?

Minimal Reproducible Example Here is the configuration I am using:

// Generate simple mock data (Short enough to show all labels clearly)
var dataX = ['09:30', '10:00', '10:30', '11:00', '11:30', '13:00', '14:00', '15:00'];
var dataY = [120, 132, 101, 134, 90, 230, 210, 150];
      return {
  // 1. Grid set to 0 to force chart to edges
  grid: {
    top: '10%',
    left: '0',   // Force align left edge
    right: '0',  // Force align right edge
    bottom: '15%',
    containLabel: false // MUST be false to reproduce the truncation issue
  },
  xAxis: {
    type: 'category',
    data: dataX,
    boundaryGap: false, // Line starts exactly at the Y-axis
    axisTick: { show: false },
    axisLine: {
      lineStyle: { color: '#E0E0E0' }
    },
    axisLabel: {
      margin: 10,
      show: true,
      color: '#666',
      fontSize: 12,
      align: 'center',
      
      // Force show ALL labels to demonstrate the uneven spacing issue
      // interval: 0, 

      // 2. The Formatter: Apply rich text styles only to first and last label
      formatter: function (value: any, index: any) {
        if (index === 0) {
          return '{start|' + value + '}';
        }
        if (index === dataX.length - 1) {
          return '{end|' + value + '}';
        }
        return value;
      },
      
      // 3. The Workaround causing the issue:
      // Using padding to shift first/last labels inwards to prevent truncation.
      // PROBLEM: This visually shifts the text but messes up the equidistant spacing.
      rich: {
        start: {
          align: 'left',
          fontSize: 12,
          // Pushing the first label to the right (inwards)
          padding: [0, 0, 0, 30] 
        },
        end: {
          align: 'right',
          fontSize: 12,
          // Pushing the last label to the left (inwards)
          padding: [0, 30, 0, 0] 
        }
      }
    }
  },
  yAxis: {
    type: 'value',
    show: true,
    axisLine: { show: false },
    axisLabel: {
      inside: true, // Labels inside the chart
      margin: 0,
      verticalAlign: 'bottom',
      color: '#999',
      fontSize: 10
    },
    splitLine: {
      show: true,
      lineStyle: { color: '#E0E0E0' }
    }
  },
  series: [
    {
      name: 'Value',
      type: 'line',
      data: dataY,
      symbol: 'none', // Hide dots for cleaner look
      lineStyle: {
        width: 1,
        color: '#F56C6C'
      }
    }
  ]
};

Solution

  • Thanks to @kikon for the insight. The issue is indeed geometric: trying to center labels on the edge of the container (where left: 0 and right: 0) will inevitably cause them to be cut off.

    There are two ways to solve this, depending on your ECharts version.

    Solution 1: The Modern Way (ECharts v5.5.0+)

    If you can upgrade to version 5.5.0 or later, ECharts introduced specific properties to handle exactly this scenario: alignMinLabel and alignMaxLabel.

    This allows the first label to be left-aligned and the last label to be right-aligned automatically, keeping the middle ones centered.

        xAxis: {
          // ... other configs
          axisLabel: {
            // Force the first label to align left (inside the chart)
            alignMinLabel: 'left', 
            // Force the last label to align right (inside the chart)
            alignMaxLabel: 'right',
            
            align: 'center', // All other labels remain centered
            // ...
          }
        }
    

    Solution 2: The Manual Way (For older versions)

    Since I am currently on v5.4.2 and cannot upgrade immediately, the workaround is to manually set the align property using a callback function. This achieves a similar effect without using padding (which messes up the equidistant spacing).

        xAxis: {
          // ...
          axisLabel: {
            // ...
            align: function(value, index) {
              // Assuming you know the index or value of your start/end points
              if (index === 0) return 'left'; 
              if (index === data.length - 1) return 'right';
              return 'center';
            }
          }
        }
    

    This ensures the labels are fully visible inside the container without distorting the visual spacing between ticks.