如何使React+Material UI中绝对定位的头像与名称Div响应式?
解决个人资料组件中绝对定位头像区域的响应式问题
问题根源
- 绝对定位的头像容器无相对定位父级参照,导致基于视口定位,屏幕尺寸变化时位置错乱
- 头像、文字使用固定尺寸,小屏幕下易出现重叠或超出容器
- 布局方向固定为横向,小屏幕下横向空间不足
具体修改方案
1. 给父容器添加相对定位
给包裹封面图和头像的外层Stack设置相对定位,让绝对定位的子元素以它为参照:
<Stack sx={{ boxShadow: '0px 0px 4px -2px', borderTopLeftRadius: 20, borderTopRightRadius: 20, position: 'relative', // 添加相对定位 }}>
2. 重构头像容器的定位逻辑
修改头像所在Box的样式,实现响应式定位:
<Box sx={{ position: 'absolute', zIndex: 999, left: { xs: '50%', md: 32 }, // 小屏幕水平居中,大屏幕左对齐 transform: { xs: 'translateX(-50%)', md: 'none' }, // 小屏幕实现居中偏移 bottom: '-70px', // 相对于父容器底部向上偏移,让头像一半覆盖在封面图上 width: '100%', maxWidth: { md: 'auto' }, px: 2, // 小屏幕添加左右内边距 }} >
3. 响应式调整头像与文字的布局和尺寸
让头像和文字在小屏幕下纵向排列,同时设置响应式尺寸:
<Stack direction={{ xs: 'column', md: 'row' }} // 小屏幕纵向,大屏幕横向 spacing={2} alignItems={{ xs: 'center' }} // 小屏幕下居中对齐 textAlign={{ xs: 'center' }} // 小屏幕文字居中显示 > <Avatar alt="Remy Sharp" src="/assets/images/avatars/avatar_default.jpg" sx={{ backgroundColor: 'rgba(0, 82, 73, 0.8)', border: '5px solid #f1f1f1', boxShadow: '0px 0px 5px -2px', width: { xs: 100, md: 140 }, // 响应式头像大小 height: { xs: 100, md: 140 }, }} /> <Typography component={Stack} direction={'column'} color={'white'} pt={{ xs: 2, md: 5 }} // 小屏幕减少文字上边距 > <Box sx={{ textTransform: 'uppercase', fontWeight: 'bold', fontSize: { xs: 20, md: 26 }, // 响应式字号 }} > Jaydon Frankie </Box> <Box sx={{ textTransform: 'capitalize', fontSize: { xs: 16, md: 20 }, opacity: '0.7' }} > Full stack developer </Box> </Typography> </Stack>
4. 调整Tab区域的上边距
给Tab所在的Box添加上边距,避免被头像遮挡:
<Box pr={2} sx={{ width: '100%', borderBottomLeftRadius: 20, borderBottomRightRadius: 20, boxShadow: '0px 0px 5px -2px', mt: 8, // 添加上边距适配头像高度 }}>
修改后的完整组件代码
import React from 'react'; import TabPanel from '@mui/lab/TabPanel'; import TabContext from '@mui/lab/TabContext'; import TabList from '@mui/lab/TabList'; import Avatar from '@mui/material/Avatar'; import '../css/main.css' // icons import EmojiEventsIcon from '@mui/icons-material/EmojiEvents'; import WorkOutlineIcon from '@mui/icons-material/WorkOutline'; import AccountBoxIcon from '@mui/icons-material/AccountBox'; import MailIcon from '@mui/icons-material/Mail'; import CakeIcon from '@mui/icons-material/Cake'; import PhoneAndroidIcon from '@mui/icons-material/PhoneAndroid'; import FacebookIcon from '@mui/icons-material/Facebook'; import InstagramIcon from '@mui/icons-material/Instagram'; import LinkedInIcon from '@mui/icons-material/LinkedIn'; import TwitterIcon from '@mui/icons-material/Twitter'; import SchoolIcon from '@mui/icons-material/School'; import CalendarMonthIcon from '@mui/icons-material/CalendarMonth'; import ClassIcon from '@mui/icons-material/Class'; import BusinessIcon from '@mui/icons-material/Business'; import LocationOnIcon from '@mui/icons-material/LocationOn'; import MilitaryTechIcon from '@mui/icons-material/MilitaryTech'; import { Box, Tab, Stack, Container, Typography, } from '@mui/material'; function Profile() { const [value, setValue] = React.useState('1'); const handleChange = (event, newValue) => { setValue(newValue); }; return ( <div> <Container maxWidth="lg"> <Stack direction="row" mb={5} > <Typography variant="h4" gutterBottom> Profile </Typography> </Stack> <Stack direction="column" mb={5}> <Box> <Stack sx={{ boxShadow: '0px 0px 4px -2px', borderTopLeftRadius: 20, borderTopRightRadius: 20, position: 'relative', // 添加相对定位 }}> <Box sx={{ width: '100%', height: 250, backgroundImage: "url('https://api-dev-minimal-v4.vercel.app/assets/images/covers/cover_2.jpg')", backgroundSize: 'cover', backgroundPosition: 'center', backgroundRepeat: 'no-repeat', backgroundColor: 'rgba(0, 82, 73, 0.8)', filter: 'blur(4px)', WebkitFilter: 'blur(4px)', borderTopLeftRadius: 20, borderTopRightRadius: 20, zIndex: 9, }} /> <Box sx={{ position: 'absolute', zIndex: 999, left: { xs: '50%', md: 32 }, transform: { xs: 'translateX(-50%)', md: 'none' }, bottom: '-70px', width: '100%', maxWidth: { md: 'auto' }, px: 2, }} > <Stack direction={{ xs: 'column', md: 'row' }} spacing={2} alignItems={{ xs: 'center' }} textAlign={{ xs: 'center' }} > <Avatar alt="Remy Sharp" src="/assets/images/avatars/avatar_default.jpg" sx={{ backgroundColor: 'rgba(0, 82, 73, 0.8)', border: '5px solid #f1f1f1', boxShadow: '0px 0px 5px -2px', width: { xs: 100, md: 140 }, height: { xs: 100, md: 140 }, }} /> <Typography component={Stack} direction={'column'} color={'white'} pt={{ xs: 2, md: 5 }} > <Box sx={{ textTransform: 'uppercase', fontWeight: 'bold', fontSize: { xs: 20, md: 26 }, }} > Jaydon Frankie </Box> <Box sx={{ textTransform: 'capitalize', fontSize: { xs: 16, md: 20 }, opacity: '0.7' }} > Full stack developer </Box> </Typography> </Stack> </Box> </Stack> </Box> <TabContext value={value}> <Box pr={2} sx={{ width: '100%', borderBottomLeftRadius: 20, borderBottomRightRadius: 20, boxShadow: '0px 0px 5px -2px', mt: 8, // 添加上边距 }}> <TabList onChange={handleChange} aria-label="lab API tabs example" ml={'auto'} sx={{ float: 'right' }}> <Tab icon={<AccountBoxIcon />} label="Basic Details" value="1" /> <Tab icon={<EmojiEventsIcon />} label="Educational Details" value="2" /> <Tab icon={<WorkOutlineIcon />} label="Working Details" value="3" /> </TabList> </Box> <TabPanel value="1" sx={{ boxShadow: '0px 0px 5px -2px', borderRadius: 3, marginTop: '20px' }}> <Container maxWidth="lg" > <Stack px={5} direction={{ xs: 'column', sm: 'column', md: 'row' }} width={{ xs: '100%', sm: '100%', md: '100%' }} spacing={5}> <Box sx={{ width: '100%', }}> <Typography variant="h5" gutterBottom> About </Typography> <p> Tart I love sugar plum I love oat cake. Sweet roll caramels I love jujubes. Topping cake wafer.. </p> <Stack direction={'row'} spacing={2}> <Box><MailIcon /></Box> <Box> <Typography> ashlynn_ohara62@gmail.com </Typography> </Box> </Stack> <Stack direction={'row'} spacing={2}> <Box><CakeIcon /></Box> <Box> <Typography > 26/04/1996 </Typography> </Box> </Stack> <Stack direction={'row'} spacing={2}> <Box><PhoneAndroidIcon /></Box> <Box> <Typography > 9978542357 </Typography> </Box> </Stack> </Box> <Box sx={{ width: '100%', }} > <Typography variant="h5" gutterBottom> Social </Typography> <Stack direction={'row'} spacing={2}> <Box color={'rgb(24, 119, 242)'}><FacebookIcon /></Box> <Box sx={{ '&:hover': { cursor: 'pointer', textDecoration: 'underline', }, }} > <Typography > https://www.facebook.com/caitlyn.kerluke </Typography> </Box> </Stack> <Stack direction={'row'} spacing={2}> <Box color={'rgb(224, 45, 105)'}><InstagramIcon /></Box> <Box sx={{ '&:hover': { cursor: 'pointer', textDecoration: 'underline', }, }} > <Typography > https://www.instagram.com/caitlyn.kerluke </Typography> </Box> </Stack> <Stack direction={'row'} spacing={2}> <Box color={'rgb(0, 126, 187)'}><LinkedInIcon /></Box> <Box sx={{ '&:hover': { cursor: 'pointer', textDecoration: 'underline', }, }} > <Typography > https://www.linkedin.com/in/caitlyn.kerluke </Typography> </Box> </Stack> <Stack direction={'row'} spacing={2}> <Box color={'rgb(0, 170, 236)'}><TwitterIcon /></Box> <Box sx={{ '&:hover': { cursor: 'pointer', textDecoration: 'underline', }, }} > <Typography > https://www.twitter.com/caitlyn.kerluke </Typography> </Box> </Stack> </Box> </Stack> </Container> </TabPanel> <TabPanel value="2" sx={{ boxShadow: '0px 0px 5px -2px', borderRadius: 3, marginTop: '20px' }}> <Container maxWidth="lg" > <Stack px={5} direction={{ xs: 'column', sm: 'column', md: 'row' }} width={{ xs: '100%', sm: '100%', md: '100%' }} spacing={5}> <Box sx={{ width: '100%', }}> <Typography variant="h5" gutterBottom> Education </Typography> <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Eum quae reiciendis, voluptate libero nesciunt iste. Eum quae reiciendis, voluptate libero nesciunt iste. </p> <Stack direction={'row'} spacing={2}> <Box><SchoolIcon /></Box> <Box> <Typography> St. Paul's Senior Secondary School </Typography> </Box> </Stack> <Stack direction={'row'} spacing={2}> <Box><CalendarMonthIcon /></Box> <Box> <Typography > 2013 </Typography> </Box> </Stack> <Stack direction={'row'} spacing={2}> <Box><ClassIcon /></Box> <Box> <Typography > B.Tech </Typography> </Box> </Stack> </Box> </Stack> </Container> </TabPanel> <TabPanel value="3" sx={{ boxShadow: '0px 0px 5px -2px', borderRadius: 3, marginTop: '20px' }}> <Container maxWidth="lg" > <Stack px={5} direction={{ xs: 'column', sm: 'column', md: 'row' }} width={{ xs: '100%', sm: '100%', md: '100%' }} spacing={5}> <Box sx={{ width: '100%', }}> <Typography variant="h5" gutterBottom> Work </Typography> <p> Software Engineer at Cybrain Software Solutions Pvt.Ltd . </p> <Stack direction={'row'} spacing={2}> <Box><WorkOutlineIcon /></Box> <Box> <Typography> Cybrain Software Solutions Pvt.Ltd </Typography> </Box> </Stack> <Stack direction={'row'} spacing={2}> <Box><BusinessIcon /></Box> <Box> <Typography > Private Limited Companies </Typography> </Box> </Stack> <Stack direction={'row'} spacing={2}> <Box><LocationOnIcon /></Box> <Box> <Typography > Industrial Area, Sahibzada Ajit Singh Nagar,Mohali,Punjab </Typography> </Box> </Stack> <Stack direction={'row'} spacing={2}> <Box><MilitaryTechIcon /></Box> <Box> <Typography > Photoshop illustrator HTML CSS </Typography> </Box> </Stack> </Box> </Stack> </Container> </TabPanel> </TabContext> </Stack> </Container> </div > ) } export default Profile
内容的提问来源于stack exchange,提问作者holoyo
相关产品推荐
相关产品推荐

