Dropdown Not Correctly Visible at Bottom Center in React Component

I am creating Amazon Prime like design to stream movies, series etc and I’m having trouble with the visibility and positioning of a dropdown component in my MediaDetailPage. I want the dropdown menu to be positioned at the bottom center of the page, when user clicks on the dropdown text.

sample MediaDetailPage

MediaDetailPage.js

import React, { useState, useEffect } from 'react';
import { useParams, useNavigate, useLocation } from 'react-router-dom';
import { Helmet } from 'react-helmet';
import SeasonEpisodeList from '../components/SeasonEpisodeList';
import '../MediaDetailPage.css';

const MediaDetailPage = () => {
    const { id } = useParams();
    const [movie, setMovie] = useState(null);
    const [loading, setLoading] = useState(true);
    const navigate = useNavigate();
    const apiBaseUrl = process.env.REACT_APP_API_BASE_URL;
    const location = useLocation(); // location object from the current route

    // Use content_type from passed state, fallback to 'default' if it's null/undefined
    const contentType = location?.state?.item?.content_type || 'default';

    useEffect(() => {
        const fetchMovieDetails = async () => {
            try {
                const response = await fetch(`${apiBaseUrl}/api/v1/listings/content/${id}/?content_type=${contentType}`);
                if (response.ok) {
                    const data = await response.json();
                    setMovie(data);
                } else if (response.status === 404) {
                    navigate('/404'); // Redirect to the 404 page
                } else {
                    console.error('Unexpected response status:', response.status);
                }
            } catch (error) {
                console.error('Error fetching movie details:', error);
            } finally {
                setLoading(false);
            }
        };

        fetchMovieDetails();
    }, [id, contentType, apiBaseUrl, navigate]);

    const handlePlay = () => {
        navigate(`/video/${id}/`);
    };

    if (loading) return <div>Loading...</div>;

    if (!movie) return null;

    return (
        <div className="media-detail-page">
            <Helmet>
                <title>{movie.title} - Cineflare</title>
                <meta name="description" content={movie.description} />
                <link rel="canonical" href={window.location.href} />
            </Helmet>
            <div className="media-detail-background-wrapper">
                <img
                    src={movie.thumbnail_url}
                    alt={movie.title}
                    className="media-detail-background"
                />
            </div>

            <div className="media-detail-content">
                <h1>{movie.title}</h1>
                <p>{movie.description}</p>
                <div className="details-row">
                    <span>{movie.duration}</span>
                    <span>{movie.release_date}</span>
                </div>
                <div className="tags-row">
                    {movie.genres && movie.genres.map((genre) => (
                        <span key={genre.id} className="tag">{genre.name}</span>
                    ))}
                </div>
                <div className="button-row">
                    {
                        contentType === 'movie' && (
                            <button className="play-button" onClick={handlePlay}>
                                Play Now
                            </button>
                        )
                    }
                </div>

                {/* Render the Season and Episode list if available */}
                {movie.latest_season && movie.season_ids && <SeasonEpisodeList data={movie} />}
            </div>
        </div>
    );
};

export default MediaDetailPage;

MediaDetailPage.css

.media-detail-page {
    position: relative;
    width: 100%;
    height: 100vh; /* Full screen height */
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: flex-start; /* Align items to the top */
    color: #fff;
    background-color: transparent;
}

/* Wrapper for the background image (thumbnail) */
.media-detail-background-wrapper {
    position: relative;
    width: 98vw;  /* Cover 98% of the screen width */
    height: 70vh; /* Cover 70% of the screen height */
    margin: 0 auto;
    overflow: hidden;
    background-color: #210d0d; /* Fallback color */
}

/* Background thumbnail image */
.media-detail-background {
    width: 100%;
    height: 100%;
    object-fit: cover; /* Cover the entire background while maintaining aspect ratio */
    filter: blur(5px); /* Blur effect */
    position: absolute;
    top: 0;
    left: 0;
    z-index: -1; /* Ensures it stays behind the content */
}

