Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

[BUG]: Directional automargin clips right-side y-axis labels despite including "right"

Đang mở
#8,073 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Đánh giá

Độ khó
3/5
Thời gian dự kiến
1-2 ngày
Mức phù hợp với người mới
65/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
d3, javascript, typescript

Hướng nghiên cứu

The bug is in src/plots/cartesian/axes.js in the filterPush function. Start by reading the issue's analysis and the candidate fix. Run the provided HTML example to see the clipping. Then, examine the MARGIN_MAPPING and filterPush logic. The fix involves initializing the keepMargin accumulator with { x: 1, y: 1 }. Verify by building the library and testing with the reproduction case. Check existing tests in the axes Karma suite and add regression tests for directional automargin.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

bug
Description

Setting yaxis.automargin to "right+top+bottom" prevents a right-side y-axis from allocating its required right margin. Its tick labels are placed outside the figure and clipped. The same figure with yaxis.automargin: true allocates the margin and displays the labels.

Expected: including "right" should allow the right margin to grow enough to display the right-side tick labels. Omitting "left" should prevent left-margin growth without disabling right-margin growth.

Actual: the computed right margin remains zero even though Plotly measures a positive right-side margin requirement.

This reproduces with one Cartesian scatter trace and one right-side y-axis. It does not require Dash, Plotly.py, a secondary axis, overlays, autoshift, or application CSS. Both plots use the same explicit margins; only yaxis.automargin changes.

Screenshots/Video

The left plot uses true. The right plot uses "right+top+bottom" and loses its right-axis labels.

Control displays right-axis labels; directional automargin clips them
Steps to reproduce
  1. Save the following example as an HTML file.
  2. Open the file in Chrome with network access to the Plotly CDN.
  3. Compare the right-side tick labels in the two plots.
  4. Inspect the computed margins printed below the plots.
<!doctype html>
<meta charset="utf-8">
<script src="https://cdn.plot.ly/plotly-4.1.1.js"></script>
<div style="display:flex;gap:24px">
  <section><h2>Control: true</h2><div id="control"></div></section>
  <section><h2>Failure: right+top+bottom</h2><div id="failure"></div></section>
</div>
<pre id="results"></pre>
<script>
(async () => {
  const results = [];
  for (const [id, automargin] of [
    ['control', true],
    ['failure', 'right+top+bottom']
  ]) {
    const gd = document.getElementById(id);
    await Plotly.newPlot(gd, [
      {x: [0, 1, 2], y: [1000, 2000, 3000], type: 'scatter'}
    ], {
      width: 500,
      height: 300,
      margin: {l: 40, r: 0, t: 30, b: 40},
      yaxis: {side: 'right', automargin, tickformat: '.0f'}
    }, {displayModeBar: false});
    results.push({
      version: Plotly.version,
      automargin,
      leftMargin: gd._fullLayout._size.l,
      rightMargin: gd._fullLayout._size.r,
      rightPush: gd._fullLayout._pushmargin['y.automargin'].r
    });
  }
  document.getElementById('results').textContent = JSON.stringify(results, null, 2);
})();
</script>
Notes

Initial reproduction — September 23, 2026

  • Verified on September 23, 2026 using unmodified, unminified Plotly.js bundles
  • Versions: 4.1.1 (latest release checked that day) and 3.3.0
  • Browser: headless Google Chrome 152.0.7977.82 on Linux x86_64, glibc 2.43
  • Viewport: 1100 × 850; device scale factor: 1
  • Two fresh-page runs per version produced the same measurements
  • No page JavaScript errors occurred

The measurements below describe the initial Chrome reproduction. Further Chrome and Firefox verification appears under the candidate fix. Other operating systems remain untested. This report does not establish the first affected release.

Measurement true "right+top+bottom"
Computed left margin 40 px 40 px
Computed right margin 28 px 0 px
Right push size 28.021484375 px 28.021484375 px
Right push anchor (r.val) 1 0
Tick-label horizontal bounds relative to paper 473–500.021484375 px 501–528.021484375 px
Paper width 500 px 500 px

These measurements were identical in both tested versions. The control's 0.0215 px overshoot reflects integer margin rounding. The failing labels lie entirely beyond the paper's right edge. The local geometry check allows 0.5 px for rounding.

Suspected cause

The source analysis below explains the suspected cause. A locally tested candidate fix follows.

  • MARGIN_MAPPING preserves r and xr for "right", but not x
  • filterPush zeroes unpreserved single-letter fields, including the right-side axis's x anchor
  • plots.autoMargin falls back to o.x when o.xr is absent
  • doAutoMargin applies the right-side constraint only when fr > fl

The recorded push retains the required pixel size but changes its anchor from 1 to 0, consistent with that diagnosis.

Requested behavior and scope

The filter must preserve the positioning information needed for enabled margin directions while suppressing disabled directions. No new public attribute appears necessary.

The demonstrated case affects Cartesian yaxis.automargin with side: "right" and the flaglist above.

Directional automargin support was introduced in PR #6193. This is related implementation history, not confirmation of the first bad revision.

Candidate fix

In src/plots/cartesian/axes.js, inside filterPush, initialize the keepMargin accumulator with the anchor coordinates:

-    }, {});
+    }, { x: 1, y: 1 });

This preserves the coordinates needed to position enabled margin requests. Disabled margin sizes are still filtered out.

The original reproduction also fails on upstream commit 6b83cb1c6764994246c6d4b5a627326c9f038812. With the candidate fix, it reserves a 28 px right margin instead of zero, and the labels remain visible.

Verification update — September 24, 2026

The candidate fix is unchanged. Further verification compared patched and unmodified builds from commit 6b83cb1c6764994246c6d4b5a627326c9f038812.

Full axes Karma suite

Build Chrome 152.0.7977.82 Firefox 150.0.2
Unmodified upstream, 402 tests 400 pass / 2 fail 401 pass / 1 fail
Candidate fix plus nine regression tests, 411 tests 409 pass / 2 fail 410 pass / 1 fail

All nine added regression tests pass in both browsers. The existing failures have identical assertion values with and without the patch:

  • Chrome: can relayout insiderange and insiderange react to new data
  • Firefox: the tickson test named should respond to relayout

For example, each Chrome build computes -0.11035128805620609,2 where the test expects -0.12,2. Their causes remain undiagnosed.

As a countercheck, the added tests also ran against unmodified production source in Chrome. Five fail: right/top axes in anchored/free modes, plus the original clipped-label example. The four left/bottom controls pass.

Thus, the new regression tests detect the defect. The full suites are not entirely green because the existing failures remain.

Additional geometry probes

The expanded matrix covers all four sides, five mirror settings, fractional subplot domains, and anchored/free axes. It also covers margin flag transitions and multiple axes with and without autoshift.

The probes assert that disabled margins do not grow. They compare all-direction flaglists against true, and single-side behavior where applicable.

Build Chrome Firefox
Unmodified upstream 1,106 / 1,264 observations pass 1,105 / 1,264 observations pass
Candidate fix 1,264 / 1,264 observations pass 1,263 / 1,264 observations pass

The patch removes 158 failed observations in each browser and introduces no new failures in this matrix.

The remaining Firefox discrepancy is identical on unmodified upstream. An anchored left axis with mirror: true and domain [0.35, 1] starts with a 1 px left margin. After flag transitions back to true, that margin becomes 0 px. This discrepancy remains unresolved.

Image comparisons

All 26 existing automargin image fixtures render pixel-for-pixel identically before and after the patch.

Local exports do not match the stored CI baselines. Every mismatch has the same pixel count on patched and unmodified builds. No baseline was replaced or accepted.

This supports no new image regression in those fixtures, but it is not a clean CI-baseline pass. These fixtures do not exercise directional flaglists; the regression tests and geometry probes cover that behavior separately.

Other checks and limits

Lint, type checking, syntax checks, and schema-drift checks pass.

The Karma runs used a 1035 × 800 viewport on Linux. Firefox used Playwright's Ubuntu 24.04 fallback build on Ubuntu 26.04. The tests therefore cover a second browser engine, not a second operating system.

The work did not run every Plotly suite or every image fixture. Safari/WebKit remains untested. Human review and authoritative upstream CI validation are still needed.

The candidate fix and verification were prepared with AI assistance. No new regressions were found in these comparisons. Does this approach look appropriate for a pull request?

With the candidate fix: both charts display the right-axis labels. The directional case reserves 28 px on the right while preserving the 40 px left margin.

With the candidate fix, both charts display their right-axis labels
Ngôn ngữ chính
JavaScript
Star
18.3k
Fork
2k
Merge trung bình
2 ngày 10 giờ
Pull request đã merge (30 ngày)
30

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của plotly/plotly.js

Tất cả issue của plotly/plotly.js

Issue tương tự

Thêm issue về JavaScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.