ReactDOM.createPortal modal is mounted on DOM but nothing is displayed on the screen - reactjs

this is a typescript-next.js project. I have this Modal component:
interface ModalProps {
onCancelModal: () => void;
onAcceptModal: () => void;
acceptEnabled: boolean;
isLoading?: boolean;
title: string;
}
const Modal: React.FC<ModalProps> = (props) => {
let containerRef = useRef<HTMLDivElement | null>(null);
console.log("container", containerRef);
useEffect(() => {
const rootContainer = document.createElement("div");
const parentElem = document.querySelector("#__next");
parentElem?.insertAdjacentElement("afterend", rootContainer);
if (!containerRef.current) {
containerRef.current = rootContainer;
}
return () => rootContainer.remove();
}, []);
return containerRef.current
? ReactDOM.createPortal(
<div className="modal">
<header className="modal__header">
<h1>{props.title}</h1>
</header>
<div className="modal__content">{props.children}</div>
<div className="modal__actions">
<Button design="danger" mode="flat" onClick={props.onCancelModal}>
Cancel
</Button>
<Button
mode="raised"
onClick={props.onAcceptModal}
disabled={!props.acceptEnabled}
loading={props.isLoading}
>
Accept
</Button>
</div>
</div>,
containerRef.current
)
: null;
};
export default Modal;
I pass a custom error to ErrorHandler component:
const ErrorHandler: React.FC<ErrorHandlerProps> = (props) => (
<Fragment>
{props.error && <Backdrop onClick={props.onHandle} />}
{props.error && (
<Modal
title="An Error Occurred"
onCancelModal={props.onHandle}
onAcceptModal={props.onHandle}
acceptEnabled
>
<p>{props.error}</p>
</Modal>
)}
</Fragment>
);
However, Modal component is successfully mounted on the DOM but nothing displays on the screen.
EDIT
I have backdrop and modal components.
// css for backdrop
.backdrop {
width: 100%;
height: 100vh;
background: rgba(0, 0, 0, 0.75);
z-index: 100;
position: fixed;
left: 0;
top: 0;
transition: opacity 0.3s ease-out;
opacity: 1;
}
// css for Modal
.modal {
position: fixed;
width: 90%;
left: 5%;
top: 20vh;
background: white;
border-radius: 5px;
z-index: 200;// I changed this to 999999 but didnot solve the issue
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
}
.modal__header {
border-bottom: 2px solid #3b0062;
}
.modal__header h1 {
font-size: 1.5rem;
color: #3b0062;
margin: 1rem;
}
.modal__content {
padding: 1rem;
}
.modal__actions {
padding: 1rem;
text-align: right;
}
.modal__actions button {
margin: 0 0.5rem;
}
#media (min-width: 768px) {
.modal {
width: 40rem;
left: calc((100% - 40rem) / 2);
}
}

I found the answer after i refresh my memory. I realized that there is another .modal className on elements-styles tab. It points me to the /node_modules/bootstrap/scss/_modal.scss file which also has modal className and it was overriding my custom className.
.modal {
position: fixed;
top: 0;
left: 0;
z-index: $zindex-modal;
display: none;
width: 100%;
height: 100%;
overflow: hidden;
// Prevent Chrome on Windows from adding a focus outline. For details, see
// https://github.com/twbs/bootstrap/pull/10951.
outline: 0;
// We deliberately don't use `-webkit-overflow-scrolling: touch;` due to a
// gnarly iOS Safari bug: https://bugs.webkit.org/show_bug.cgi?id=158342
// See also https://github.com/twbs/bootstrap/issues/17695
}

Related

How do I dynamically add a div where mouse was clicked in React?