/* Main content of the media detail */
.media-detail-content {
    position: absolute;
    bottom: 0; /* Align the content to the bottom of the thumbnail */
    z-index: 1;
    width: 100%;
    padding: 20px;
    box-sizing: border-box;
    background: rgba(0, 0, 0, 0.7); /* Semi-transparent background to make content readable */
}

.details-row,
.tags-row {
    margin: 10px 0;
}

.tag {
    display: inline-block;
    margin-right: 10px;
    padding: 5px 10px;
    background-color: rgba(255, 255, 255, 0.2);
    border-radius: 20px;
    font-size: 0.9rem;
}

.button-row {
    margin-top: 10px;
    display: flex;
    justify-content: flex-start;  /* Align play button to the left */
    width: 100%;
}

.play-button {
    padding: 10px 20px;
    background-color: #00a8e1;
    color: #fff;
    border: none;
    cursor: pointer;
    font-size: 1rem;
    border-radius: 5px;
}

/* Make the layout responsive */
@media (max-width: 768px) {
    .media-detail-background-wrapper {
        height: 50vh; /* Reduce thumbnail height on smaller screens */
    }

    .episode-list {
        height: 50vh; /* Adjust episode list height */
    }

    .play-button {
        font-size: 12px;
        padding: 6px 12px;
    }
}

SeasonEpisodeList.js

import React, { useState } from 'react';
import SeasonSelector from './SeasonSelector';
import axios from 'axios';
import '../SeasonEpisodeList.css';

// Function to check if the device is mobile
const isMobileDevice = () => {
    return window.innerWidth <= 768; // Mobile view if width is 768px or less
};

const SeasonEpisodeList = ({ data }) => {
    const { latest_season, season_ids } = data;
    const [selectedSeasonId, setSelectedSeasonId] = useState(latest_season.id);
    const [selectedSeason, setSelectedSeason] = useState(latest_season);
    const [isLoading, setIsLoading] = useState(false);
    const [expandedEpisodeId, setExpandedEpisodeId] = useState(null);
    const apiBaseUrl = process.env.REACT_APP_API_BASE_URL;

    const handleSeasonChange = async (newSeasonId) => {
        if (typeof newSeasonId !== 'string') {
            console.error('Invalid Season ID passed:', newSeasonId);
            return;
        }

        setSelectedSeasonId(newSeasonId);
        setIsLoading(true);

        try {
            const response = await axios.get(`${apiBaseUrl}/api/v1/listings/content/${newSeasonId}/?content_type=season`);
            setSelectedSeason(response.data);
        } catch (error) {
            console.error('Error fetching season data:', error);
        } finally {
            setIsLoading(false);
        }
    };

    const toggleEpisodeExpand = (episodeId) => {
        if (isMobileDevice()) {
            setExpandedEpisodeId((prev) => (prev === episodeId ? null : episodeId));
        }
    };

    return (
        <div className="season-episode-container">
            <SeasonSelector
                seasonIds={season_ids}
                selectedSeasonId={selectedSeasonId}
                onSeasonChange={handleSeasonChange}
            />

            {/* Scrollable Episode List */}
            <div className="episode-list">
                {isLoading ? (
                    <p>Loading episodes...</p>
                ) : (
                    selectedSeason.episodes && selectedSeason.episodes.length > 0 ? (
                        selectedSeason.episodes.map((episode) => (
                            <div key={episode.id} className={`episode-card ${expandedEpisodeId === episode.id ? 'expanded' : ''}`}>
                                <div className="episode-info" onClick={() => toggleEpisodeExpand(episode.id)}>
                                    <div className="episode-text">
                                        <h4>{`S${selectedSeason.season_number} E${episode.episode_number}`}</h4>
                                        <p>{episode.title}</p>
                                    </div>
                                    {isMobileDevice() ? (
                                        <button className="play-button" onClick={(e) => {
                                            e.stopPropagation();
                                            window.location.href = `/video/${episode.id}`;
                                        }}>
                                            Play Now
                                        </button>
                                    ) : (
                                        <div className="episode-details">
                                            <img src={episode.thumbnail_url} alt={episode.title} className="episode-thumbnail" />
                                            <p className="release-year">{episode.release_year || 'Release Year Not Available'}</p>
                                            <p className="episode-description">{episode.description}</p>
                                        </div>
                                    )}
                                </div>

                                {expandedEpisodeId === episode.id && isMobileDevice() && (
                                    <div className="episode-extra-details">
                                        <img src={episode.thumbnail_url} alt={episode.title} className="episode-thumbnail" />
                                        <div>
                                            <p className="release-year">{episode.release_year || 'Release Year Not Available'}</p>
                                            <p className="episode-description">{episode.description}</p>
                                        </div>
                                    </div>
                                )}
                            </div>
                        ))
                    ) : (
                        <p>No episodes available for this season.</p>
                    )
                )}
            </div>
        </div>
    );
};

