You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React电影卡片横向排列问题求助:Flex/Grid如何正确应用?

React中实现MovieCard横向并排显示的解决方案

问题概述

在React项目中尝试让MovieCard组件横向并排显示,但卡片始终呈纵向排列,尝试多种div属性无效,需要明确是否使用Flex/Grid布局及正确应用方法。以下是相关组件代码:

MoviesList组件

import React, { useState } from 'react'
import { useSelector } from 'react-redux'
import MovieCard from './MovieCard'

const MoviesList = (props) => {
    const [search, setSearch] = useState('')
    const [filterBy, setFilterBy] = useState([])
    const [orderBy, setOrderBy] = useState('')

    const movies = useSelector((state) => {
        console.log(state.movies)
        return state.movies
    })

    const handleChange = (e) => {
        const inputValue = e.target.value
        setSearch(inputValue)

        const filteredValue = movies.filter((movie) => {
            return movie.Title.toLowerCase().includes(inputValue)
        })
        setFilterBy(filteredValue)

        console.log(filteredValue)
    }

    const handleSelectChange = (e) => {
        setOrderBy(e.target.value)
    }

    const show = (movies) => {
        switch (orderBy) {
            case 'a-z': return [...movies.sort((a, b) => a.Title.localeCompare(b.Title))]
            case 'z-a': return [...movies.sort((a, b) => b.Title.localeCompare(a.Title))]
            case '1-100': return [...movies.sort((a, b) => a.imdbRating - b.imdbRating)]
            case '100-1': return [...movies.sort((a, b) => b.imdbRating - a.imdbRating)]
            default: return [...movies]
        }
    }

    return (
        <div className='container'>
            <div className='d-flex mb-3 '>
                <h1 style={{ textAlign: 'center', border: 'solid lightgreen', backgroundColor: 'white' }} >My Movie List</h1>
                <form style={{ float: 'right', marginRight: '35px' }}>
                    <input type="text" placeholder='search by name' value={search} onChange={handleChange} />
                    <select value={orderBy} onChange={handleSelectChange} >
                        <option value="">orderBy</option>
                        <option value="a-z">a-z</option>
                        <option value="z-a">z-a</option>
                        <option value="1-100">1-100</option>
                        <option value="100-1">100-1</option>
                    </select>
                </form>
            </div>
            <div className=" row pt-2  justify-content-around " style={{ textAlign: 'center', width: '100%' }}>
                {
                    filterBy.length > 0 ? (
                        filterBy.map((movie) => {
                            return <MovieCard key={movie.imdbID} Poster={movie.Poster} Title={movie.Title} imdbRating={movie.imdbRating} imdbID={movie.imdbID} />
                        })
                    ) : (
                        show(movies).map((movie) => {
                            return <MovieCard key={movie.imdbID} {...movie} />
                        })
                    )
                }
            </div>
        </div >
    )
}

export default MoviesList

MovieCard组件

import React from 'react'
import { useDispatch } from 'react-redux'
import { removeMovie } from '../actions/moviesAction'

const MovieCard = (props) => {
    console.log(props)
    const { Title, Poster, imdbRating, imdbID } = props
    const dispatch = useDispatch()

    return (
        <div className="card mt-2 p-2 bd-highlight border shadow rounded" style={{ width: '16rem' }}>
            <img className="card-img-left pt-2" src={Poster} alt={Title} style={{ width: '200px', height: '200px' }} />
            <div className="card-body">
                <h4 className="card-title">Name : {Title}</h4>
                <h5 className="card-title">Ranking : #{imdbRating}</h5>
                <ion-icon name="trash" style={{ color: 'red' }} onClick={() => {
                    dispatch(removeMovie(imdbID))
                }}></ion-icon>
            </div>
        </div>
)}
export default MovieCard

解决方案

你可以通过Bootstrap栅格系统(你已在使用Bootstrap)、Flex布局或Grid布局实现横向排列,以下是具体实现方式:

方式1:利用Bootstrap栅格系统(最简便,适配现有代码)

你已经使用了Bootstrap的row类,只需给每个MovieCard外层添加Bootstrap的列类(如col-md-3),即可让卡片自动横向排列并响应式适配屏幕:

修改MoviesList组件中渲染MovieCard的部分:

{
    filterBy.length > 0 ? (
        filterBy.map((movie) => {
            return (
                <div key={movie.imdbID} className="col-md-3 mb-4">
                    <MovieCard Poster={movie.Poster} Title={movie.Title} imdbRating={movie.imdbRating} imdbID={movie.imdbID} />
                </div>
            )
        })
    ) : (
        show(movies).map((movie) => {
            return (
                <div key={movie.imdbID} className="col-md-3 mb-4">
                    <MovieCard {...movie} />
                </div>
            )
        })
    )
}
  • col-md-3表示在中等屏幕及以上,每行显示4个卡片(12/3=4);
  • mb-4添加底部间距,避免卡片紧贴。

方式2:使用Flex布局

给包裹MovieCard的容器添加Flex样式,让卡片横向排列并自动换行:

修改MoviesList中包裹卡片的div:

<div style={{ 
    display: 'flex', 
    flexWrap: 'wrap', 
    gap: '1rem', 
    justifyContent: 'center',
    width: '100%',
    paddingTop: '1rem'
}}>
    {/* 渲染MovieCard的代码 */}
</div>
  • display: flex启用Flex布局;
  • flexWrap: wrap让卡片在容器宽度不足时自动换行;
  • gap: 1rem设置卡片之间的间距;
  • justifyContent: 'center'让卡片居中排列。

方式3:使用Grid布局

通过Grid布局实现更灵活的卡片排列,自动根据容器宽度调整每行数量:

修改包裹卡片的div样式:

<div style={{ 
    display: 'grid',
    gridTemplateColumns: 'repeat(auto-fill, minmax(16rem, 1fr))',
    gap: '1rem',
    width: '100%',
    paddingTop: '1rem'
}}>
    {/* 渲染MovieCard的代码 */}
</div>
  • gridTemplateColumns: 'repeat(auto-fill, minmax(16rem, 1fr))'表示自动填充列,每列最小宽度为16rem(和你的卡片宽度一致),剩余空间平均分配;
  • gap: 1rem设置卡片之间的间距。

以上三种方式都能解决卡片纵向排列的问题,推荐优先使用Bootstrap栅格系统,因为你已经在项目中引入了Bootstrap,风格更统一。

内容的提问来源于stack exchange,提问作者dharani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 18:16:38