Troubleshooting: Issue with fixed positioning in React (Next.js) causing problems with modal window functionality

I'm currently working on implementing a modal window in React, but I've encountered an issue where setting position: fixed results in the modal window's position being relative to the page rather than the browser window. For privacy reasons, I've added black boxes over certain areas in the screenshot below. https://i.sstatic.net/FZp2p.png

Below is the code for this page, which includes the modal window component placed at the top.

import React, { useState } from 'react';
import Head from 'next/head';
import utilStyles from '../styles/util.module.css';
import styles from '../styles/education.module.css';
import courseData from '../public/courses.json' assert {type: 'json'};
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faCalendar } from '@fortawesome/free-regular-svg-icons';
import { faXmark } from '@fortawesome/free-solid-svg-icons';

// Modal Component
function Modal({ isShow, handleClick, longDescription, children }) {
    return (isShow ? 
        <div className="modal-outer" onClick={handleClick}>
            <div className="modal-inner">
                {children}
                <button className="exit"><FontAwesomeIcon className="exit-icon" icon={faXmark}/></button>
                <p className="course-description-long">{longDescription}</p>
            </div>
        </div>
     : "");
}

// Course Content Component
function CourseContent({ courseName, shortDescription }) {
    return (
        <>
            <h3 className="course-name">{courseName}</h3>
            <p className="course-description-short">{shortDescription}</p>
        </>
    )
}

// Course Card Component
function CourseCard({ courseName, shortDescription, longDescription}){
  const [isShow, setIsShow] = useState(false);

    function handleClick () {
        setIsShow(!isShow);
    }

  return (
    <>
        <li key={courseName} className="course-card" onClick={handleClick}>
            <CourseContent courseName={courseName} shortDescription={shortDescription}/>
        </li>
        <Modal isShow={isShow} 
        longDescription="this is the long description"
        handleClick={handleClick}>
            <CourseContent courseName={courseName} shortDescription={shortDescription}/>
        </Modal>
        
     </>
  )
}

// Degree Information Component
function DegreeInfo(props) {
  const { universityName, degreeType, degreeName, startYear, endYear, courses } = props;
  return (
    <li>
      <p>{universityName}</p>
      <p>{degreeType}.&nbsp;{degreeName}</p>
      <div className="date-container">
        <FontAwesomeIcon icon={faCalendar}/>
        <time dateTime={`${startYear}/${endYear}`}>{startYear}&ndash;{endYear}</time>
      </div>
      <ul className="course-cards-list">
        {courses.map(course => 
          <CourseCard key={course.courseName} courseName={course.courseName} shortDescription={course.shortDescription} />
        )}
      </ul>
    </li>
  )
}

export default function EducationPage() {
  const yearDecoder = {1: "First-year", 2: "Second-year", 3: "Third-year"};
  return (
    <>
      <Head>
        <title>Education | Alé Pouroullis</title>
      </Head>
      <div  className={`${utilStyles.container} ${utilStyles['float-in']}`}>
        
        <h1>Education</h1>
        <section className="university">
            <h2>Tertiary</h2>
            <ul className={`${styles['main-list']}`}>
                    {courseData.degrees.map(degree => {
                    const courses = degree.courses;
                    courses.sort(sortByYear);
                    return (<DegreeInfo key={degree.name} universityName={degree.universityName}
                                degreeType={degree.type} degreeName={degree.degreeName}
                                startYear={degree.startYear} endYear={degree.endYear}
                                courses={courses}/>)
                    })}
                </ul>
        </section>
        <section className="courses">
          <h2>Courses</h2>
          <ul className="main-list">
            <li className="main-list-item">
              <span className="main-list-text">Mathematics for Machine Learning Specialization</span>
              <ul className="sub-list">
                <li className="sub-list-item"><span className="sub-list-text">Linear Algebra</span></li>
                <li className="sub-list-item"><span className="sub-list-text">Multivariable Calculus</span></li>
              </ul>
            </li>
          </ul>
        </section>
      </div>
    </>
  );
}

// Sorting Function for Courses
function sortByYear(a, b) {
  if (a.year < b.year) {
    return -1;
  } else if (a.year > b.year) {
    return 1;
  } else {
    return 0;
  }
}

Here is the CSS styling used for the modal window:

.modal-outer {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, .5);
  display: flex;
  justify-content: center;
  align-items: center; 
}

As a beginner in React, I appreciate any advice or assistance with this issue. Thank you!

Answer №1

For optimal centering of your modal component, utilize the following CSS:

top: 50%; left: 50%; transform: translateY(-50%); transform: translatex(-50%);
This will ensure that your modal is positioned at the exact center of the screen.

For a more inventive approach, consider using the React.createPortal function. Find out more about it here: https://reactjs.org/docs/portals.html

Answer №2

Here is the recommended CSS code snippet for .modal-outer element.