export default SeasonEpisodeList;

SeasonEpisodeList.css

/* General styles for the container */
.season-episode-container {
    margin: 20px; /* Add margin as needed */
}

/* Scrollable Episode List */
.episode-list {
    height: auto; /* Set to auto to accommodate content */
    overflow-y: auto; /* Enable scrolling for overflow */
}

/* Episode card styles */
.episode-card {
    display: flex;
    flex-direction: column; /* Stack elements vertically */
    margin-bottom: 10px;
    padding: 10px;
    background-color: rgba(255, 255, 255, 0.1); /* Semi-transparent card background */
    border-radius: 5px;
    color: #fff;
    transition: all 0.3s ease;
}

/* Styles for expanded episode */
.episode-card.expanded {
    background-color: rgba(255, 255, 255, 0.15);
}

/* Episode info layout */
.episode-info {
    display: flex; /* Flexbox for layout */
    justify-content: space-between; /* Space elements */
    align-items: center; /* Center align */
}

/* Episode text section */
.episode-text {
    flex: 1; /* Allow this to take remaining space */
}

/* Play button styles */
.play-button {
    background-color: #00a8e1;
    border: none;
    color: white;
    padding: 8px 16px;
    border-radius: 5px;
    cursor: pointer;
    transition: background-color 0.3s;
}

/* Play button hover effect */
.play-button:hover {
    background-color: #0056b3; /* Darker blue on hover */
}

/* Extra details for expanded episode */
.episode-extra-details {
    display: flex; /* Use flexbox for layout */
    margin-top: 10px; /* Space above */
}

/* Thumbnail styling */
.episode-thumbnail {
    width: 100px; /* Fixed width for thumbnail */
    height: auto; /* Maintain aspect ratio */
    border-radius: 5px; /* Rounded corners */
    margin-right: 10px; /* Space between thumbnail and description */
}

/* Release year style */
.release-year {
    font-weight: bold;
    color: #f0f0f0; /* Adjust text color for better readability */
}

/* Episode description style */
.episode-description {
    margin-top: 5px; /* Space above description */
    color: #d0d0d0; /* Adjust text color for better readability */
}

/* Adjustments for mobile view */
@media (max-width: 768px) {
    /* Ensure the episode card layout is flexible on mobile */
    .episode-card {
        flex-direction: column; /* Stack elements on top of each other */
    }
}

SeasonSelector.js

import React, { useState, useEffect, useRef } from 'react';
import '../SeasonEpisodeList.css'; // Ensure your CSS file path is correct

const useIsMobile = () => {
    const [isMobile, setIsMobile] = useState(window.innerWidth <= 768);

    useEffect(() => {
        const handleResize = () => {
            setIsMobile(window.innerWidth <= 768);
        };

        window.addEventListener('resize', handleResize);
        return () => window.removeEventListener('resize', handleResize);
    }, []);

    return isMobile;
};

