繁体   English   中英

在可变高度网格行内处理@material-ui Skeleton 缩放的好方法?

[英]A good way to handle @material-ui Skeleton scaling within a variable height grid row?

我正在尝试显示一个阿凡达图像网格。 在过渡状态下,我希望出现图像的骨架表示。 为此,我正在使用@material-ui/lab/Skeleton

我遇到的问题是,因为我的图像使用height: auto, width: 100%设置为在网格内自动缩放,并且图像下显示的内容的高度/长度各不相同,所以没有设置高度 val我可以传递给骨架组件。

如果您缩小沙箱屏幕的宽度,您可以看到由此导致的问题。 网格项目的高度增加导致圆形骨架开始变形为椭圆形。

这里是否有解决方案可能会给我类似于图像height: auto, width: 100%

到目前为止,我所拥有的完整代码在下方和沙箱中: https : //codesandbox.io/s/skeleton-scaling-y00cd

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Avatar from "@material-ui/core/Avatar";
import Skeleton from "@material-ui/lab/Skeleton";
import Typography from "@material-ui/core/Typography";
import clsx from "clsx";
import Grid from "@material-ui/core/Grid";

const useStyles = makeStyles(theme => ({
  root: {
    textAlign: "center",
    height: "100%",
    width: "100%"
  },
  title: {
    marginTop: theme.spacing(1)
  },
  avatarRoot: {
    // width: '100%',
    // height: 'auto',
    // minHeight: '273px',
  },
  withTitle: {
    margin: "auto"
  },
  img: {},
  content: {
    lineHeight: "1.4em"
  },
  link: {
    color: "inherit",
    textDecoration: "none"
  },
  icon: {},
  fillContainer: {
    height: `auto`,
    width: `100%`,
    fontSize: "4em"
  },
  container: {
    marginTop: "250px"
  },
  fallback: {
    height: "75%",
    width: "auto"
  },
  loader: {},
  avatarLoader: {
    height: "75%",
    width: "100%"
  },
  titleLoader: {
    width: "60%",
    margin: "auto",
    marginTop: "8px",
    height: "5%"
  },
  contentLoader: {
    width: "40%",
    margin: "auto",
    marginTop: "8px",
    height: "5%"
  },
  testImg: {
    borderRadius: "100%",
    height: "auto",
    width: "100%"
  },
  isLoading: {
    display: "none"
  },
  imgContainer: {
    paddingTop: "100%",
    borderRadius: "100%",
    backgroundPosition: "center",
    backgroundSize: "contain",
    backgroundImage: "url(https://via.placeholder.com/500)"
  }
}));

export default function ImageAvatars() {
  const classes = useStyles();

  return (
    <div className={classes.root}>
      <Grid container spacing={1} className={classes.container}>
        <Grid container item xs={3} spacing={0} direction="column">
          <Avatar
            src={"https://via.placeholder.com/500"}
            variant="circle"
            className={clsx(classes.avatarRoot, {
              [classes.isLoading]: false,
              [classes.withTitle]: true,
              [classes.fallback]: false,
              [classes.fillContainer]: true
            })}
          />
          <Typography className={classes.title}>MUI Avatar</Typography>
          <Typography className={classes.content}>test test test</Typography>
        </Grid>
        <Grid container item xs={3} spacing={0} direction="column">
          <div className={classes.imgContainer} />
          <div>
            <Typography className={classes.title}>background image</Typography>
            <Typography className={classes.content}>test test test</Typography>
          </div>
        </Grid>
        <Grid container item xs={3} spacing={0} direction="column">
          <img
            className={classes.testImg}
            src={"https://via.placeholder.com/500"}
            alt={"test"}
          />
          <div>
            <Typography className={classes.title}>image el</Typography>
            <Typography className={classes.content}>test test test</Typography>
          </div>
        </Grid>
        <Grid container item xs={3} spacing={0} direction="column">
          <Skeleton
            variant="circle"
            className={clsx(classes.avatarLoader, classes.avatarRoot)}
          />
          <Skeleton className={clsx(classes.titleLoader, classes.title)} />
          <Skeleton className={clsx(classes.contentLoader, classes.content)} />
        </Grid>
      </Grid>
    </div>
  );
}

下面的解决方案基于这里的文章: https : //css-tricks.com/aspect-ratio-boxes/#article-header-id-3

