Skip to content

Add link/lock aspect ratio button for width & height fields - #17494

Open
djcesar wants to merge 1 commit into
AUTOMATIC1111:masterfrom
djcesar:resize-link-aspect-ratio
Open

djcesar wants to merge 1 commit into
AUTOMATIC1111:masterfrom
djcesar:resize-link-aspect-ratio

Conversation

@djcesar

@djcesar djcesar commented Sep 22, 2026 •

Copy link
Copy Markdown

Summary

Adds a small chain-link ToolButton (🔗) next to the existing switch-width/height button (⇅) in three places:

  • txt2img — Width/Height
  • img2img — "Resize to" tab
  • Extras — "Scale to" tab

When toggled on, it captures the current width/height ratio, and from then on editing either field — by typing in the number box or by dragging the slider — automatically recalculates the other field to keep that ratio, rounded to the field's step and clamped to its min/max. Toggling it off lets both fields move independently again, as today.

This is a small quality-of-life addition for anyone resizing/upscaling to a specific target resolution who wants to keep the source aspect ratio without doing the math by hand or re-checking it after every edit.

Screenshots

Off (default):
Width and Height sliders behave exactly as before.

image

On:
The link button gets a solid highlighted background (reusing the theme's --primary-600, the same color used elsewhere for primary actions) so its state is clear at a glance. Dragging Width from 432 to 1024 (with Height starting at 768) automatically moves Height to 1816, preserving the original ~0.748 ratio.

image

Implementation notes

  • javascript/ui.js: toggleResLinkFor(linkBtnId, widthElemId, heightElemId) and setupResLinkFor(linkBtnId, widthElemId, heightElemId, minVal, maxVal, step) hold the actual linking logic. They listen on both input[type=number] and input[type=range] for each field, since Gradio's Slider renders both and either one can be the source of a user edit. toggleResLink(tabname) / setupResLink(tabname) are thin convenience wrappers for the common "{tabname}_width" / "{tabname}_height" elem_id convention already used by txt2img/img2img, so existing call sites stay simple.
  • A recursion guard (state.syncing) prevents the programmatic update of the "other" field from re-triggering the handler.
  • Extras' "Scale to" fields go up to 8192 (vs. 2048 for txt2img/img2img), so it calls setupResLinkFor(...) directly with its own range rather than using the tabname-convention wrapper.
  • modules/ui.py / scripts/postprocessing_upscale.py: new ToolButton per location, wired with fn=None, _js="...", following the exact same pattern already used by the neighboring switch-width/height button.
  • style.css: .res-link-enabled gives the button an opaque background while active instead of a subtle transparency overlay, for better at-a-glance visibility.

Test plan

  • Toggled the link on in txt2img, dragged the Width slider, confirmed Height updates to keep the ratio, and vice versa.
  • Same test in img2img "Resize to" and in Extras "Scale to" (confirmed the 8192 max is respected there, not clamped to 2048).
  • Confirmed typing directly in the number field also triggers the sync (not just dragging).
  • Toggled the link off and confirmed both fields go back to moving independently.
  • Checked the browser console for errors during all of the above — none.

Adds a chain-link ToolButton next to the existing width/height
switch button in txt2img, img2img (Resize to), and Extras (Scale to).
When enabled, editing either the width or height slider/number field
(by typing or by dragging) automatically recalculates the other field
to preserve the aspect ratio captured at the moment the link was
turned on, rounded to the nearest valid step and clamped to that
field's own min/max.

- modules/ui.py: new link_dimensions_symbol and res_link_btn
  ToolButton for txt2img and img2img, wired to toggleResLink().
- scripts/postprocessing_upscale.py: same button for the Extras
  "Scale to" tab, wired to the generic toggleResLinkFor() so it can
  use its own 64-8192 range instead of the 64-2048 range used by
  txt2img/img2img.
- javascript/ui.js: toggleResLinkFor()/setupResLinkFor() implement
  the linking logic, listening on both the number input and the
  range input Gradio renders for each Slider (so it reacts to typing
  and to dragging). toggleResLink()/setupResLink() are thin
  convenience wrappers for the common "{tabname}_width"/"_height"
  elem_id convention used by txt2img/img2img.
- style.css: .res-link-enabled gives the button a solid, opaque
  background (var(--primary-600)) while the link is active, matching
  the button color used elsewhere for primary actions.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

⌂ Proxy