<div id="app"></div>
<div id="modal"></div>
html {
  background: #ccc;
  font: normal 100%/1.4 system-ui, sans-serif;
}

h1 {
  line-height: 1;
}

.app {
  background: #fff;
  overflow: hidden;
  padding: 20px;
}

.c-modal {
  height: 100vh;
  left: 0;
  position: absolute;
  top: 0;
  width: 100vw;
  z-index: 2;

  &__veil {
    background: rgba(black, 0.4);
    height: 100%;
    width: 100%;
    z-index: 0;
  }

  &__box {
    background: #fff;
    box-shadow: 0 0 10px rgba(black, 0.4);
    left: 50%;
    padding: 20px;
    position: absolute;
    text-align: center;
    transform: translate3d(-50%, -50%, 0);
    top: 50%;
    width: 250px;
    z-index: 1;
  }

  &__close {
    background: nonel;
    border: 0;
    position: absolute;
    right: 20px;
    top: 20px;
  }
}
View Compiled
// These two containers are siblings in the DOM
const appEl = document.getElementById('app');
const modalEl = document.getElementById('modal');

class Modal extends React.Component {
  constructor(props) {
    super(props);
    this.el = document.createElement('div');
  }

  componentDidMount() {
    // Append the element into the DOM on mount.
    modalEl.appendChild(this.el);
  }

  componentWillUnmount() {
    modalEl.removeChild(this.el);
  }
  
  render() {
    const { children, handleClose } = this.props;
    return ReactDOM.createPortal(
      <div className="c-modal">
        <div className="c-modal__veil" onClick={handleClose} />
        <div
          className="c-modal__box">
          <button className="c-modal__close" onClick={handleClose}>X</button>
          {children}
        </div>
      </div>,
      this.el,
    );
  }
}

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      counter: 0,
      showModal: false
    };
  }

  handleShow() {
    this.setState({showModal: true});
  }
  
  handleHide() {
    this.setState({showModal: false});
  }
  
  increment(e) {
    if (e.target.nodeName === 'BUTTON') {
      this.setState(prevState => ({
        counter: prevState.counter + 1
      }));
    }
  }

  render() {
    const { counter } = this.state;
    const { members } = this.props;
    
    const modal = this.state.showModal ? (
      <Modal handleClose={() => this.handleHide()}>
        <React.Fragment>
          <h1>Thanks for clicking!</h1>
          <p>This is being rendered inside the #modal div for {counter} {members}.</p>
          <button>Increment</button>
        </React.Fragment>
      </Modal>
    ) : null;

    return (
      <div className="app">
        <h1>My website</h1>
        <p>Welcome to my website {counter} {members}!</p>
        <button onClick={() => this.handleShow()}>Show modal</button>
        <div onClick={(e) => this.increment(e)}>
          {modal}
        </div>
      </div>
    );
  }
}

ReactDOM.render(<App members="Lifeworkers" />, appEl);
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/react/16.2.0/umd/react.development.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.2.0/umd/react-dom.development.js