I'm new to react and wonder how to do weird code stuff. I have a div component that I need to add child divs to depending on where I clicked on the div. I could do this easily in vanilla JS - here is a code sandbox of JS of what I want to do : https://codepen.io/Webasics/pen/YXXyEO
here is what I have in react so far (this is inside my App component):
const imgAdder = (e) => {
console.log(e.pageX, e.pageY)
}
<main onClick={imgAdder} </main>
$(document).ready(function() {
$(this).click(function(e) {
var x = e.pageX;
var y = e.pageY;
$('<div/>').css({
'top': y,
'left': x
}).appendTo('body');
});
});
div {
background-color: red;
width: 50px;
height: 50px;
position: absolute;
transform: translate(-50%, -50%);
/* optional */
border: 1px solid black;
/* optional */
}
h2 {
z-index: 10;
/* optional */
/* This always keeps the title on top*/
position: absolute;
}
body {
background-color: #E1E7E8;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h2>Click anywhere</h2>
Any directions would be lovely ! thank you.
function App() {
// declare array of boxes
const [boxes, setBoxes] = useState([]);
const handleClick = ({ pageX, pageY }) => {
// on every click push a new coordinate to the boxes array
setBoxes((boxes) => [...boxes, { x: pageX, y: pageY }]);
};
return (
<div className="app" onClick={handleClick}>
// display boxes
{boxes.map((box) => (
// map coordinates to left and top
<div className="box" style={{ left: box.x, top: box.y }}></div>
))}
</div>
);
}
Styles, mostly copied from the codepen
.app {
width: 100%;
height: 100vh;
}
.box {
position: absolute;
width: 50px;
height: 50px;
background: red;
transform: translate(-50%, -50%);
}
sandbox
Weird, but I like it!
https://codesandbox.io/s/elated-meadow-zuerrg?file=/src/App.js
I would simply use useEffect to register a click handler on the document and on click, add elements to a state array.
Finally, render those elements onto the page.
import { useEffect, useState } from "react";
import "./styles.css";
export default function App() {
const elements = useDynamicElements();
return (
<>
<h2>Click anywhere</h2>
{elements}
</>
);
}
const useDynamicElements = () => {
const [state, setState] = useState([]);
useEffect(() => {
const handler = (event) => {
setState((previous) => [
...previous,
<div style={{ top: event.pageY, left: event.pageX }} />
]);
};
document.addEventListener("click", handler);
return () => document.removeEventListener("click", handler);
});
return state;
};
An over simplified example in React could be like this:
This version can run in the snippets below for convenience.
const App = () => {
const [boxList, setBoxList] = React.useState([]);
const handleClick = (e) => {
if (e.target.classList.contains("btn")) {
setBoxList([]);
return;
}
setBoxList((prev) => {
const { pageX, pageY } = e;
const newBox = { left: pageX, top: pageY };
return [...prev, newBox];
});
};
return (
<div className="app" onClick={handleClick}>
<button className="btn">CLEAN UP</button>
<h2>Click anywhere</h2>
{boxList.length > 0 &&
boxList.map((box, index) => (
<div className="box" style={{ top: box.top, left: box.left }} key={index}></div>
))}
</div>
);
};
ReactDOM.render(<App />, document.querySelector("#root"));
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.app {
width: 100%;
height: 100vh;
background-color: pink;
position: relative;
}
.box {
background-color: #000;
width: 50px;
height: 50px;
position: absolute;
transform: translate(-50%, -50%);
border: 1px solid black;
}
h2 {
top: 50%;
left: 50%;
position: absolute;
transform: translate(-50%, -50%);
}
.btn {
margin: 15px;
padding: 15px;
background-color: #fff;
border: 0;
border-radius: 12px;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.production.min.js"></script>

Mapped buttons that have opacity of 0 are showing, and are overlapping when resizing the window

I've successfully mapped over text and have styled it with transition effects when going from one slide to the next as you can see here:
Following a similar concept with buttons isn't working. There should only be one button active per slide like you see here:
I want the buttons to have the same effect as the text, but I'm getting behaviors like you see here:
As you can see, there is no transition effect on the button when clicking to the second slide, and it also appears in a lower spot.
And lastly, when resizing the window, buttons are overlapping like you see here:
Don't know what to try next.
Here's the ImageSlider component:
import { useState } from "react";
import { SliderData } from "../data";
import { categories } from "../data";
import ShopNowButtonActive from "./ShopNowButtonActive";
import { IoIosArrowBack } from "react-icons/io";
import { IoIosArrowForward } from "react-icons/io";
import "./ImageSlider.css";
import ShopNowButton from "./ShopNowButton";
const ImageSlider = ({ slides }) => {
const [current, setCurrent] = useState(0);
const length = slides.length;
const nextSlide = () => {
setCurrent(current === length - 1 ? 0 : current + 1);
};
const prevSlide = () => {
setCurrent(current === 0 ? length - 1 : current - 1);
};
return (
<div className="slider">
<IoIosArrowBack className="left-arrow" onClick={prevSlide} />
{SliderData.map((slide, index) => (
<div key={slide.id}>
<img
src={slide.img}
alt=""
className={index === current ? "slide active" : "slide"}
/>
<div className="info-container">
<div className={index === current ? "title active" : "title"}>
{slide.title}
</div>
<div className={index === current ? "desc active" : "desc"}>
{slide.desc}
</div>
{categories.map((item, index) =>
index === current ? (
<ShopNowButtonActive item={item} />
) : (
<ShopNowButton item={item} />
)
)}
</div>
</div>
))}
<IoIosArrowForward className="right-arrow" onClick={nextSlide} />
</div>
);
};
export default ImageSlider;
The css file:
.slider {
height: 90vh;
margin-bottom: 0.5rem;
}
.left-arrow {
position: absolute;
top: 45%;
left: 32px;
font-size: 2rem;
cursor: pointer;
opacity: 0.5;
z-index: 1;
}
.slide.active {
opacity: 1;
width: 100%;
height: 88%;
object-fit: cover;
object-position: center;
-webkit-clip-path: polygon(100% 0, 100% 80%, 50% 100%, 0 80%, 0% 0%);
clip-path: polygon(100% 0, 100% 80%, 50% 100%, 0 80%, 0% 0%);
}
.slide {
opacity: 0;
transition: 500ms opacity ease-in-out;
width: 100%;
height: 88%;
object-fit: cover;
object-position: center;
position: absolute;
-webkit-clip-path: polygon(100% 0, 100% 80%, 50% 100%, 0 80%, 0% 0%);
clip-path: polygon(100% 0, 100% 80%, 50% 100%, 0 80%, 0% 0%);
}
.info-container {
display: flex;
flex-direction: column;
width: 40%;
height: 100%;
position: absolute;
top: 45%;
right: 30px;
}
.title.active {
opacity: 1;
transition-delay: 700ms;
font-size: 4rem;
}
.title {
opacity: 0;
transition: 200ms opacity ease-in-out;
font-size: 4rem;
}
.desc.active {
opacity: 1;
padding-top: 1.5em;
transition-delay: 700ms;
font-size: 1.25rem;
font-weight: 500;
letter-spacing: 3px;
}
.desc {
opacity: 0;
padding-top: 1.5em;
transition: 200ms opacity ease-in-out;
font-size: 1.25rem;
font-weight: 500;
letter-spacing: 3px;
}
.right-arrow {
position: absolute;
top: 45%;
right: 32px;
font-size: 2rem;
cursor: pointer;
opacity: 0.5;
z-index: 1;
}
The ShopNowButtonActive component:
import React from "react";
import styled from "styled-components/macro";
import { Link } from "react-router-dom";
const ButtonActive = styled.button`
opacity: 1;
padding: 0.5rem;
margin-top: 2.5rem;
width: 8rem;
font-size: 20px;
background-color: transparent;
cursor: pointer;
transition-delay: 700ms;
`;
const ShopNowButtonActive = ({ item }) => {
return (
<Link to={`/products/${item.cat}`}>
<ButtonActive>SHOP NOW</ButtonActive>
</Link>
);
};
export default ShopNowButtonActive;
And finally, the ShopNowButton component:
import React from "react";
import styled from "styled-components/macro";
import { Link } from "react-router-dom";
const Button = styled.button`
opacity: 0;
/* display: none; */
padding: 0.5rem;
margin-top: 2.5rem;
width: 8rem;
font-size: 20px;
background-color: transparent;
cursor: pointer;
transition: 200ms opacity ease-in-out;
`;
const ShopNowButton = ({ item }) => {
return (
<Link to={`/products/${item.cat}`}>
<Button>SHOP NOW</Button>
</Link>
);
};
export default ShopNowButton;
(Sorry for the use of both an external css file and styled components.)
Any suggestions?
I have recreated the above scenario using some static data. I have modified some of the css. It is working as expected. I also observed that the only major difference between ShopNowButton and ShopNowButtonActive was opacity property which hides the element. The reason you are observing 2 buttons because they were all there in the dom actually.(They were not hiding properly due to which we are observing more shop now buttons and every time we click on next icon the corresponding button is being displayed. Basically all the buttons are there on the page itself.)
Please find the sandbox url below.
https://codesandbox.io/s/stackoverflow-6u05e7?file=/src/ImageSlider/ImageSlider.js

Closing modal window by clicking on backdrop (ReactJS)

Could you please help me with one issue? I'd like to make a closing modal window by clicking on backdrop (using ReactJS). But in result window is closing even i click on modal window (at any position).
Here is my code:
import React from "react";
import { Fragment } from "react";
import ReactDOM from "react-dom";
import "./_Modal.scss";
const Backdrop = (props) => {
return (
<div className="backdrop" onClick={props.onClose}>
{props.children}
</div>
);
};
const ModalOverlay = (props) => {
return <div className="modal">{props.children}</div>;
};
const portalItem = document.getElementById("overlays");
const Modal = (props) => {
return (
<Fragment>
{ReactDOM.createPortal(
<Backdrop onClose={props.onClose}>
<ModalOverlay>{props.children}</ModalOverlay>
</Backdrop>,
portalItem
)}
</Fragment>
);
};
export default Modal;
And here is CSS:
.backdrop {
position: fixed;
top:0;
left: 0;
width: 100%;
height: 100vh;
z-index: 20;
background-color: rgba(0,0,0, 0.7);
display: flex;
justify-content: center;
align-items: flex-start;
overflow: auto;
padding-bottom: 15vh;
}
.modal {
position: relative;
max-width: 70%;
top: 5vh;
background-color: $darkgrey;
padding: 1rem;
border-radius: 1.5rem;
box-shadow: 0 1rem 1rem rgba(0,0,0, 0.25);
z-index: 30;
}
}
I'm just start to learning frontend, therefore do not judge strictly )
Just for understanding other people: after adding event.stopPropagation() in ModalOverlay everything works!
const ModalOverlay = (props) => {
return (
<div
className="modal"
onClick={(event) => {
event.stopPropagation();
}}
>
{props.children}
</div>
);
};

React Carousel target div elements

I am learning to make custom Carousel by using React and Typescript. For styling I used styled components and scss. I found from one Article how to make Carousel. My carousel works fine.
I have made four div elements. when the carousel image slide will change, I want to change background-color of the div elements inot orange color. But Don't know how to do that.
I share my code in codesandbox
This is my Carousel component
import React, { useState, useEffect, useRef, memo, useCallback } from "react";
import styled from "styled-components";
interface ICarousel {
children: JSX.Element[];
currentSlide?: number;
autoPlay?: boolean;
dots?: boolean;
interval?: number;
arrow?: boolean;
}
const IMG_WIDTH = 320;
const IMG_HEIGHT = 700;
export default memo(
({
children,
autoPlay = false,
dots = false,
interval = 3000,
arrow = false
}: ICarousel) => {
const [currentSlide, setSlide] = useState(0);
const [isPlaying, setIsPlaying] = useState(autoPlay);
const timer = useRef<any>(undefined);
const slides = children.map((slide, index) => (
<CarouselSlide key={index}>{slide}</CarouselSlide>
));
const handleSlideChange = useCallback(
(index: number) =>
setSlide(
index > slides.length - 1 ? 0 : index < 0 ? slides.length - 1 : index
),
[slides]
);
const createInterval = useCallback(() => {
timer.current = setInterval(() => {
handleSlideChange(currentSlide + 1);
}, interval);
}, [interval, handleSlideChange, currentSlide]);
const destroyInterval = useCallback(() => {
clearInterval(timer.current);
}, []);
useEffect(() => {
if (autoPlay) {
createInterval();
return () => destroyInterval();
}
}, [autoPlay, createInterval, destroyInterval]);
return (
<CarouselContainer
onMouseEnter={() => {
if (autoPlay) {
destroyInterval();
}
}}
onMouseLeave={() => {
if (autoPlay) {
createInterval();
}
}}
>
<CarouselSlides currentSlide={currentSlide}>{slides}</CarouselSlides>
{arrow ? (
<div>
<LeftButton onClick={() => handleSlideChange(currentSlide - 1)}>
❮
</LeftButton>
<RightButton onClick={() => handleSlideChange(currentSlide + 1)}>
❯
</RightButton>
</div>
) : null}
{dots ? (
<Dots>
{slides.map((i, index) => (
<Dot
key={index}
onClick={() => handleSlideChange(index)}
active={currentSlide === index}
/>
))}
</Dots>
) : null}
</CarouselContainer>
);
}
);
const Buttons = styled.a`
cursor: pointer;
position: relative;
font-size: 18px;
transition: 0.6s ease;
user-select: none;
height: 50px;
width: 40px;
display: flex;
justify-content: center;
align-items: center;
align-content: center;
top: calc(50% - 25px);
position: absolute;
&:hover {
background-color: rgba(0, 0, 0, 0.8);
}
`;
const RightButton = styled(Buttons)`
border-radius: 3px 0 0 3px;
right: 0;
`;
const LeftButton = styled(Buttons)`
border-radius: 0px 3px 3px 0px;
left: 0;
`;
const Dots = styled.div`
display: flex;
justify-content: center;
align-items: center;
align-content: center;
margin-top: 10px;
`;
const Dot = styled.span<{ active: boolean }>`
cursor: pointer;
height: 15px;
width: 15px;
margin: 0 10px;
border-radius: 50%;
display: inline-block;
transition: background-color 0.6s ease;
background-color: ${({ active }) => (active ? `red` : `#eeeeee`)};
`;
const CarouselContainer = styled.div`
overflow: hidden;
position: relative;
width: ${IMG_WIDTH}px;
height: ${IMG_HEIGHT}px;
img {
/* change the margin and width to fit the phone mask */
width: ${IMG_WIDTH - 20}px;
height: ${IMG_HEIGHT - 50}px;
margin-left: 10px;
margin-top: 15px;
}
z-index: 1;
`;
const CarouselSlide = styled.div`
flex: 0 0 auto;
transition: all 0.5s ease;
width: 100%;
`;
const CarouselSlides = styled.div<{
currentSlide: ICarousel["currentSlide"];
}>`
display: flex;
${({ currentSlide }) =>
` transform: translateX(-${currentSlide ? currentSlide * 100 + `%` : 0})`};
transition: transform 300ms linear;
cursor: pointer;
`;
This where I am using the Carousel component
import * as React from "react";
import "./styles.scss";
import Carousel from "./carousel";
export const imgUrls = [
`https://images.unsplash.com/photo-1455849318743-b2233052fcff?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=900&q=60`,
`https://images.unsplash.com/photo-1508138221679-760a23a2285b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=900&q=60`,
`https://images.unsplash.com/photo-1519125323398-675f0ddb6308?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=900&q=60`,
`https://images.unsplash.com/photo-1494253109108-2e30c049369b?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=900&q=60`
];
export default function App() {
return (
<div className="App">
<main className="Testeru">
<div className="phone-left">
// I want change background color of this div element
<div className="phone-left-upper">left upper</div>
<div className="phone-left-lower">left-lower</div>
</div>
<div className="phone-slider">
<div className="mobile_overlay">
<Carousel autoPlay>
{imgUrls.map((i) => {
return (
<img
key={i}
src={i}
alt=""
style={{
borderRadius: `20px`
}}
/>
);
})}
</Carousel>
</div>
</div>
// I want change background color of this div element
<div className="phone-right">
<div className="phone-right-upper">right upper</div>
<div className="phone-right-lower">right-lower</div>
</div>
</main>
</div>
);
}

react Portal - how to close modal when clicking outside of modal and how to assign ref to modal inside parent component rendering modal?

I am using react portal and want to make it possible that modal closes when user clicks outside of modal. I am creating a ref inside my parent,but cannot really assign it to the modal itself as react portals arent actual DOM nodes (as I understood). I can also not wrap around this.props.children inside a div and assign it a ref inside my Modal component also, because then I cannot access and use it inside my Parent component.
What can I do? Thanks!
my modal:
import React from 'react';
import { createPortal } from 'react-dom';
const modalRoot = document.getElementById( 'modal' );
class Modal extends React.Component {
constructor( props ) {
super( props );
this.element = document.createElement( 'div' );
}
componentDidMount() {
modalRoot.appendChild( this.element );
}
componentWillUnmount() {
modalRoot.removeChild( this.element );
}
render() {
return createPortal(this.props.children, document.querySelector('#modal'));
}
}
the parent component rendering modal:
class Parent extends React.Component {
constructor (props) {
super(props);
this.state = {
showModal: false
};
this.modal=React.createRef();
}
showModal = () => {
this.setState({
showModal: !this.state.showModal
})
};
closeModal = (e) => {
if (this.modal.current.contains(e.target)) {
return;
} else {
this.showModal()
}
}
componentDidMount () {
document.addEventListener('click', this.closeModal, false)
}
componentWillUnmount() {
document.removeEventListener('click', this.closeModal, false)
}
render () {
const {src, height, width} = this.props;
return (
<React.Fragment>
<img
className="image"
src={src}
onClick={this.showModal}
/>
{
this.state.showModal ? (
<Modal>
<div className="my-modal">
<h1 >Heading</h1>
<p>Lorem ipsum </p>
<button
className="modal-close"
onClick={this.showModal}
>X
</button>
</div>
</Modal>
) : null
}
</React.Fragment>
)
}
};
Since the click listener will be applied to all modal instances, I'd move the listener and the ref to a reuseable modal component -- now it'll control clicks once opened. The only thing it really needs is a passed down toggle modal function prop from the parent.
Working example:
components/Modal/index.js
import React, { Fragment, PureComponent } from "react";
import { createPortal } from "react-dom";
import PropTypes from "prop-types";
class Modal extends PureComponent {
componentDidMount() {
document.addEventListener("click", this.closeModal, false);
}
componentWillUnmount() {
document.removeEventListener("click", this.closeModal, false);
}
closeModal = ({ target }) => {
if (this.modal && !this.modal.contains(target)) {
this.props.toggleModal();
}
};
render = () =>
createPortal(
<Fragment>
<div className="overlay" />
<div className="window-container">
<div className="modal-container">
<div ref={node => (this.modal = node)} className="modal">
{this.props.children}
</div>
</div>
</div>
</Fragment>,
document.body
);
}
Modal.propTypes = {
children: PropTypes.node.isRequired,
toggleModal: PropTypes.func.isRequired
};
export default Modal;
components/Parent/index.js
import React, { Component } from "react";
import Modal from "../Modal";
class Parent extends Component {
state = {
showModal: false
};
toggleModal = () => {
this.setState(prevState => ({
showModal: !prevState.showModal
}));
};
render = () => (
<div className={`${this.state.showModal ? "blur" : undefined} app`}>
<img
src="https://i.imgur.com/BGwgr3A.jpg"
className="image"
alt="example.png"
onClick={this.toggleModal}
/>
{this.state.showModal && (
<Modal toggleModal={this.toggleModal}>
<h1 className="title">Hello!</h1>
<p className="subtitle">There are two ways to close this modal</p>
<ul>
<li>Click outside of this modal in the grey overlay area.</li>
<li>Click the close button below.</li>
</ul>
<button
className="uk-button uk-button-danger uk-button-small"
onClick={this.toggleModal}
>
Close
</button>
</Modal>
)}
</div>
);
}
export default Parent;
styles.css
.app {
text-align: center;
margin-top: 20px;
}
.blur > img {
-webkit-filter: blur(10px);
-moz-filter: blur(10px);
-ms-filter: blur(10px);
-o-filter: blur(10px);
filter: blur(10px);
}
.image {
display: block;
margin: 0 auto;
cursor: pointer;
width: 600px;
}
.modal {
max-width: 600px;
max-height: calc(100% - 96px);
padding: 20px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
position: relative;
overflow-y: auto;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-shadow: 0px 11px 15px -7px rgba(0, 0, 0, 0.2),
0px 24px 38px 3px rgba(0, 0, 0, 0.14), 0px 9px 46px 8px rgba(0, 0, 0, 0.12);
box-shadow: 0px 11px 15px -7px rgba(0, 0, 0, 0.2),
0px 24px 38px 3px rgba(0, 0, 0, 0.14), 0px 9px 46px 8px rgba(0, 0, 0, 0.12);
border-radius: 4px;
background-color: #fff;
text-align: left;
}
.modal-container {
opacity: 1;
-webkit-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
-o-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
height: 100%;
outline: none;
}
.overlay {
opacity: 1;
-webkit-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
-o-transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
transition: opacity 225ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: -1;
position: fixed;
-ms-touch-action: none;
touch-action: none;
background-color: rgba(0, 0, 0, 0.5);
-webkit-tap-highlight-color: transparent;
}
.subtitle {
margin: 0;
text-align: center;
font-weight: bold;
}
.title {
text-align: center;
}
.window-container {
text-align: center;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: auto;
outline: 0;
-webkit-animation: fadeIn 0.2s 0s ease-in-out forwards;
animation: fadeIn 0.2s 0s ease-in-out forwards;
z-index: 100;
}

Resources