Fix inline Submit button layout and position#2969
Conversation
📝 WalkthroughWalkthroughAdds logic to detect and reflow inline submit buttons when they share a row with other fields, plus a helper to compare element top positions; updates call sites during form init/destroy. Also adds CSS rules to position the inline submit button container and align the submit button. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
|
Overall Grade |
Security Reliability Complexity Hygiene |
Code Review Summary
| Analyzer | Status | Updated (UTC) | Details |
|---|---|---|---|
| PHP | Feb 24, 2026 12:11p.m. | Review ↗ | |
| JavaScript | Feb 24, 2026 12:11p.m. | Review ↗ |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@js/formidable.js`:
- Around line 1687-1699: Guard against null DOM nodes and replace strict top
equality with a tolerance check: when iterating submitButtons, ensure
submitContainer (from button.closest('.frm_form_field')) and previousSibling
exist before calling getTopPositionOfElement to avoid getBoundingClientRect()
errors; then compare tops using a tolerance (e.g.,
Math.abs(getTopPositionOfElement(submitContainer) -
getTopPositionOfElement(previousSibling)) > tolerance) instead of === so
sub‑pixel differences don’t skip inline layouts; keep references to
submitContainer, previousSibling, submitWrapper, and button when applying style
changes.
js/formidable.js
Outdated
| submitButtons.forEach( button => { | ||
| const submitContainer = button.closest( '.frm_form_field' ); | ||
| const previousSibling = submitContainer.previousElementSibling; | ||
| if ( getTopPositionOfElement( submitContainer ) !== getTopPositionOfElement( previousSibling ) ) { | ||
| // If the submit button is not inline with other fields, do not update the layout. | ||
| return; | ||
| } | ||
|
|
||
| submitContainer.style.position = 'relative'; | ||
| const submitWrapper = button.closest( 'div' ); | ||
| submitWrapper.style.position = 'absolute'; | ||
| submitWrapper.style.bottom = '0'; | ||
| button.style.marginBottom = '0'; |
There was a problem hiding this comment.
Guard null elements and avoid brittle top equality checks.
If a submit button isn’t inside .frm_form_field, or the container has no previous sibling, getBoundingClientRect() will throw and break init. Also, strict top equality is fragile due to sub‑pixel rounding, so inline layouts may be skipped unintentionally. Consider null guards plus a small tolerance.
🔧 Proposed fix
submitButtons.forEach( button => {
const submitContainer = button.closest( '.frm_form_field' );
- const previousSibling = submitContainer.previousElementSibling;
- if ( getTopPositionOfElement( submitContainer ) !== getTopPositionOfElement( previousSibling ) ) {
+ if ( ! submitContainer ) {
+ return;
+ }
+ const previousSibling = submitContainer.previousElementSibling;
+ if ( ! previousSibling ) {
+ return;
+ }
+ const submitTop = getTopPositionOfElement( submitContainer );
+ const prevTop = getTopPositionOfElement( previousSibling );
+ if ( Math.abs( submitTop - prevTop ) > 1 ) {
// If the submit button is not inline with other fields, do not update the layout.
return;
}
submitContainer.style.position = 'relative';
const submitWrapper = button.closest( 'div' );
+ if ( ! submitWrapper ) {
+ return;
+ }
submitWrapper.style.position = 'absolute';
submitWrapper.style.bottom = '0';
button.style.marginBottom = '0';
} );🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@js/formidable.js` around lines 1687 - 1699, Guard against null DOM nodes and
replace strict top equality with a tolerance check: when iterating
submitButtons, ensure submitContainer (from button.closest('.frm_form_field'))
and previousSibling exist before calling getTopPositionOfElement to avoid
getBoundingClientRect() errors; then compare tops using a tolerance (e.g.,
Math.abs(getTopPositionOfElement(submitContainer) -
getTopPositionOfElement(previousSibling)) > tolerance) instead of === so
sub‑pixel differences don’t skip inline layouts; keep references to
submitContainer, previousSibling, submitWrapper, and button when applying style
changes.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
js/formidable.js (2)
1688-1693: Null guards forsubmitContainerandpreviousSiblingare still absent.
button.closest('.frm_form_field')returnsnullwhen the button is not inside a field container, andsubmitContainer.previousElementSiblingcan benullwhen there is no preceding sibling. Both cases causegetBoundingClientRect()to throw, breakinginit(). The strict-equality check is also still fragile for sub-pixel layout values.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@js/formidable.js` around lines 1688 - 1693, Protect against nulls and fragile exact-equality by checking button.closest('.frm_form_field') and its previousElementSibling before calling getTopPositionOfElement inside init(); if either submitContainer or previousSibling is null, skip the alignment logic. Replace the strict equality test with a tolerant comparison such as Math.abs(getTopPositionOfElement(submitContainer) - getTopPositionOfElement(previousSibling)) < 1 to allow sub-pixel differences, and only add the 'frm_inline_submit_button' class when that tolerant check passes.
1688-1693:⚠️ Potential issue | 🟠 MajorFalse-positive: hidden forms cause
frm_inline_submit_buttonto be applied to every submit button.
getBoundingClientRect().topreturns0for all elements inside hidden containers (e.g., Elementor popups — explicitly supported in this codebase at line 1803). Duringinit()every hidden form's submit button satisfies0 === 0, sofrm_inline_submit_buttonis unconditionally added to each, regardless of actual field layout. When the popup is later revealed, the CSS ruleposition: absolute; bottom: 0fires on non-inline submit buttons, mispositions them.Add a visibility guard before comparing positions.
🔧 Proposed fix
submitButtons.forEach( button => { const submitContainer = button.closest( '.frm_form_field' ); + if ( ! submitContainer ) { + return; + } + // Skip elements that are not rendered (e.g. hidden Elementor popup forms). + if ( submitContainer.getBoundingClientRect().height === 0 ) { + return; + } const previousSibling = submitContainer.previousElementSibling; - if ( getTopPositionOfElement( submitContainer ) === getTopPositionOfElement( previousSibling ) ) { + if ( ! previousSibling ) { + return; + } + if ( Math.abs( getTopPositionOfElement( submitContainer ) - getTopPositionOfElement( previousSibling ) ) <= 1 ) { // If the submit button is inline with other fields, vertically align it with other fields in the same row. submitContainer.classList.add( 'frm_inline_submit_button' ); } } );🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@js/formidable.js` around lines 1688 - 1693, The current logic in init() that compares getTopPositionOfElement(submitContainer) and getTopPositionOfElement(previousSibling) can produce false positives for hidden forms (e.g., Elementor popups) because getBoundingClientRect().top returns 0 for invisible elements; before comparing positions, ensure visibility by checking the submitContainer and previousSibling are visible (e.g., element.getClientRects().length > 0 or offsetParent !== null) and only then run the top-position comparison and add the frm_inline_submit_button class; update the block around submitContainer/previousSibling and getTopPositionOfElement to short-circuit when either element is not visible.
🧹 Nitpick comments (1)
js/formidable.js (1)
1806-1810:maybeUpdateInlineSubmitButtonLayoutis not re-invoked onfrmPageChanged.For multi-page forms, the submit button typically lives only on the last page. When
init()runs, no.frm_button_submitelements are in the DOM yet, so the function returns immediately. After an AJAX page transition injects the last page's content,frmPageChangedfires anddestroyhCaptcharuns, butmaybeUpdateInlineSubmitButtonLayoutis never called, so the inline-submit layout never gets applied on paginated forms.♻️ Proposed fix
jQuery( document ).on( 'frmPageChanged', destroyhCaptcha ); +jQuery( document ).on( + 'frmPageChanged', + maybeUpdateInlineSubmitButtonLayout +); maybeUpdateInlineSubmitButtonLayout();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@js/formidable.js` around lines 1806 - 1810, The inline-submit layout isn't applied after AJAX page transitions because maybeUpdateInlineSubmitButtonLayout isn't called when frmPageChanged fires; update the event handler registration that currently calls destroyhCaptcha so it also invokes maybeUpdateInlineSubmitButtonLayout (e.g., call both destroyhCaptcha and maybeUpdateInlineSubmitButtonLayout inside the frmPageChanged handler or register a second listener), ensuring the function runs after page content is injected so the final-page .frm_button_submit elements are detected.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@css/custom_theme.css.php`:
- Around line 611-613: The rule ".with_frm_style .frm_inline_submit_button
.frm_submit .frm_button_submit { margin-bottom: 0; }" is being overridden by the
stronger ".frm_center_submit .frm_submit button { margin-bottom: 8px !important;
}"; update the inline-submit selector to win (either by matching or exceeding
specificity and/or adding !important) so margin-bottom:0 actually applies when
both classes are present—modify the ".with_frm_style .frm_inline_submit_button
.frm_submit .frm_button_submit" rule to use a higher-specificity selector or
include !important to override ".frm_center_submit .frm_submit button".
---
Duplicate comments:
In `@js/formidable.js`:
- Around line 1688-1693: Protect against nulls and fragile exact-equality by
checking button.closest('.frm_form_field') and its previousElementSibling before
calling getTopPositionOfElement inside init(); if either submitContainer or
previousSibling is null, skip the alignment logic. Replace the strict equality
test with a tolerant comparison such as
Math.abs(getTopPositionOfElement(submitContainer) -
getTopPositionOfElement(previousSibling)) < 1 to allow sub-pixel differences,
and only add the 'frm_inline_submit_button' class when that tolerant check
passes.
- Around line 1688-1693: The current logic in init() that compares
getTopPositionOfElement(submitContainer) and
getTopPositionOfElement(previousSibling) can produce false positives for hidden
forms (e.g., Elementor popups) because getBoundingClientRect().top returns 0 for
invisible elements; before comparing positions, ensure visibility by checking
the submitContainer and previousSibling are visible (e.g.,
element.getClientRects().length > 0 or offsetParent !== null) and only then run
the top-position comparison and add the frm_inline_submit_button class; update
the block around submitContainer/previousSibling and getTopPositionOfElement to
short-circuit when either element is not visible.
---
Nitpick comments:
In `@js/formidable.js`:
- Around line 1806-1810: The inline-submit layout isn't applied after AJAX page
transitions because maybeUpdateInlineSubmitButtonLayout isn't called when
frmPageChanged fires; update the event handler registration that currently calls
destroyhCaptcha so it also invokes maybeUpdateInlineSubmitButtonLayout (e.g.,
call both destroyhCaptcha and maybeUpdateInlineSubmitButtonLayout inside the
frmPageChanged handler or register a second listener), ensuring the function
runs after page content is injected so the final-page .frm_button_submit
elements are detected.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
js/formidable-settings-components.js.mapis excluded by!**/*.map
📒 Files selected for processing (3)
css/custom_theme.css.phpjs/formidable-web-components.jsjs/formidable.js
| .with_frm_style .frm_inline_submit_button .frm_submit .frm_button_submit{ | ||
| margin-bottom: 0; | ||
| } |
There was a problem hiding this comment.
margin-bottom: 0 is overridden by the existing !important rule when frm_center_submit is present.
The rule at lines 660–664 sets margin-bottom: 8px !important on .frm_center_submit .frm_submit button. Because !important wins regardless of specificity, any form that combines frm_center_submit with an inline submit button that receives frm_inline_submit_button will retain the 8 px margin, nullifying the intent of this rule.
🔧 Proposed fix
.with_frm_style .frm_inline_submit_button .frm_submit .frm_button_submit{
- margin-bottom: 0;
+ margin-bottom: 0 !important;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .with_frm_style .frm_inline_submit_button .frm_submit .frm_button_submit{ | |
| margin-bottom: 0; | |
| } | |
| .with_frm_style .frm_inline_submit_button .frm_submit .frm_button_submit{ | |
| margin-bottom: 0 !important; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@css/custom_theme.css.php` around lines 611 - 613, The rule ".with_frm_style
.frm_inline_submit_button .frm_submit .frm_button_submit { margin-bottom: 0; }"
is being overridden by the stronger ".frm_center_submit .frm_submit button {
margin-bottom: 8px !important; }"; update the inline-submit selector to win
(either by matching or exceeding specificity and/or adding !important) so
margin-bottom:0 actually applies when both classes are present—modify the
".with_frm_style .frm_inline_submit_button .frm_submit .frm_button_submit" rule
to use a higher-specificity selector or include !important to override
".frm_center_submit .frm_submit button".
Fix https://github.com/Strategy11/formidable-pro/issues/6326

Before:
After:
