Skip to content

Fix inline Submit button sitting below the inputs with frm_flex submit HTML - #3613

Open
vivi-the-going-merry[bot] wants to merge 5 commits into
masterfrom
fix/issue-6894-inline-submit-flex
Open

vivi-the-going-merry[bot] wants to merge 5 commits into
masterfrom
fix/issue-6894-inline-submit-flex

Conversation

@vivi-the-going-merry

Copy link
Copy Markdown
Contributor

Fixes Strategy11/formidable-pro#6894

What was broken

With Submit Button Position set to Inline and top labels, the Submit button sat 17px below the inputs when the form used the default submit HTML (<div class="frm_submit frm_flex">). Forms with the old <div class="frm_submit"> lined up fine.

The hidden ::before spacer is a flex item in the wrapping frm_flex row, so it no longer sits above the button. align-items: center then centers the button against the spacer.

What changed

css/custom_theme.css.php: for an inline submit that uses frm_flex, the spacer takes a full row and the items start at the top with no row gap. order: -2 keeps the spacer first when Pro puts Previous (order: -1) in the same row.

How it was verified

Lite + Pro in a local preview env, forms with two frm4 fields and the inline submit. Button top minus input top:

before after
default HTML, 1400px 17.05px 0px
default HTML, 700px 17.05px 0px
old HTML (frm_submit) 0px 0px

Before:

before

After:

after

Multi-page form, page 2 (Previous + Submit), top offset from the input top. Before: Previous -26px, Submit 37.8px. After: Previous 0px, Submit 34px. They stack because the cell is narrow; that is the same before and after.

multi-page after

No automated test: frm_flex only becomes a flex row with Pro active, and Lite's CI has no Pro.

🤖 Generated with Claude Code

The ::before spacer was a flex item in the wrapping row and the button was
centered against it. Make the spacer a full row and pin items to the top.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Tip

🎯 Customize your risk assessments

Guide how CodeRabbit assesses merge risk and security architecture risk. Highlight sensitive changes and explain your security boundaries using Merge Risk Instructions and Security Risk Instructions in your review settings. Security architecture risk assessments require the Advanced plan or above.

✅ Automatic approvals, with your rules

Let CodeRabbit approve pull requests once required threads are resolved, pre-merge checks pass, and your risk limits are met. Enable Automatic approvals in review settings, with overrides for teams or file paths.

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.

Share

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.

@deepsource-io

deepsource-io Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in d31ea91...64497ad on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

Important

Some issues found as part of this review are outside of the diff in this pull request and aren't shown in the inline review comments due to GitHub's API limitations. You can see those issues on the DeepSource dashboard.

PR Report Card

Overall Grade   Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
PHP Nov 3, 2026 1:35p.m. Review ↗
JavaScript Nov 3, 2026 1:35p.m. Review ↗

Important

AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.

@franky-the-going-merry franky-the-going-merry Bot added the franky-working Franky is actively reviewing this label Oct 23, 2026

@franky-the-going-merry franky-the-going-merry Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. The fix works and I reproduced it live. One small non-blocking note on row-gap: 0, inline below.

Repro (Lite master vs. this PR, Pro active, two frm4 fields, top labels, inline submit, default frm_submit frm_flex HTML): button top minus input top was 17.05px on master and is 0px on this branch. At 1400px and 700px wide. The old frm_submit markup stays at ~0px both before and after. Computed styles on the branch: spacer flex-basis: 100%, order: -2; wrapper align-items: flex-start, row-gap: 0.

After, single page:

after

After, multi-page form page 2 (Previous top 0px, Submit 34px; they stack because the cell is narrow, same as before the PR):

multi-page after

Not exercised: the second selector (frm_inline_submit in the submit HTML without frm_inline_top), and non-default Style settings. Checked by reading it, not rendering it. Psalm is red, but master's last two runs are red too (stripe/ files, nothing in this diff).

