Search code examples
reactjsinternet-explorer-9componentsrender

React.js how to return commented video tag for ie9 support


Let's say in React I want to support ie9 by wrapping my code, as this example for picturefill does:

<picture>
  <!--[if IE 9]><video style="display: none;"><![endif]-->
  <source srcset="examples/images/extralarge.jpg" media="(min-width: 1000px)">
  <source srcset="examples/images/large.jpg" media="(min-width: 800px)">
  <!--[if IE 9]></video><![endif]-->
  <img srcset="examples/images/medium.jpg" alt="…">
</picture>

In react, that would be:

return (
                <picture>
                <!--[if IE 9]><video style="display: none;"><![endif]-->
                <source type="image/webp" className="full-photo2 slide-init" srcSet={"./build/assets/images/photos/responsive/webp/" + image.id + "-400.webp 400w, ./build/assets/images/photos/responsive/webp/" + image.id + "-800.webp 800w, ./build/assets/images/photos/responsive/webp/" + image.id + "-1000.webp 1000w,"} />
                <img className="full-photo2 slide-init" srcSet={"./build/assets/images/photos/responsive/jpg/" + image.id + "-400.jpg 400w, ./build/assets/images/photos/responsive/jpg/" + image.id + "-800.jpg 800w, ./build/assets/images/photos/responsive/jpg/" + image.id + "-1000.jpg 1000w,"} />
                <!--[if IE 9]></video><![endif]-->  
            </picture>
 )

Of course, React gets angry about this.

So how can you return IE9 hacks like this in your React returns?


Solution

  • With all the caveats about using dangerouslySetInnerHTML as per the above link, this is what I have made work (using ES6):-

    const createMarkup = () => {
      return  {__html:
        `<!--[if IE 9]><video style="display: none;"><![endif]-->
        <source srcSet="examples/images/extralarge.jpg" media="(min-width: 1000px)">
        <source srcSet="examples/images/large.jpg" media="(min-width: 800px)">
        <!--[if IE 9]></video><![endif]-->
        <img src="examples/images/medium.jpg" alt="…">`
      };
    };
    
    return (
      <picture dangerouslySetInnerHTML={createMarkup()}>
      </picture>
    )
    

    You can of course also pass arguments into the createMarkup function and interpolate those within the template string as placeholders using the ${ } syntax (Getting Literal With ES6 Template Strings):-

    const createMarkup = (path) => {
      return  {__html:
        `<!--[if IE 9]><video style="display: none;"><![endif]-->
        <source srcSet="${path}extralarge.jpg" media="(min-width: 1000px)">
        <source srcSet="${path}large.jpg" media="(min-width: 800px)">
        <!--[if IE 9]></video><![endif]-->
        <img src="${path}medium.jpg" alt="…">`
      };
    };
    
    return (
      <picture dangerouslySetInnerHTML={createMarkup('examples/images/')}>
      </picture>
    )