Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic sizing of the modal #62

Closed
molson504x opened this issue Aug 19, 2015 · 20 comments
Closed

Dynamic sizing of the modal #62

molson504x opened this issue Aug 19, 2015 · 20 comments

Comments

@molson504x
Copy link

Does anyone know how to dynamically size the modal? For example, if I hard-coded the width of some content to be 100px wide, and the app element that the modal is bound to is 200px wide, I want the modal to be centered in the window at 100px wide. Any ideas?

@davidmfoley
Copy link

Here is a hack I used to do a similar thing, vertically rather than horizontally.

  • Add a ref name (ie: ref='content') to your content container div.
  • Grab the height of the content container element once it is in the DOM and put it in state:
  componentDidUpdate() {
    if (window.requestAnimationFrame) {
      window.requestAnimationFrame(this.sizeDialog);
    }
    else {
      // IE <10 CYA - Note: I haven't actually tested this in IE - YMMV
      window.setTimeout(this.sizeDialog, 50);
    }
  }

  sizeDialog = () => {
    if (!this.refs.content) return;
    let contentHeight = this.refs.content.getBoundingClientRect().height;
    this.setState({
      contentHeight: contentHeight,
    });
  }

Note that use requestAnimationFrame here - the ref was not yet defined otherwise. Maybe this has to do with the DOM magic react-modal does... At any rate this is a hack and I'm sure there is a better way to do this.

  • In render(), use this.state.contentHeight to style the dialog:
    const padding = 90; // adjust this to your needs
    let height = (this.state.contentHeight + padding);
    let heightPx = height + 'px';
    let heightOffset = height / 2;
    let offsetPx = heightOffset + 'px';

    const style = {
      content: {
        border: '0',
        borderRadius: '4px',
        bottom: 'auto',
        height: heightPx,  // set height
        left: '50%',
        padding: '2rem',
        position: 'fixed',
        right: 'auto',
        top: '50%', // start from center
        transform: 'translate(-50%,-' + offsetPx + ')', // adjust top "up" based on height
        width: '40%',
        maxWidth: '40rem'
      }
    };

    return (
      <Modal isOpen={this.props.show} style={style} className='dialog'>
        <div className='dialog__content' ref='content'>
        ... your content goes here ...
        </div>
      </Modal>
    );

Hope this helps.

@alopes
Copy link

alopes commented Dec 13, 2015

Thanks @davidmfoley.
It works quite well.

@molson504x
Copy link
Author

Nice @davidmfoley

@davidmfoley
Copy link

No problem.

We are now using pure CSS to size the modal, which works as long as you style the components in the modal so that they result in proper width/height, relieving the need for any requestAnimationFrame/manual coordinate math:

...
      content: {
        border: '0',
        borderRadius: '4px',
        bottom: 'auto',
        minHeight: '10rem',
        left: '50%',
        padding: '2rem',
        position: 'fixed',
        right: 'auto',
        top: '50%',
        transform: 'translate(-50%,-50%)',
        minWidth: '20rem',
        width: '80%',
        maxWidth: '60rem'
      }
...

@crisu83
Copy link

crisu83 commented Apr 16, 2016

Thanks for the pure CSS solution!

@claydiffrient
Copy link
Contributor

It's been a while since there was any discussion on this issue. I'm assuming that it isn't a problem anymore. If it is, feel free to re-open the issue.

@amangeot
Copy link

amangeot commented Apr 15, 2017

Hello guys,
did you find a solution to let the modal resize to fit its content's width, centering the modal in the window, without disabling vertical scrolling of the modal ? The modal should move, not the content inside the modal.

@anthony2025
Copy link

anthony2025 commented Apr 26, 2017

@amangeot As David pointed out, the layout breaks if the children inside the modal exceed the dimensions of the viewport, but defining maximum dimensions for a child container in viewport units should take care of that. Using his code I ended up doing this:

.modalClass {
  position: fixed;
  top: 50%;
  right: auto;
  bottom: auto;
  left: 50%;
  transform: translate(-50%,-50%);
  outline: 0;
}

