docs: function () {
              var axis = this,
                chart = axis.chart,
                renderer = chart.renderer,
                options = axis.options,
                tickPositions = axis.tickPositions,
                ticks = axis.ticks,
                horiz = axis.horiz,
                side = axis.side,
                invertedSide = chart.inverted ? [1, 0, 3, 2][side] : side,
                hasData,
                showAxis,
                titleOffset = 0,
                titleOffsetOption,
                titleMargin = 0,
                axisTitleOptions = options.title,
                labelOptions = options.labels,
                labelOffset = 0, // reset
                labelOffsetPadded,
                axisOffset = chart.axisOffset,
                clipOffset = chart.clipOffset,
                directionFactor = [-1, 1, 1, -1][side],
                n,
                i,
                autoStaggerLines = 1,
                maxStaggerLines = pick(labelOptions.maxStaggerLines, 5),
                sortedPositions,
                lastRight,
                overlap,
                pos,
                bBox,
                x,
                w,
                lineNo,
                lineHeightCorrection;
  
              // For reuse in Axis.render
              axis.hasData = hasData = (axis.hasVisibleSeries || (defined(axis.min) && defined(axis.max) && !!tickPositions));
              axis.showAxis = showAxis = hasData || pick(options.showEmpty, true);
  
              // Set/reset staggerLines
              axis.staggerLines = axis.horiz && labelOptions.staggerLines;
  
              // Create the axisGroup and gridGroup elements on first iteration
              if (!axis.axisGroup) {
                  axis.gridGroup = renderer.g('grid')
                    .attr({ zIndex: options.gridZIndex || 1 })
                    .add();
                  axis.axisGroup = renderer.g('axis')
                    .attr({ zIndex: options.zIndex || 2 })
                    .add();
                  axis.labelGroup = renderer.g('axis-labels')
                    .attr({ zIndex: labelOptions.zIndex || 7 })
                    .addClass(PREFIX + axis.coll.toLowerCase() + '-labels')
                    .add();
              }
  
              if (hasData || axis.isLinked) {
  
                  // Set the explicit or automatic label alignment
                  axis.labelAlign = pick(labelOptions.align || axis.autoLabelAlign(labelOptions.rotation));
  
                  // Generate ticks
                  each(tickPositions, function (pos) {
                      if (!ticks[pos]) {
                          ticks[pos] = new Tick(axis, pos);
                      } else {
                          ticks[pos].addLabel(); // update labels depending on tick interval
                      }
                  });
  
                  // Handle automatic stagger lines
                  if (axis.horiz && !axis.staggerLines && maxStaggerLines && !labelOptions.rotation) {
                      sortedPositions = axis.reversed ? [].concat(tickPositions).reverse() : tickPositions;
                      while (autoStaggerLines < maxStaggerLines) {
                          lastRight = [];
                          overlap = false;
  
                          for (i = 0; i < sortedPositions.length; i++) {
                              pos = sortedPositions[i];
                              bBox = ticks[pos].label && ticks[pos].label.getBBox();
                              w = bBox ? bBox.width : 0;
                              lineNo = i % autoStaggerLines;
  
                              if (w) {
                                  x = axis.translate(pos); // don't handle log
                                  if (lastRight[lineNo] !== UNDEFINED && x < lastRight[lineNo]) {
                                      overlap = true;
                                  }
                                  lastRight[lineNo] = x + w;
                              }
                          }
                          if (overlap) {
                              autoStaggerLines++;
                          } else {
                              break;
                          }
                      }
  
                      if (autoStaggerLines > 1) {
                          axis.staggerLines = autoStaggerLines;
                      }
                  }
  
  
                  each(tickPositions, function (pos) {
                      // left side must be align: right and right side must have align: left for labels
                      if (side === 0 || side === 2 || { 1: 'left', 3: 'right' }[side] === axis.labelAlign) {
  
                          // get the highest offset
                          labelOffset = mathMax(
                            ticks[pos].getLabelSize(),
                            labelOffset
                          );
                      }
                  });
  
                  if (axis.staggerLines) {
                      labelOffset *= axis.staggerLines;
                      axis.labelOffset = labelOffset;
                  }
  
  
              } else { // doesn't have data
                  for (n in ticks) {
                      ticks[n].destroy();
                      delete ticks[n];
                  }
              }
  
              if (axisTitleOptions && axisTitleOptions.text && axisTitleOptions.enabled !== false) {
                  if (!axis.axisTitle) {
                      axis.axisTitle = renderer.text(
                        axisTitleOptions.text,
                        0,
                        0,
                        axisTitleOptions.useHTML
                        )
                        .attr({
                            zIndex: 7,
                            rotation: axisTitleOptions.rotation || 0,
                            align:
                            axisTitleOptions.textAlign ||
                            { low: 'left', middle: 'center', high: 'right' }[axisTitleOptions.align]
                        })
                        .addClass(PREFIX + this.coll.toLowerCase() + '-title')
                        .css(axisTitleOptions.style)
                        .add(axis.axisGroup);
                      axis.axisTitle.isNew = true;
                  }
  
                  if (showAxis) {
                      titleOffset = axis.axisTitle.getBBox()[horiz ? 'height' : 'width'];
                      titleOffsetOption = axisTitleOptions.offset;
                      titleMargin = defined(titleOffsetOption) ? 0 : pick(axisTitleOptions.margin, horiz ? 5 : 10);
                  }
  
                  // hide or show the title depending on whether showEmpty is set
                  axis.axisTitle[showAxis ? 'show' : 'hide']();
              }
  
              // handle automatic or user set offset
              axis.offset = directionFactor * pick(options.offset, axisOffset[side]);
  
              lineHeightCorrection = side === 2 ? axis.tickBaseline : 0;
              labelOffsetPadded = labelOffset + titleMargin +
                (labelOffset && (directionFactor * (horiz ? pick(labelOptions.y, axis.tickBaseline + 8) : labelOptions.x) - lineHeightCorrection));
              axis.axisTitleMargin = pick(titleOffsetOption, labelOffsetPadded);
  
              axisOffset[side] = mathMax(
                axisOffset[side],
                axis.axisTitleMargin + titleOffset + directionFactor * axis.offset,
                labelOffsetPadded // #3027
              );
              clipOffset[invertedSide] = mathMax(clipOffset[invertedSide], mathFloor(options.lineWidth / 2) * 2);
          }