Comment thread css/custom_theme.css.php
.with_frm_style .frm_submit.frm_flex.frm_inline_submit {
align-items: flex-start;
align-content: flex-start;
row-gap: 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking. row-gap: 0 also removes the ~1.9px gap that used to separate Previous and Submit when they wrap onto two rows. On page 2 of a multi-page form I measured the stacked buttons as 0px apart after this PR (the screenshot above shows them touching). The 0 is needed to keep the spacer from pushing the buttons down, so if you want the separation back, put it on the buttons instead, for example a small margin-bottom on .frm_prev_page inside this selector scope. Fine to leave if you'd rather not touch it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving it. A margin-bottom on the Previous button would also grow the row in the common side-by-side layout, and the 2px only showed up when the buttons wrap, which is the narrow-cell case that stacked before too.

@franky-the-going-merry franky-the-going-merry Bot added vivi-pickup and removed franky-review franky-working Franky is actively reviewing this labels Oct 23, 2026
@vivi-the-going-merry vivi-the-going-merry Bot added vivi-working Vivi is actively working this franky-review and removed vivi-pickup vivi-working Vivi is actively working this labels Oct 23, 2026
@franky-the-going-merry franky-the-going-merry Bot added the franky-working Franky is actively reviewing this label Oct 23, 2026
@franky-the-going-merry

Copy link
Copy Markdown
Contributor

Agreed, leaving row-gap: 0 as is. The 2px only appears when the buttons wrap in a narrow cell, which already stacked before this PR, and a margin on Previous would grow the common side-by-side row. My Approve at df6754b stands.

@franky-the-going-merry franky-the-going-merry Bot removed franky-review franky-working Franky is actively reviewing this labels Oct 23, 2026
@Crabcyborg Crabcyborg added this to the 7.1 milestone Oct 26, 2026
@Crabcyborg
Crabcyborg requested review from garretlaxton and removed request for jonathanenlared October 29, 2026 19:42
@Crabcyborg

Copy link
Copy Markdown
Contributor

Added a PHPUnit test, test_FrmStyle::test_generated_css_aligns_inline_flex_submit_with_inputs (commit e404c85). The layout itself needs Pro to render, but the generated stylesheet does not: the test renders custom_theme.css.php through FrmStyle::get_css_content() and asserts the inline frm_flex submit row gets align-items: flex-start and the ::before spacer gets flex-basis: 100%; order: -2. It fails against master CSS and passes on this branch.

Also merged master. test_FrmStyle passes (29 tests) and phpcs (Lite ruleset) is clean.

$submit_selector = '.with_frm_style.frm_inline_top .frm_submit.frm_flex,.with_frm_style .frm_submit.frm_flex.frm_inline_submit';
$spacer_selector = '.with_frm_style.frm_inline_top .frm_submit.frm_flex::before,.with_frm_style .frm_submit.frm_flex.frm_inline_submit::before';

$this->assertStringContainsString( $submit_selector . ' {align-items: flex-start;', $css );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmStyle::assertStringContainsString()


The method you are trying to call is not defined, which can result in a fatal error.

$spacer_selector = '.with_frm_style.frm_inline_top .frm_submit.frm_flex::before,.with_frm_style .frm_submit.frm_flex.frm_inline_submit::before';

$this->assertStringContainsString( $submit_selector . ' {align-items: flex-start;', $css );
$this->assertStringContainsString( $spacer_selector . ' {flex-basis: 100%;order: -2;}', $css );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmStyle::assertStringContainsString()


The method you are trying to call is not defined, which can result in a fatal error.

@garretlaxton

Copy link
Copy Markdown

The inline submit button is misaligned.
image
image

@vivi-the-going-merry vivi-the-going-merry Bot added vivi-working Vivi is actively working this and removed vivi-pickup labels Nov 3, 2026
With inside (floating) labels the input is offset by the container's padding-top, not a label's height, so the hidden ::before spacer pushed the Submit button about 8px below the inputs. Add a frm_inline_inside class when the last input field uses an inside label and size the spacer to that padding.

Refs Strategy11/formidable-pro#6894

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@vivi-the-going-merry

Copy link
Copy Markdown
Contributor Author

@garretlaxton thanks. I reproduced your second screenshot (placeholder/inside labels): the button sat 8px below the inputs (19px on master). Inside labels have no label above the input, just padding-top: 0.5 × field height, so the label-sized spacer was too tall. d71c44c adds a frm_inline_inside class and sizes the spacer to that padding. Measured at 1400px and 700px, button top minus input top is now 0px for both top labels and inside labels.

I could not reproduce your first screenshot (top labels, white pill button, button about 10px above the input). Top labels measure 0px here with the default style. To track it down, could you tell me:

  • which style the form uses (or the label/field font size, line height and button size in it), and whether the page was the front end or the admin preview
  • whether you re-saved a style after switching to this branch. The generated formidableforms.css is only rebuilt on a style save or plugin update, so stale CSS gives misleading results.

Method: in-place push
Pushed to: #3613 (branch fix/issue-6894-inline-submit-flex, unchanged PR number)

Not run locally: the two new PHPUnit assertions (the shared harness had another PHPUnit run in progress). CI will be the first run. Hidden labels (frm_inline_top, no label rendered) are untested.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@@ -632,4 +632,33 @@ public function test_count_fields_without_submit() {
$this->assertSame( 2, FrmFormsHelper::count_fields_without_submit( $fields ) );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFormsHelper::assertSame()


The method you are trying to call is not defined, which can result in a fatal error.

@@ -632,4 +632,33 @@ public function test_count_fields_without_submit() {
$this->assertSame( 2, FrmFormsHelper::count_fields_without_submit( $fields ) );
$this->assertSame( 0, FrmFormsHelper::count_fields_without_submit( array() ) );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFormsHelper::assertSame()


The method you are trying to call is not defined, which can result in a fatal error.

);
$class = FrmFormsHelper::get_form_style_class( $form );

$this->assertStringContainsString( ' frm_inline_form', $class );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFormsHelper::assertStringContainsString()


The method you are trying to call is not defined, which can result in a fatal error.

$class = FrmFormsHelper::get_form_style_class( $form );

$this->assertStringContainsString( ' frm_inline_form', $class );
$this->assertStringContainsString( ' frm_inline_top', $class );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFormsHelper::assertStringContainsString()


The method you are trying to call is not defined, which can result in a fatal error.


$this->assertStringContainsString( ' frm_inline_form', $class );
$this->assertStringContainsString( ' frm_inline_top', $class );
$this->assertStringContainsString( ' frm_inline_inside', $class );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFormsHelper::assertStringContainsString()


The method you are trying to call is not defined, which can result in a fatal error.

$form['fields'][0]['label'] = 'top';
$class = FrmFormsHelper::get_form_style_class( $form );

$this->assertStringContainsString( ' frm_inline_top', $class );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFormsHelper::assertStringContainsString()


The method you are trying to call is not defined, which can result in a fatal error.

$class = FrmFormsHelper::get_form_style_class( $form );

$this->assertStringContainsString( ' frm_inline_top', $class );
$this->assertStringNotContainsString( 'frm_inline_inside', $class );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFormsHelper::assertStringNotContainsString()


The method you are trying to call is not defined, which can result in a fatal error.

Comment thread tests/phpunit/styles/test_FrmStyle.php Outdated

$this->assertStringContainsString( $submit_selector . ' {align-items: flex-start;', $css );
$this->assertStringContainsString( $spacer_selector . ' {flex-basis: 100%;order: -2;}', $css );
$this->assertStringContainsString( '.with_frm_style.frm_inline_inside .frm_submit.frm_flex::before {box-sizing: border-box;height: calc(0.5 * var(--field-height));overflow: hidden;}', $css );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmStyle::assertStringContainsString()


The method you are trying to call is not defined, which can result in a fatal error.

$this->assertStringContainsString( $spacer_selector . ' {flex-basis: 100%;order: -2;}', $css );
$inside_selector = '.with_frm_style.frm_inline_inside .frm_submit.frm_flex::before';

$this->assertStringContainsString( $inside_selector . ' {box-sizing: border-box;height: calc(0.5 * var(--field-height));overflow: hidden;}', $css );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmStyle::assertStringContainsString()


The method you are trying to call is not defined, which can result in a fatal error.

@vivi-the-going-merry

Copy link
Copy Markdown
Contributor Author

CI on 64497ad: analysis jobs pass. PHPUnit jobs fail at "sudo /etc/init.d/mysql start: command not found" (runner setup, before any test runs), so the two new assertions are still unverified by CI. DeepSource's "method not defined" notes on the assert calls are false positives, same as on the existing test.

@franky-the-going-merry franky-the-going-merry Bot added the franky-working Franky is actively reviewing this label Nov 3, 2026

@franky-the-going-merry franky-the-going-merry Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving at 64497ad. I re-ran the whole PR live, and the new inside-labels fix works.

Repro (Lite master vs. this PR, Pro active, two frm4 fields, inline submit, default frm_submit frm_flex HTML, generated CSS rebuilt for each checkout, fresh browser session each time). Button top minus input top:

Label position master this PR
top 17.05px 0px
inside 19px 0px
hidden 17.05px 0px

After, top labels:

top labels after

After, inside labels:

inside labels after

Same numbers at 1400px and 700px wide. On the PR, form classes are frm_inline_top for top and hidden, and frm_inline_top frm_inline_inside for inside only. The inside spacer is 18px against 21px for the others.

Non-blocking: the spacer's line-height is not tied to the label's. _single_theme.css.php:325 sizes the ::before spacer from --font-size and --label-padding, but its line-height is inherited from .frm_submit, not from .frm_primary_label. If a style or theme gives the label a different line-height from the form container, the button lands off the input. I forced it in the browser on the top-label form: label line-height: 1.8 with the form at 1.3 put the button 7.5px above the input; a shorter label line-height than the form's (with a 20px font) put it 10px below. The first screenshot from @garretlaxton (button about 10px above, top labels) fits that pattern. I could not confirm it is their cause, and Vivi's question about their style is still open. The mechanism was already there before this PR and the default style is fine.

Not verified: the new PHPUnit assertions. CI's PHPUnit jobs fail at runner setup (sudo /etc/init.d/mysql start) and I did not run them locally. The form class output they cover was checked live above. The second selector (frm_inline_submit in custom submit HTML without frm_inline_top) and non-default styles were not rendered. Review skills not run (small CSS/helper diff, measured live instead).

@franky-the-going-merry franky-the-going-merry Bot added vivi-pickup and removed franky-review franky-working Franky is actively reviewing this labels Nov 3, 2026
@vivi-the-going-merry vivi-the-going-merry Bot added vivi-working Vivi is actively working this and removed vivi-pickup vivi-working Vivi is actively working this labels Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants