Search code examples
javascripthtmlcssiframetransparency

How can an iframe get its parent background color?


I have a Pardot (Salesforce) form displayed in an iframe and control over the markup and scripts on both domains. The form has a transparent background and sometimes the parent page's background photo or color does not have enough contrast with the text color of form labels. You can't read First Name when it's dark text on a dark background.

My goal is to set a body class inside the iframe that is .light-bg or .dark-bg based on a color sampling of the parent element containing the frame.

In this code the iframe would be able to determine if div.framed-lead-form has a light or dark background. There are JS plugins to get an element's color saturation (this one has an interesting license https://gist.github.com/larryfox/1636338) but I can't find anything that works through iframes.

<div class="framed-lead-form">
    <iframe src="//go.pardot.com/id" allowtransparency="true"></iframe>
</div>

Solution

  • Made a fiddle with main document and iframe.
    From main document sends theme with window post message
    From iframe listens to message and sets background theme color

    Main document: https://jsfiddle.net/kristapsv/L1fd64b3/33/

    (function($){
    
    $.fn.lightOrDark = function(){
    var r,b,g,hsp
      , a = this.css('background-color');
    
    if (a.match(/^rgb/)) {
      a = a.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/);
      r = a[1];
      b = a[2];
      g = a[3];
    } else {
      a = +("0x" + a.slice(1).replace( // thanks to jed : http://gist.github.com/983661
          a.length < 5 && /./g, '$&$&'
        )
      );
      r = a >> 16;
      b = a >> 8 & 255;
      g = a & 255;
    }
    hsp = Math.sqrt( // HSP equation from http://alienryderflex.com/hsp.html
      0.299 * (r * r) +
      0.587 * (g * g) +
      0.114 * (b * b)
    );
    if (hsp>127.5) {
      return 'light';
    } else {
      return 'dark';
    }
    }
    
    })(jQuery);
    
    var iframe = document.getElementById('my-iframe');
    
    // Set here light/dark depending on container or whatever color
    var theme =  $('.container').lightOrDark();
    
    var jsonMessage = {
      'action' : 'set-theme',
      'theme' : theme
    };
    
    iframe.contentWindow.postMessage(JSON.stringify(jsonMessage), '*');
    

    Iframe: https://jsfiddle.net/kristapsv/zLL9db1c/11/

    var messageHandler = function (event) {
      var message;
    
      try {
        message = JSON.parse(event.data);
      } catch (e) {
        return;
      }
    
      switch (message.action) {
        case 'set-theme':
            setTheme(message.theme);
            break;
      }
    };
    
    var setTheme = function(theme) {
      $('.text-container')
        .removeClass('dark')
        .removeClass('light')
        .addClass(theme);
    }
    
    window.addEventListener('message', messageHandler, false);