.modal-outer {
  position: fixed;
  top: 50%;
  left: 50%; transform:translate(-50%, -50%);
  background-color: rgba(0, 0, 0, .5);
  display: flex;
  justify-content: center;
  align-items: center; 
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to monitor a Vue instance property within a component?

I recently implemented a plugin that introduces a new property to the Vue instance. This property can then be accessed within components using this.$plugin.prop. However, I am encountering difficulty in watching for changes to this property. I need to perf ...

What is the reason behind the MenuAppBar defaulting to the 1st menu item being selected

Unlike in the menu where the first item is not selected by default, the menuAppBar has the first item selected by default. I am looking to have the same behavior as the menu in the menuAppBar. ...

Using ng-class in Angular.js with a boolean retrieved from a service: A step-by-step guide

I need to dynamically set a class based on a boolean value that is determined in a service. This example is simplified for readability, but in reality, the boolean would be set by multiple functions within the service. Here is how it would look in HTML: ...

Tips on concealing a div until the value of a specific field surpasses zero

In order to ensure that users focus on the first section of the form before proceeding, I plan to hide the last section until a specific field has a value greater than zero. Check out my HTML code below: <div class="fieldcontainer"> <label>E- ...

Guide on resizing the Image element's height in Next.js

Three images with varying size ratios are sent from the server to me, and my goal is to resize them based on their height. I am currently utilizing the Image component from next.js within a designated container. ...

Accessing the URL causes malfunctioning of the dynamic routing in Angular 2

I am currently working on implementing dynamic routing functionality in my Angular application. So far, I have successfully achieved the following functionalities: Addition of routing to an existing angular component based on user input Removal of routin ...

Error: The function subscribe in _store_js__WEBPACK_IMPORTED_MODULE_12__.default is not supported

In my main App component, I am subscribing to the store in a normal manner: class App extends Component { constructor(props) { super(props) this.state = {} this.unsubscribe = store.subscribe(() => { console.log(store.getState()); ...

Getting just the main nodes from Firebase using Angularfire

I'm having trouble figuring out how to print just the parent element names from the structure of my database. The image provided shows the layout, but I can't seem to isolate the parent elements successfully. ...

Exploring the wonders of Vue.js and Laravel's type casting techniques

I have implemented DB2-style IDs for my database records in my Laravel 5.7 application, like this example: 201402241121000000000000. When trying to use it in my Vue component, I used the following syntax: <mycomponent v-bind:listing-key="{{ $listing-&g ...

jquery line break in textarea

There is a 'edit description' button that, when clicked, makes text disappear and reappear if (id == 'commedit') jQuery(this).html('<textarea>'+jQuery(this).text()+'</textarea>'); else i ...

"Attempt to create angular fork results in an unsuccessful build

I have recently created a fork of angularJs and I am facing an issue when trying to build it. The build process fails when running grunt package npm -v --> 3.5.2 bower --version --> 1.7.2 I followed the steps provided in the official documentation ...

Using static methods within a static class to achieve method overloading in Typescript

I have a TypeScript static class that converts key-value pairs to strings. The values can be boolean, number, or string, but I want them all to end up as strings with specific implementations. [{ key: "key1", value: false }, { key: "key2&qu ...

Can storing JWT in the windows object be considered a secure method for easy retrieval when required?

I have received an access token (JWT) in the URL. For example: . Is it secure to save this token in the window object? For instance: window.jwt = Token If so, how can it be utilized (extracting the JWT from the Window object and carrying out subsequent ...

Methods to prevent ExtentReports from transforming HTML references in your Selenium logs into real HTML code

Having an issue with ExtentReports 4 for .Net and HTML V3 reporter. Whenever a test fails, the failure message is displayed in the report. However, if the failure message contains an HTML tag, it gets converted to actual HTML on the report, causing layout ...

React: Issue with conditional button text not displaying as expected

I am having an issue with a Button react-bootstrap component that I have implemented. <Button className="btn-omega has-icon" onClick={() => { handleFavsClick(data.products)}} variant="" > <Icon size="1.75rem&quo ...

Implementing image uploads with Spring and React

How can I resolve the issue involving status 415 in Spring? I've been attempting to upload images into a database using React, but keep encountering errors: In the Spring console : Content-Type 'multipart/form-data;boundary=----WebKitFormBounda ...

When hovering over an image, CSS text will be displayed

Creating a CSS hover effect where text appears when the user hovers over a small thumbnail and a large image is displayed upon clicking. I have set up a modal for the image, but having difficulty with positioning the text. Currently, the text is located un ...

Tips for enabling autoplay for videos in Owl Carousel

I am facing an issue with implementing autoplay functionality for videos in an owl carousel. Despite trying different solutions found online, including this Owl Carousel VIDEO Autoplay doesn’t work, I haven't been able to make it work. Additionally, ...

Remove a Row from a Table by Clicking a Button with Ajax

I currently have an HTML table with 4 columns: SKU Group, Group_ID, Edit button, and Delete button. My focus at the moment is on implementing the delete functionality. I want it so that when the delete button is clicked, a confirmation box appears. If "OK" ...

Issue encountered when attempting to upload several images on Laravel

I am working on a feature that allows registered users to create posts with the ability to upload multiple images. The goal is to store the image paths in the images table along with the post_id to associate each image with the correct post. However, upon ...