Blog

How to modify embedded Hubspot forms with Javascript

Customizing the appearance of embedded HubSpot forms on your WordPress website can be challenging, especially when dealing with cross-browser compatibility issues. In this guide, we’ll walk through the process of applying custom styles to HubSpot forms, overcoming common challenges, and ensuring your styles are loaded consistently across different browsers.

1. Understanding the Challenge

When embedding HubSpot forms into your WordPress site, the forms are rendered inside an iframe. Applying custom styles directly to elements within an iframe requires a different approach than styling regular elements on your site. Moreover, different browsers (like Chrome and Firefox) may handle styles differently, particularly when it comes to pseudo-elements like ::placeholder.

Common Issues:

  • Styles not being applied consistently across browsers.
  • Styles being overridden by other CSS or not loading in the correct order.
  • Placeholder styles not appearing as intended.

2. Initial Custom Styling Approach

Let’s start with a basic approach: using JavaScript to apply styles to the HubSpot form inside the iframe. Here’s a simple example:

window.onload = function() {
    function applyStylesToIframe(iframe) {
        if (iframe && iframe.contentWindow && iframe.contentWindow.document) {
            let doc = iframe.contentWindow.document;

            // Check if the style already exists
            if (!doc.querySelector('style[data-custom-style="true"]')) {
                let style = doc.createElement('style');
                style.setAttribute('data-custom-style', 'true'); // Add an attribute to identify your custom style
                style.innerHTML = `
                    .hs-button { padding: 10px 30px !important; } 
                    .hs-input { color: #000 !important; } 
                    .hs-input::placeholder { color: #000 !important; }
                `;
                doc.head.appendChild(style);
            }
        }
    }

    function checkAndApplyStyles() {
        let myiFrame0 = document.getElementById("hs-form-iframe-0");
        let myiFrame1 = document.getElementById("hs-form-iframe-1");

        if (myiFrame0) {
            applyStylesToIframe(myiFrame0);
        }

        if (myiFrame1) {
            applyStylesToIframe(myiFrame1);
        }

        if (!myiFrame0 || !myiFrame1) {
            setTimeout(checkAndApplyStyles, 100);  // Fallback polling every 100ms
        }
    }

    checkAndApplyStyles();
};

This code injects custom styles into the iframe where the HubSpot form is rendered. However, as we found, it might not work consistently in all browsers, particularly Firefox.

3. Addressing Cross-Browser Compatibility

To ensure that your styles, especially the ::placeholder styles, work across different browsers, you need to add cross-browser CSS support:

.hs-input::-webkit-input-placeholder {
    color: #000 !important;
}
.hs-input::-moz-placeholder {
    color: #000 !important;
}
.hs-input:-moz-placeholder {
    color: #000 !important;
}
.hs-input:-ms-input-placeholder {
    color: #000 !important;
}
.hs-input::placeholder {
    color: #000 !important;
}

Adding this code ensures that your placeholder styles are correctly applied across Chrome, Firefox, Safari, and Edge.

4. Ensuring Styles Are Applied After Reset Styles

One common issue is that reset styles or global styles might override your custom styles. Here’s how to ensure your styles are applied after any reset styles:

  • Load Custom Styles Last: Place your custom styles at the end of the <head> section of your HTML.
<head>
    <!-- Other stylesheets -->
    <link rel="stylesheet" href="reset.css">
    <link rel="stylesheet" href="main.css">
    <!-- Custom styles -->
    <link rel="stylesheet" href="custom-styles.css">
</head>

Increase Selector Specificity: Use more specific selectors to ensure your styles override any reset styles.

form .hs-input::placeholder {
    color: #000 !important;
}

Inject Styles via JavaScript After the DOM Has Loaded: This ensures that your styles are applied last, after any other stylesheets or reset styles.

document.addEventListener('DOMContentLoaded', function() {
    var style = document.createElement('style');
    style.innerHTML = `
        .hs-input::placeholder {
            color: #000 !important;
        }
    `;
    document.head.appendChild(style);
});

5. Advanced: JavaScript Enhancements

In some cases, even after adding cross-browser CSS, you might need to directly manipulate the DOM using JavaScript to ensure that placeholder styles are applied as intended:

window.onload = function() {
    function applyStylesToIframe(iframe) {
        if (iframe && iframe.contentWindow && iframe.contentWindow.document) {
            let doc = iframe.contentWindow.document;

            // Check if the style already exists
            if (!doc.querySelector('style[data-custom-style="true"]')) {
                let style = doc.createElement('style');
                style.setAttribute('data-custom-style', 'true');

                style.innerHTML = `
                    .hs-button { padding: 10px 30px !important; } 
                    .hs-input { color: #000 !important; } 
                    
                    /* Cross-browser placeholder styling */
                    .hs-input::-webkit-input-placeholder {
                        color: #000 !important;
                    }
                    .hs-input::-moz-placeholder {
                        color: #000 !important;
                    }
                    .hs-input:-moz-placeholder {
                        color: #000 !important;
                    }
                    .hs-input:-ms-input-placeholder {
                        color: #000 !important;
                    }
                    .hs-input::placeholder {
                        color: #000 !important;
                    }
                `;
                doc.head.appendChild(style);
            }
        }
    }

    function checkAndApplyStyles() {
        let myiFrame0 = document.getElementById("hs-form-iframe-0");
        let myiFrame1 = document.getElementById("hs-form-iframe-1");

        if (myiFrame0) {
            applyStylesToIframe(myiFrame0);
        }

        if (myiFrame1) {
            applyStylesToIframe(myiFrame1);
        }

        if (!myiFrame0 || !myiFrame1) {
            setTimeout(checkAndApplyStyles, 100);  // Fallback polling every 100ms
        }
    }

    checkAndApplyStyles();
};

This ensures that your custom styles are injected and applied correctly, even if there are random delays in the iframe loading or if other stylesheets are loaded earlier.

6. Debugging and Final Checks

Finally, use browser developer tools (F12) to inspect the elements and verify which styles are applied. This can help you identify any conflicts or specific rules that are overriding your custom styles.

Key Takeaways:

  • Always test your styles across multiple browsers.
  • Ensure your styles are loaded last by adjusting the order in the HTML or using JavaScript.
  • Use cross-browser compatible CSS for consistent behavior.
  • Increase specificity or use !important as needed to override reset styles.

By following these best practices, you can ensure that your custom styles are applied consistently to HubSpot forms embedded on your WordPress site, providing a seamless experience for your users across all browsers.


Conclusion:

Styling embedded forms, particularly those inside iframes like HubSpot forms, requires careful consideration of cross-browser compatibility and CSS specificity. By using the techniques outlined in this guide, you can ensure your custom styles are consistently applied, resulting in a polished and professional appearance for your forms.