Как поместить всплывающее окно за пределы div карты с помощью css?

#html #css #reactjs

#HTML #css #reactjs

Вопрос:

у меня есть всплывающее окно, которое появляется при нажатии кнопки добавить. проблема в том, что всплывающее окно отображается внутри div карты.

ниже приведен мой код,

 .outer_wrapper {
    display: flex;
    flex-direction: column;
    position: relative;
    justify-content: flex-start;
    align-items: center;
    overflow: hidden;
    flex: 1;
    z-index: 1;
}

.control_wrapper {
    width: calc(100vw - 16px);
    margin: 24px;
    display: flex;
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
}

@media screen and (max-width: 1320px) {
    .control_wrapper {
        max-width: 784px;
    }
}

.wrapper {
    max-height: calc(100vh - 216px);
    transition: max-height 300ms ease-in-out;
    display: flex;
    justify-content: center;
    overflow-x: hidden;
    overflow-y: scroll;
}

.cards {
    display: flex;
    flex-wrap: wrap;
}


@media screen and (max-width: 1320px) {
    .cards {
        padding: 0 calc(50vw - 400px);
    }
}

.card {
    max-width: 384px;
    height: 256px;
    margin: 8px;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
}

@media screen and (max-width: 1320px) {
    .card {
        width: calc(50% - 16px);
        transform: translate3D(0px, 0px, 0px) scale(1);
    }
}

.content {
    flex: 1;
    width: 100%;
}

.footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
}

.name {
    display: flex;
    flex: 1;
    flex-direction: column;
    padding: 10px 0px 10px 32px;
    white-space: nowrap;
    overflow: hidden;
}

.button_wrapper {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    margin-right: 16px;
    margin-left: 16px;
}

.overlay {
    /* this is within the card and not expanding outside card div */
    position: fixed;
    top: 60px;
    transition: top 300ms ease-in-out;
    bottom: 60px;
    left: 0;
    right: 0;
    z-index: 100;
    display: flex;
    justify-content: center;
    align-items: center;
}

.dialog {
    padding: 16px;
    width: 384px;
    max-height: calc(100% - 200px);
    display: flex;
    flex-direction: column;
}

.container {
    align-items: center;
    padding-bottom: 16px;
    margin-bottom: 16px;
}

.item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    height: 48px;
}

.dialog_footer {
    height: 24px;
    margin: 0 -16px -16px;
}

.message {
    position: absolute;
    bottom: 24px;
    display: flex;
    align-items: center;
    justify-content: center;
}  
 <div class="outer_wrapper">
    <div class="control_wrapper"></div>
    <div class="wrapper">
        <div class="cards">
            <div class="card">
                <a class="content"></a>
                <div class="footer">
                    <a class="name">
                        <div class="button_wrapper">
                            <button>add</button>
                            <div class="overlay">
                                <!-- 
                                //this is the one that is inside card div only i want
                                //it to occupy full screen height and width 
                                -->
                                <div class="dialog">
                                    <span>some </span>
                                    <input type="text" placeholder="input..." />
                                    <div class="container">
                                        <span>something</span>
                                        <div class="list">
                                            <div class="item"></div>
                                        </div>
                                        <div class="dialog_footer"></div>
                                    </div>
                                    <div class="message"></div>
                                </div>
                            </div>
                        </div>
                    </a>
                </div>
            </div>
        </div>
    </div>
</div>  

Я не уверен, как разместить оверлейный div за пределами div карты и соответствовать ширине и высоте экрана.

я не уверен, что проблема связана с наложением div или dialog div

может кто-нибудь помочь мне с этим. Спасибо.

Редактировать:

как это происходит в react

 function Parent() {
    return (
        <Wrapper>
            <Cards>
            {currentList.map((item, index) => {

                return (
                    <Card
                        key={index}
                        $bgUrl={item.thumbnailUrl}
                        $index={index}
                    >
                        <Content to={toUrl} />
                        <Footer>
                            <Name to={toUrl}>
                                <span>{site.name}</span>
                                <span></span>
                            </Name>
                            <AddItem/>
                        )}
                    </Cards>
                </Wrapper>
            );
        }

const Wrapper = styled.div`
    max-height: calc(100vh -46  96}px);
    display: flex;
    overflow-x: hidden;
    overflow-y: scroll;
`;

const Cards = styled.div`
    display: flex;
    flex-wrap: wrap;
`;

 const Card = styled.div<{
     width: calc(33.33% - 16px);
     display: flex;
     flex-direction: column;
     align-items: flex-end;
     background-size: cover;
 `;


function AddItem({isDialogOpen}: props) {
    return (
        <AddItemWrapper>
            <button onClick={onAddClick}>Add</button>

            {isDialogOpen amp;amp; (
                <Overlay>
                    <Dialog></Dialog>
                </Overlay>
            )}
        </AddItemWrapper>
    );
}


const AddItemWrapper = styled.div`
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    margin-right: 16px;
`;

const Overlay = styled.div`
    position: fixed;
    top: 60px;
    bottom: 40px;
    left: 0;
    right: 0;
    z-index: 100;
    display: flex;
    justify-content: center;
    align-items: center;
`;

 const Dialog = styled.div`
     padding: 16px;
     width: 384px;
     max-height: calc(100% - 200px);
     display: flex;
     flex-direction: column;
 `;
        
  

Ответ №1:

Если вы уже используете React, вы можете использовать порталы для создания всплывающих окон

 // Parent component 

export default function App() {

  const [isOpen, setIsOpen] = useState(false);
  const popupRef = useRef(null);
  const [popupSt, setPopupSt] = useState();

  return (
    <>
      <div
        style={BUTTON_WRAPPER_STYLES}
        onClick={() => console.log("clicked")}
        ref={(current) => {
          popupRef.current = current;
          setPopupSt(popupRef.current);
        }}
      >
        <button onClick={() => setIsOpen(true)}>Open Modal</button>

        <Popup
          open={isOpen}
          onClose={() => setIsOpen(false)}
          popupRef={popupRef}
        >
          Fancy Popup
        </Popup>
      </div>

      <div style={OTHER_CONTENT_STYLES}>Other Content</div>
    </>
  );
}
  
 // Popup component 

export default function Popup({ open, children, onClose, popupRef }) {
  if (!open || !popupRef.current) return null;

  return ReactDom.createPortal(
    <>
      <div style={OVERLAY_STYLES} />
      <div style={MODAL_STYLES}>
        <button onClick={onClose}>Close Popup</button>
       Hi, this is popup
      </div>
    </>,
    document.getElementById("portal")
  );
}
  
  // index.html 

   ..
    <div id="portal"></div>
   ..
  

Пример песочницы кода

Комментарии:

1. Потому что до первого рендеринга в DOM нет элемента, и document.getElementById он не может получить доступ ни к одному элементу. Оно будет отображаться Target container is not a DOM element . Итак, я использовал useRef в родительском компоненте и отправил его в popupComponent.

Ответ №2:

Вы помещаете наложение внутри карты, так что теперь его атрибуты положения относятся к карте. Поместите наложение вне карты как отдельный элемент (на том же уровне, что и карта), и оно должно работать.

Комментарии:

1. спасибо, но могу ли я сделать это, не помещая наложение за пределы карты?

2. Что плохого в том, чтобы поместить наложение вне карты? Это отдельный элемент, так что даже лучше для семантики

3. Это в основном тот же код, за исключением того, что вы вырезаете наложение изнутри карты и вставляете его сразу после закрытия <div class=»card»>

4. или на самом деле я не могу этого сделать, поскольку это наложение является div внутри компонента react, который также используется другим компонентом