const SeasonSelector = ({ seasonIds, selectedSeasonId, onSeasonChange }) => {
    const [showDropdown, setShowDropdown] = useState(false);
    const isMobile = useIsMobile();
    const dropdownRef = useRef(null);

    const selectedSeasonNumber = Object.keys(seasonIds).find(
        (seasonNumber) => seasonIds[seasonNumber] === selectedSeasonId
    ) || Object.keys(seasonIds)[0];

    const handleDropdownToggle = (event) => {
        event.stopPropagation();
        setShowDropdown((prev) => !prev);
    };

    const handleSeasonSelect = (seasonId, event) => {
        event.stopPropagation();
        setShowDropdown(false);
        onSeasonChange(seasonId);
    };

    const handleClickOutside = (event) => {
        if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
            setShowDropdown(false);
        }
    };

    useEffect(() => {
        if (showDropdown) {
            window.addEventListener('click', handleClickOutside);
        } else {
            window.removeEventListener('click', handleClickOutside);
        }
        return () => {
            window.removeEventListener('click', handleClickOutside);
        };
    }, [showDropdown]);

    return (
        <div className="dropdown-container" ref={dropdownRef}>
            {isMobile ? (
                <div onClick={handleDropdownToggle} className="dropdown-toggle">
                    {`Season ${selectedSeasonNumber}`}
                    {showDropdown && (
                        <div className="mobile-dropdown-list">
                            {Object.entries(seasonIds).map(([seasonNumber, seasonId]) => (
                                <div
                                    key={seasonId}
                                    onClick={(e) => handleSeasonSelect(seasonId, e)}
                                    className="mobile-dropdown-item"
                                >
                                    {`Season ${seasonNumber}`}
                                </div>
                            ))}
                        </div>
                    )}
                </div>
            ) : (
                <select
                    value={selectedSeasonId}
                    onChange={(e) => handleSeasonSelect(e.target.value, e)}
                    className="dropdown-list"
                    onClick={(e) => e.stopPropagation()}
                >
                    {Object.entries(seasonIds).map(([seasonNumber, seasonId]) => (
                        <option key={seasonId} value={seasonId}>
                            {`Season ${seasonNumber}`}
                        </option>
                    ))}
                </select>
            )}
        </div>
    );
};

export default SeasonSelector;

SeasonSelector.css

/* SeasonEpisodeList.css */

/* General styles for the container */
.season-container {
    padding: 20px;
    color: white;
}

/* Dropdown styles */
.dropdown-container {
    position: relative; /* Allow absolute positioning of dropdown items */
}

/* Mobile dropdown toggle style */
.dropdown-toggle {
    cursor: pointer;
    padding: 10px;
    background-color: #444; /* Background color for the toggle */
    border-radius: 10px; /* Rounded corners */
    text-align: center; /* Center the text */
    margin-bottom: 10px; /* Space below the toggle */
}

/* Mobile dropdown list styles */
.mobile-dropdown-list {
    position: fixed; /* Fix it to the bottom of the viewport */
    bottom: 0; /* Align to the bottom */
    left: 50%; /* Start from the left center */
    transform: translateX(-50%); /* Center the dropdown */
    background-color: #333; /* Dropdown background */
    border-radius: 10px; /* Rounded corners */
    z-index: 1000; /* Ensure it appears above other elements */
    width: 90%; /* Set width */
    max-height: 50vh; /* Maximum height */
    overflow-y: auto; /* Allow scrolling */
    box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.5); /* Optional shadow */
    opacity: 1; /* Fully visible when shown */
}

/* Mobile dropdown item styles */
.mobile-dropdown-item {
    padding: 10px; /* Padding for items */
    color: white; /* Text color */
    cursor: pointer; /* Pointer cursor */
}

/* Add hover effect for dropdown items */
.mobile-dropdown-item:hover {
    background-color: #555; /* Darker background on hover */
}

/* Episode list styles */
.episode-list {
    width: 100%;             /* Full width */
    padding: 0 15px;        /* Optional: Add padding for spacing on sides */
    box-sizing: border-box;  /* Include padding and border in element's total width */
}

.episode-item {
    display: flex;
    align-items: center;
    gap: 20px;
    background-color: #222;
    padding: 10px;
    border-radius: 10px;
}

.episode-item img {
    width: 150px;
    height: 100px;
    border-radius: 5px;
    object-fit: cover;
}

.episode-details {
    flex-grow: 1;
}

.episode-player {
    margin-top: 30px;
}

With this code, I am unable to bring the dropdown menu at the bottom center, I am expecting the dropdown to be positioned correctly as in this image, but in bottom center – Amazon Prime Dropdown reference

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật