diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js
index 3e5a8e040..5b9843ae1 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js
@@ -336,6 +336,24 @@ RED.view = (function() {
function init() {
chart = $("#red-ui-workspace-chart");
+
+ // Add invisible spacer div to ensure scrollable area matches canvas dimensions
+ // At minimum zoom with "cover" behavior, SVG may be smaller than viewport in one dimension
+ // This spacer forces the browser to calculate scrollWidth/Height based on full canvas size
+ // Browser's maxScroll = scrollWidth - viewport will then correctly show canvas edges
+ var scrollSpacer = $('
')
+ .css({
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ width: space_width + 'px',
+ height: space_height + 'px',
+ pointerEvents: 'none',
+ visibility: 'hidden'
+ })
+ .attr('id', 'red-ui-workspace-scroll-spacer')
+ .appendTo(chart);
+
chart.on('contextmenu', function(evt) {
if (RED.view.DEBUG) {
console.warn("contextmenu", { mouse_mode, event: d3.event });
@@ -2810,14 +2828,14 @@ RED.view = (function() {
// Calculate the minimum zoom to ensure canvas always fills the viewport (no empty space)
var viewportWidth = chart.width();
var viewportHeight = chart.height();
-
+
// Canvas is 8000x8000, calculate zoom to cover viewport
var zoomToFitWidth = viewportWidth / space_width;
var zoomToFitHeight = viewportHeight / space_height;
-
+
// Use the LARGER zoom to ensure canvas covers entire viewport (no empty space visible)
var calculatedMinZoom = Math.max(zoomToFitWidth, zoomToFitHeight);
-
+
// Return the larger of the calculated min or the configured min
// This ensures canvas always fills the viewport
return Math.max(calculatedMinZoom, RED.view.zoomConstants.MIN_ZOOM);
@@ -4969,6 +4987,15 @@ RED.view = (function() {
eventLayer.attr("transform","scale("+scaleFactor+")");
outer.attr("width", space_width*scaleFactor).attr("height", space_height*scaleFactor);
+ // Update scroll spacer to match scaled canvas size
+ // This ensures scrollable area = canvas area
+ // Browser calculates maxScroll = scrollWidth - viewport, which correctly
+ // allows scrolling to see the far edges of canvas without going beyond
+ $('#red-ui-workspace-scroll-spacer').css({
+ width: (space_width * scaleFactor) + 'px',
+ height: (space_height * scaleFactor) + 'px'
+ });
+
// Don't bother redrawing nodes if we're drawing links
if (showAllLinkPorts !== -1 || mouse_mode != RED.state.JOINING) {