解决方案的要点是使用以百分比表示的 padding-top 来创建具有特定纵横比(在这种情况下为正方形)的框。 即使在指定 padding-top 或 padding-bottom 时,填充百分比也是基于宽度的,因此 100% 的 padding-top 会产生等于宽度的填充高度。

相关的 CSS/JSS 是:

  avatarSkeletonContainer: {
    height: 0,
    overflow: "hidden",
    paddingTop: "100%",
    position: "relative"
  },
  avatarLoader: {
    position: "absolute",
    top: 0,
    left: 0,
    width: "100%",
    height: "100%"
  },

然后按如下方式使用:

        <Grid container item xs={3} spacing={0} direction="column">
          <div className={classes.avatarSkeletonContainer}>
            <Skeleton variant="circle" className={classes.avatarLoader} />
          </div>
          <Skeleton className={clsx(classes.titleLoader, classes.title)} />
          <Skeleton className={clsx(classes.contentLoader, classes.content)} />
        </Grid>

这是我修改您的沙箱的完整代码:

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Avatar from "@material-ui/core/Avatar";
import Skeleton from "@material-ui/lab/Skeleton";
import Typography from "@material-ui/core/Typography";
import clsx from "clsx";
import Grid from "@material-ui/core/Grid";

const useStyles = makeStyles(theme => ({
  root: {
    textAlign: "center",
    height: "100%",
    width: "100%"
  },
  title: {
    marginTop: theme.spacing(1)
  },
  withTitle: {
    margin: "auto"
  },
  content: {
    lineHeight: "1.4em"
  },
  link: {
    color: "inherit",
    textDecoration: "none"
  },
  fillContainer: {
    height: `auto`,
    width: `100%`,
    fontSize: "4em"
  },
  container: {
    marginTop: "250px"
  },
  fallback: {
    height: "75%",
    width: "auto"
  },
  avatarSkeletonContainer: {
    height: 0,
    overflow: "hidden",
    paddingTop: "100%",
    position: "relative"
  },
  avatarLoader: {
    position: "absolute",
    top: 0,
    left: 0,
    width: "100%",
    height: "100%"
  },
  titleLoader: {
    width: "60%",
    margin: "auto",
    marginTop: "8px",
    height: "5%"
  },
  contentLoader: {
    width: "40%",
    margin: "auto",
    marginTop: "8px",
    height: "5%"
  },
  testImg: {
    borderRadius: "100%",
    height: "auto",
    width: "100%"
  },
  isLoading: {
    display: "none"
  },
  imgContainer: {
    paddingTop: "100%",
    borderRadius: "100%",
    backgroundPosition: "center",
    backgroundSize: "contain",
    backgroundImage: "url(https://via.placeholder.com/500)"
  }
}));

export default function ImageAvatars() {
  const classes = useStyles();

  return (
    <div className={classes.root}>
      <Grid container spacing={1} className={classes.container}>
        <Grid container item xs={3} spacing={0} direction="column">
          <Avatar
            src={"https://via.placeholder.com/500"}
            variant="circle"
            className={clsx(classes.avatarRoot, {
              [classes.isLoading]: false,
              [classes.withTitle]: true,
              [classes.fallback]: false,
              [classes.fillContainer]: true
            })}
          />
          <Typography className={classes.title}>MUI Avatar</Typography>
          <Typography className={classes.content}>test test test</Typography>
        </Grid>
        <Grid container item xs={3} spacing={0} direction="column">
          <div className={classes.imgContainer} />
          <div>
            <Typography className={classes.title}>background image</Typography>
            <Typography className={classes.content}>test test test</Typography>
          </div>
        </Grid>
        <Grid container item xs={3} spacing={0} direction="column">
          <img
            className={classes.testImg}
            src={"https://via.placeholder.com/500"}
            alt={"test"}
          />
          <div>
            <Typography className={classes.title}>image el</Typography>
            <Typography className={classes.content}>test test test</Typography>
          </div>
        </Grid>
        <Grid container item xs={3} spacing={0} direction="column">
          <div className={classes.avatarSkeletonContainer}>
            <Skeleton variant="circle" className={classes.avatarLoader} />
          </div>
          <Skeleton className={clsx(classes.titleLoader, classes.title)} />
          <Skeleton className={clsx(classes.contentLoader, classes.content)} />
        </Grid>
      </Grid>
    </div>
  );
}

编辑骨架缩放

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM