A good[ish] website

Web development blog, loads of UI and JavaScript topics

Perfect iframe React component

Filed under: UI components— Tagged with: React, HTML

Here’s a cool iframe component that loads fast, is accessible, and easy on the eyes.

I’m thinking the iframe (Inline Frame) should have the following things:

  • Accessible: easy, because iframes have no major accessibility issues.
  • Optional caption: iframes can also be wrapped in <figure>.
  • Lazy loading: for page speed (user experience).
  • Fluid width: for responsive layouts.
  • Good looks: for the soul.

The React component

See the highlighted lines and the breakdown below.

import React from 'react'
import PropTypes from 'prop-types'
import { Iframe, Figure, Figcaption } from './styles'

const IframeComponent = props => {
  const { caption, width } = props

  return (
    <Figure width={width}>      <Iframe {...props} frameBorder={0} hasCaption={Boolean(caption)} />
      {caption && <Figcaption>{caption}</Figcaption>}

const srcPropsCheck = (props, propName, componentName) => {  if (!props.src && !props.srcDoc) {
    return new Error(
      `One of 'src' or 'srcData' is required by '${componentName}' component.`

IframeComponent.defaultProps = {
  loading: 'lazy',  height: 500,
  sandbox: ''}

IframeComponent.propTypes = {
  caption: PropTypes.string,
  height: PropTypes.number,
  loading: PropTypes.oneOf(['lazy', 'eager']),  sandbox: PropTypes.string,
  src: srcPropsCheck,
  srcDoc: srcPropsCheck,  title: PropTypes.string.isRequired,  width: PropTypes.number

export default IframeComponent

Here’s the interesting bits:

The figure element can be there even if caption is not provided, it’s valid HTML. It also serves as a flex wrapper for the fluid width iframe.
PropTypes helper can take a custom validation function, this checks thatsrc or srcdoc are passed in.
loading: 'lazy'
This is the browser’s native loading attribute, which can be added to images or iframes. It’s still not supported in Safari and some other runt-of-the-litter-browsers, but its global usage is 71.38% (at the time of writing this).
This "sandboxes" the iframe even more strongly, meaning the frame can’t submit forms, or allow downloads etc. see the whole list of values you can pass into the sandbox attribute. If just the attribute is present with no value, all the restrictions are applied.
Iframe can receive data as a string, if srcDoc is used src can be skipped.
In images et al, title attribute doesn’t do much for accessibility, but in iframes it’s an important addition. It should describe the iframe somehow.


I’s using styled-components in this case, but there’s nothing special here that wouldn’t work with vanilla CSS or another CSS-in-JS lib:

import styled from 'styled-components'

export const Figure = styled.figure(props => ({
  margin: '0 0 20px 0',
  ...(props.width    ? { width: props.width }
    : {
        display: 'flex',
        flexDirection: 'column',
        overflow: 'hidden',
        width: '100%'

export const Figcaption = styled.figcaption({
  margin: 0,
  fontSize: '85%',

export const Iframe = styled.iframe(props => ({
  border: '1px solid gray',
  flexGrow: 1,  marginBottom: props.hasCaption ? '3px' : '5px',
  padding: 0
If we have a fixed width, then use it, if not then render as a fluid width flex container.
flexGrow: 1
Iframe should fill the whole wrapper.


Good thing is that there are no big accessibility issues with iframes, just remember to provide the title.

...descriptive title attribute value is not required for accessibility, but if the inline frame presents content as a whole that is visually distinctive, such as an advertisement or video player, then a title should be provided to indicate this distinction. WebAIM


There’s not too much to demo, but here’s an iframe from this website:

  caption="This website’s 404 page loaded into an iframe"
  title="404 page example"

It adapts nicely to the page width:

This website’s 404 page loaded into an iframe


There’s some amount of mysticism around the safety of iframes, just remember not embed dodgy sites, same way you wouldn’t provide a link to a dodgy site. If iframes are used for same origin URLs there’s not much to worry about.

The irony of iframes is that you should block other sites from embedding your site, to prevent clickjacking etc. It can be done by setting the X-Frame-Options header value to DENY.

Comments would go here, but the commenting system isn’t ready yet, sorry.

  • © 2022 Antti Hiljá
  • About
  • All rights reserved yadda yadda.
  • I can put just about anything here, no one reads the footer anyways.
  • I love u!