From 960797ecb9f3ff00c272712ceddf8aed5fdfdb68 Mon Sep 17 00:00:00 2001 From: "vivi-the-going-merry[bot]" <308115520+vivi-the-going-merry[bot]@users.noreply.github.com> Date: Thu, 1 Oct 2026 04:11:58 -0600 Subject: [PATCH 1/3] Fix Stripe Link email asterisk position when label font differs from iframe Measure the Email label from Stripe's own .Label appearance rules instead of the page's label styles, pass fontFamily to the .Label rule, and drop the asterisk's left padding. Co-Authored-By: Claude Sonnet 5.5 --- .../FrmStrpLiteActionsController.php | 1 + stripe/js/frmstrp.js | 54 ++++++++----------- 2 files changed, 24 insertions(+), 31 deletions(-) diff --git a/stripe/controllers/FrmStrpLiteActionsController.php b/stripe/controllers/FrmStrpLiteActionsController.php index de9fb02d64..7de0c9c105 100644 --- a/stripe/controllers/FrmStrpLiteActionsController.php +++ b/stripe/controllers/FrmStrpLiteActionsController.php @@ -624,6 +624,7 @@ private static function get_appearance_rules( $settings ) { 'backgroundColor' => $settings['bg_color_active'], ), '.Label' => array( + 'fontFamily' => $settings['font'], 'color' => $settings['label_color'], 'fontSize' => $settings['font_size'], 'fontWeight' => $settings['weight'], diff --git a/stripe/js/frmstrp.js b/stripe/js/frmstrp.js index de1b7a36ca..0fbc7d192d 100644 --- a/stripe/js/frmstrp.js +++ b/stripe/js/frmstrp.js @@ -752,8 +752,9 @@ requiredIndicator.style.position = 'absolute'; requiredIndicator.style.fontSize = 'var(--font-size)'; requiredIndicator.style.top = '-4px'; - requiredIndicator.style.left = `${ getEmailAsteriskOffset( cardElement ) }px`; + requiredIndicator.style.left = `${ getEmailAsteriskOffset() }px`; requiredIndicator.style.padding = 'var(--label-padding)'; + requiredIndicator.style.paddingLeft = '0'; requiredIndicator.setAttribute( 'aria-hidden', 'true' ); authenticationMountTarget.append( requiredIndicator ); } ); @@ -762,44 +763,35 @@ /** * Create a temporary label element to determine the width of the Email label. * The asterisk is positioned after the label that Stripe renders inside of the iframe. + * The label is styled from the same appearance rules that Stripe uses, so it does not inherit page styles. * * @since 6.35 * - * @param {Element} cardElement * @return {number} The label width in pixels. */ - function getEmailAsteriskOffset( cardElement ) { - const label = document.createElement( 'label' ); - label.classList.add( 'frm_primary_label', 'form-label' ); - label.textContent = 'Email'; - label.innerHTML += ' '; - - const tempContainer = document.createElement( 'div' ); - tempContainer.classList.add( 'with_frm_style' ); - tempContainer.style.position = 'absolute'; - tempContainer.style.visibility = 'hidden'; - tempContainer.style.height = '0'; - tempContainer.style.overflow = 'hidden'; - - const formContainer = cardElement.closest( '.with_frm_style' ); - if ( formContainer ) { - each( - formContainer.classList, - function( className ) { - if ( className.startsWith( 'frm_style_' ) ) { - tempContainer.classList.add( className ); - return false; - } - } - ); - } + function getEmailAsteriskOffset() { + const rules = frm_stripe_vars.appearanceRules[ '.Label' ] || {}; + const label = document.createElement( 'span' ); + label.innerHTML = 'Email '; - tempContainer.append( label ); - document.body.append( tempContainer ); + Object.assign( + label.style, + { + position: 'absolute', + visibility: 'hidden', + whiteSpace: 'nowrap', + fontFamily: rules.fontFamily || 'inherit', + fontSize: rules.fontSize, + fontWeight: rules.fontWeight, + padding: rules.padding, + letterSpacing: 'normal', + textTransform: 'none' + } + ); + document.body.append( label ); const labelWidth = label.getBoundingClientRect().width; - - tempContainer.remove(); + label.remove(); return labelWidth; } From ad853bafd1a0f2e2df15b117d8bc9ab4408eccfb Mon Sep 17 00:00:00 2001 From: "vivi-the-going-merry[bot]" <308115520+vivi-the-going-merry[bot]@users.noreply.github.com> Date: Fri, 2 Oct 2026 13:41:43 -0600 Subject: [PATCH 2/3] Measure Stripe Link email label without page web fonts The Stripe iframe does not load page web fonts, so the .Label font stack now drops them before it is sent to Stripe and used for the asterisk probe. Co-Authored-By: Claude Sonnet 5.5 --- stripe/js/frmstrp.js | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/stripe/js/frmstrp.js b/stripe/js/frmstrp.js index 0fbc7d192d..0d7dedd93f 100644 --- a/stripe/js/frmstrp.js +++ b/stripe/js/frmstrp.js @@ -649,7 +649,7 @@ colorBackground: maybeAdjustColorForStripe( frm_stripe_vars.appearanceRules[ '.Input' ].backgroundColor ), fontSmooth: 'auto' }, - rules: frm_stripe_vars.appearanceRules + rules: getAppearanceRules() }; elements = frmstripe.elements( { clientSecret, appearance } ); isStripeLink = true; @@ -760,6 +760,39 @@ } ); } + /** + * Get the appearance rules to send to Stripe. + * The Label font is limited to families the Stripe iframe can render, so the page can measure the same text. + * + * @since 6.35 + * + * @return {Object} Appearance rules. + */ + function getAppearanceRules() { + const rules = frm_stripe_vars.appearanceRules; + const label = rules[ '.Label' ]; + if ( ! label || ! label.fontFamily ) { + return rules; + } + return Object.assign( {}, rules, { '.Label': Object.assign( {}, label, { fontFamily: removeWebFonts( label.fontFamily ) } ) } ); + } + + /** + * Remove families that the page loads as web fonts from a font stack. + * The Stripe iframe does not load them, so it falls back to the rest of the stack. + * + * @since 6.35 + * + * @param {string} fontFamily + * @return {string} The font stack without web fonts. + */ + function removeWebFonts( fontFamily ) { + const unquote = family => family.trim().replace( /^['"]|['"]$/g, '' ).toLowerCase(); + const webFonts = Array.from( document.fonts, font => unquote( font.family ) ); + const families = fontFamily.split( ',' ).filter( family => family.trim() && ! webFonts.includes( unquote( family ) ) ); + return families.length ? families.map( family => family.trim() ).join( ', ' ) : 'sans-serif'; + } + /** * Create a temporary label element to determine the width of the Email label. * The asterisk is positioned after the label that Stripe renders inside of the iframe. @@ -770,7 +803,7 @@ * @return {number} The label width in pixels. */ function getEmailAsteriskOffset() { - const rules = frm_stripe_vars.appearanceRules[ '.Label' ] || {}; + const rules = getAppearanceRules()[ '.Label' ] || {}; const label = document.createElement( 'span' ); label.innerHTML = 'Email '; @@ -780,7 +813,7 @@ position: 'absolute', visibility: 'hidden', whiteSpace: 'nowrap', - fontFamily: rules.fontFamily || 'inherit', + fontFamily: rules.fontFamily || 'system-ui, sans-serif', fontSize: rules.fontSize, fontWeight: rules.fontWeight, padding: rules.padding, From 051aea5fbe2d4169c61a9bb163e09566e6f97e54 Mon Sep 17 00:00:00 2001 From: "vivi-the-going-merry[bot]" <308115520+vivi-the-going-merry[bot]@users.noreply.github.com> Date: Fri, 2 Oct 2026 14:11:19 -0600 Subject: [PATCH 3/3] Skip Stripe Label fontFamily when the style font is blank Stripe then draws with its default stack instead of an empty value. Note the English-only probe text in the offset docblock. Co-Authored-By: Claude Sonnet 5.5 --- stripe/controllers/FrmStrpLiteActionsController.php | 5 +++++ stripe/js/frmstrp.js | 1 + 2 files changed, 6 insertions(+) diff --git a/stripe/controllers/FrmStrpLiteActionsController.php b/stripe/controllers/FrmStrpLiteActionsController.php index 7de0c9c105..e5503f64a5 100644 --- a/stripe/controllers/FrmStrpLiteActionsController.php +++ b/stripe/controllers/FrmStrpLiteActionsController.php @@ -636,6 +636,11 @@ private static function get_appearance_rules( $settings ) { ), ); + if ( '' === (string) $settings['font'] ) { + // Leave the font out so Stripe uses its default stack instead of an empty value. + unset( $rules['.Label']['fontFamily'] ); + } + /* * Filters the appearance rules for Stripe elements. * diff --git a/stripe/js/frmstrp.js b/stripe/js/frmstrp.js index 0d7dedd93f..b8389cafa2 100644 --- a/stripe/js/frmstrp.js +++ b/stripe/js/frmstrp.js @@ -797,6 +797,7 @@ * Create a temporary label element to determine the width of the Email label. * The asterisk is positioned after the label that Stripe renders inside of the iframe. * The label is styled from the same appearance rules that Stripe uses, so it does not inherit page styles. + * The probe text is the English word, so the offset can be off when Stripe renders a localized label. * * @since 6.35 *