.childDiv {
  max-height: 90vh;
  max-width: 90vw;
}

At least for the image previews I am using it for, it seems to work really well, even on mobile.

@mohandere
Copy link

mohandere commented Oct 12, 2017

I get this fixed by writing HOC where i am using refs to get content/modal height.

Link - https://gist.github.com/mohandere/b563d19f5f1c7bf027fd7129592e9ab8

@slassen
Copy link

slassen commented Jan 22, 2018

Here's how I do it with my modals.

content: {
  border: '1px solid #ccc', background: '#fff',
  overflow: 'auto', WebkitOverflowScrolling: 'touch',
  borderRadius: '4px', outline: 'none', padding: '20px',
  top: '50%', left: '50%', right: 'auto', bottom: 'auto',
  marginRight: '-50%', transform: 'translate(-50%, -50%)',
}

@sialvsic
Copy link

sialvsic commented Jan 31, 2018

import Modal from 'react-modal';
import PropTypes from 'prop-types';
import styled from 'styled-components';

const CustomStyles = {
  overlay: {
    backgroundColor: 'rgba(32, 40, 46, 0.5)',
    display: 'flex',
    'align-items': 'center',
  },
};

export const StyledModal = styled(Modal)`
  position: relative;
  overflow: auto;
  outline: none;
  margin: auto;
  top: 0px;
  left: 0px;
  right: 0px;
  bottom: 0px;
  box-shadow: 0 5px 20px 0 rgba(0, 0, 0, 0.5);
  border-radius: 8px;
  width: 290px;
`;

<StyledModal isOpen={ isModalOpen } onRequestClose={ onCloseModal } contentLabel={ "Modal" }
                   style={ CustomStyles } >
        <InvisibleButtonWrapper/>
        <div> content here</div>
 </StyledModal>

@danderson00
Copy link

It would seem there are enough people asking for this feature. It's not sufficient to declare static CSS classes as this doesn't meet the needs of the OP - i.e. dynamic modal sizes.

It would be relatively trivial to implement additional props on the Modal component that affect the size.

laimison added a commit to laimison/react-rails that referenced this issue Dec 17, 2018
@Sislar
Copy link

Sislar commented Jun 16, 2020

Late to the game but not following how to dynamically size the modal. What I see is that the dialog width is set to 50%, (.popup-content width:50%). That ends up being 50% of the viewport. If I constrain the width of the contents that makes the content smaller but there is still a bounding rect that is 50% of the viewport.

div class="popup-content " style="position: relative; background: rgb(255, 255, 255); width: 50%; margin: auto; border: 1px solid rgb(187, 187, 187); padding: 5px;"

@JivkoJelev91
Copy link

What about dynamic sizing of the modal in typescript?

@smboy86
Copy link

smboy86 commented Feb 12, 2022

my solution is
... right: 'auto', bottom: 'auto', ...

@callagga
Copy link

callagga commented Jul 6, 2022

I'm still having issues getting modal to auto-expand when react-datepicker is clicked on within the modal. Posted a question here: https://stackoverflow.com/questions/72890966/react-modal-how-to-get-modal-to-auto-expand-when-react-datepicker-is-clicked

@diasbruno
Copy link
Collaborator

@callagga you can try to define de height as auto, it will be a little bit of a challenge to make it position correctly.

@callagga
Copy link

callagga commented Jul 8, 2022

thanks - I've tried but did note"

  • adding a: height: 'auto' - doesn't change anything
  • additing the "height auto" and also removing the "bottom auto" - the size of the dialog is bigger, however it is big for the initial state before the date field has been selected, as well as after the date field is selected and the month calendar appears? so not dynamic. That is like this:

image

then

image

@polixisNG
Copy link

polixisNG commented Jan 27, 2023

I don't have any other options how to do it (((

.ReactModal__Content--after-open {
width: 1000px !important;
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%) !important;
min-height: max-content !important;
overflow: hidden !important;
}

@diasbruno
Copy link
Collaborator

@polixisNG Actually, you do!! You can use the style attributes do manage the size of the content and overlay.

http://reactcommunity.org/react-modal/styles/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests