Chrome 和 Safari 之间 React 组件的不同网格行为

问题描述 投票:0回答:1

我目前正在尝试实现一个基于shadcn的Timeline React组件。该组件是社区贡献的组件,我承认它只是从 GitHub 复制粘贴的。我只在 Chromium 浏览器上进行测试,即使在移动设备上它看起来也很好。但当我通过 Vercel 部署它时,时间线组件立即崩溃,并且在浏览器中看起来有所不同。

这就是 Chrome 上的样子: 镀铬图像

这就是 Safari 上的样子: Safari 图像

我的第一直觉认为这是 TimelineHeading 高度的问题,导致它向下推其下方的所有元素。但进一步检查后发现,与 Chrome 相比,Safari 中该点的顶部和底部似乎有更大的空间。

为了了解更多背景信息,该应用程序是使用 Astro 制作的,组件是使用 React 创建的。执行

client:only="react"
也不起作用,因为它只会进一步破坏布局。如果有人能指出我正确的方向,那就太好了。谢谢!

History.astro

---
import { Image } from "astro:assets";
import {
  Timeline,
  TimelineContent,
  TimelineDot,
  TimelineHeading,
  TimelineItem,
  TimelineLine,
} from "@/components/ui/timeline";
import gihay_launch from "@/assets/about/gihay_launch.jpeg";
import gihay_first_workshop from "@/assets/about/gihay_first_workshop.jpeg";
import gihay_thousand_cores from "@/assets/about/gihay_thousand_cores.jpeg";
import gihay_seventy from "@/assets/about/gihay_seventy.jpeg";
import gihay_ramon_distribution from "@/assets/about/gihay_ramon_distribution.jpg";
import gihay_purras_distribution from "@/assets/about/gihay_purras_distribution.jpeg";
import gihay_hundred from "@/assets/about/gihay_hundred.jpeg";
import gihay_calma_distribution from "@/assets/about/gihay_calma_distribution.jpeg";
import gihay_umapad_distribution from "@/assets/about/gihay_umapad_distribution.jpeg";
import gihay_my_refuge from "@/assets/about/gihay_my_refuge.png";
---

<section class="h-full flex flex-col bg-gihay-bg py-10 gap-10 items-center">
  <div class="flex justify-center h-fit gap-4">
    <span
      class="font-extrabold text-7xl md:text-8xl lg:text-9xl text-gihay-dark-pink"
      >Origin</span
    >
    <div class="flex flex-col justify-end text-4xl md:text-5xl lg:text-6xl">
      <span class="font-bright text-gihay-dark-pink">Gihay</span>
      <span class="font-bright text-gihay-dark-pink">Initiative</span>
    </div>
  </div>
  <div class="w-11/12 md:w-9/12">
    <Timeline positions="center">
      <TimelineItem status="done">
        <TimelineHeading
          className="text-gihay-dark-pink text-lg md:text-xl lg:text-2xl font-semibold"
          side="left">March 3, 2022</TimelineHeading
        >
        <TimelineDot status="done" />
        <TimelineLine done />
        <TimelineContent
          className="text-gihay-text text-sm md:text-md lg:text-xl"
          side="left"
        >
          Launched during Women's Month, the Gihay Initiative empowers
          underprivileged menstruating individuals in Cebu by providing them
          with sustainable, reusable napkins. This initiative, spearheaded by
          passionate Carolinian youth, aims to address menstrual hygiene
          accessibility while promoting environmental sustainability.
        </TimelineContent>
        <TimelineContent side="right">
          <Image
            src={gihay_launch}
            class="h-[20vh] shadow-xl object-cover object-top rounded-xl"
            alt="Gihay launch picture"
          />
        </TimelineContent>
      </TimelineItem>
      <TimelineItem>
        <TimelineHeading
          className="text-gihay-dark-pink text-lg md:text-xl lg:text-2xl font-semibold"
          side="right">June 22 - July 7, 2022</TimelineHeading
        >
        <TimelineDot status="done" />
        <TimelineLine done />
        <TimelineContent
          className="text-gihay-text text-sm md:text-md lg:text-xl"
          side="right"
        >
          Over three weeks, the Gihay Initiative held its first Volunteer
          Workshop and Orientation, attracting 35 dynamic volunteers committed
          to the cause. These sessions included training on the production and
          distribution of reusable menstrual products, reinforcing our
          community's commitment to women's health.
        </TimelineContent>
        <TimelineContent side="left">
          <Image
            src={gihay_first_workshop}
            class="h-[20vh] shadow-xl object-cover object-top rounded-xl"
            alt="Gihay first workshop picture"
            quality="max"
          />
        </TimelineContent>
      </TimelineItem>
      <TimelineItem status="done">
        <TimelineHeading
          className="text-gihay-dark-pink text-lg md:text-xl lg:text-2xl font-semibold"
          side="left">August 11, 2022</TimelineHeading
        >
        <TimelineDot status="done" />
        <TimelineLine done />
        <TimelineContent
          className="text-gihay-text text-sm md:text-md lg:text-xl"
          side="left"
        >
          A significant achievement: the organization alone crafted over 1,000
          reusable cores, marking a major milestone in our commitment to
          sustainability and support for menstrual health.
        </TimelineContent>
        <TimelineContent side="right">
          <Image
            src={gihay_thousand_cores}
            class="h-[20vh] shadow-xl object-cover object-top rounded-xl"
            alt="Gihay 1000 core milestone picture"
          />
        </TimelineContent>
      </TimelineItem>
      <TimelineItem status="done">
        <TimelineHeading
          className="text-gihay-dark-pink text-lg md:text-xl lg:text-2xl font-semibold"
          side="right">September 1, 2022</TimelineHeading
        >
        <TimelineDot status="done" />
        <TimelineLine done />
        <TimelineContent
          className="text-gihay-text text-sm md:text-md lg:text-xl"
          side="right"
        >
          The initiative received 70 kilograms of cloth donations and mobilized
          40 dedicated youth volunteers. This substantial support has greatly
          enhanced our production capabilities and outreach efforts.
        </TimelineContent>
        <TimelineContent side="left">
          <Image
            src={gihay_seventy}
            class="h-[20vh] shadow-xl object-cover rounded-xl"
            alt="Gihay 70 kg donation picture"
          />
        </TimelineContent>
      </TimelineItem>
      <TimelineItem status="done">
        <TimelineHeading
          className="text-gihay-dark-pink text-lg md:text-xl lg:text-2xl font-semibold"
          side="left">December 5, 2022</TimelineHeading
        >
        <TimelineDot status="done" />
        <TimelineLine done />
        <TimelineContent
          className="text-gihay-text text-sm md:text-md lg:text-xl"
          side="left"
        >
          Hosted a Period Poverty Awareness and Menstrual Health Seminar at
          Ramon Duterte National High School to educate and empower students.
          This event highlighted the importance of menstrual health and provided
          valuable information to hundreds of students.
        </TimelineContent>
        <TimelineContent side="right">
          <Image
            src={gihay_ramon_distribution}
            class="h-[20vh] shadow-xl object-cover rounded-xl"
            alt="Gihay Ramon distribution picture"
          />
        </TimelineContent>
      </TimelineItem>
      <TimelineItem status="done">
        <TimelineHeading
          className="text-gihay-dark-pink text-lg md:text-xl lg:text-2xl font-semibold"
          side="right">December 19, 2022</TimelineHeading
        >
        <TimelineDot status="done" />
        <TimelineLine done />
        <TimelineContent
          className="text-gihay-text text-sm md:text-md lg:text-xl"
          side="right"
        >
          Expanded our educational outreach with a Menstrual Health Seminar in
          Sitio Purras, emphasizing proper menstrual health practices. This
          seminar provided in-depth education on menstrual health management,
          impacting numerous lives in the community.
        </TimelineContent>
        <TimelineContent side="left">
          <Image
            src={gihay_purras_distribution}
            class="h-[20vh] shadow-xl object-cover object-top rounded-xl"
            alt="Gihay Ramon distribution picture"
          />
        </TimelineContent>
      </TimelineItem>
      <TimelineItem status="done">
        <TimelineHeading
          className="text-gihay-dark-pink text-lg md:text-xl lg:text-2xl font-semibold"
          side="left">January 21, 2023</TimelineHeading
        >
        <TimelineDot status="done" />
        <TimelineLine done />
        <TimelineContent
          className="text-gihay-text text-sm md:text-md lg:text-xl"
          side="left"
        >
          Continued our mission in Sitio Calma, conducting a seminar focused on
          Period Poverty Awareness and promoting menstrual health awareness.
          This seminar is part of our ongoing efforts to educate and support
          underprivileged communities.
        </TimelineContent>
        <TimelineContent side="right">
          <Image
            src={gihay_calma_distribution}
            class="h-[20vh] shadow-xl object-cover rounded-xl"
            alt="Gihay Ramon distribution picture"
          />
        </TimelineContent>
      </TimelineItem>
      <TimelineItem>
        <TimelineHeading
          className="text-gihay-dark-pink text-lg md:text-xl lg:text-2xl font-semibold"
          side="right">June 19, 2023</TimelineHeading
        >
        <TimelineDot status="done" />
        <TimelineLine done />
        <TimelineContent
          className="text-gihay-text text-sm md:text-md lg:text-xl"
          side="right"
        >
          Celebrating another major donation milestone with 100 kilograms of
          cloth received, alongside the mobilization of 55 inspired youth
          volunteers. These donations have been instrumental in expanding our
          reach and increasing our impact.
        </TimelineContent>
        <TimelineContent side="left">
          <Image
            src={gihay_hundred}
            class="h-[20vh] shadow-xl object-cover rounded-xl"
            alt="Gihay Ramon distribution picture"
          />
        </TimelineContent>
      </TimelineItem>
      <TimelineItem status="done">
        <TimelineHeading
          className="text-gihay-dark-pink text-lg md:text-xl lg:text-2xl font-semibold"
          side="left">August 5, 2023</TimelineHeading
        >
        <TimelineDot status="done" />
        <TimelineLine done />
        <TimelineContent
          className="text-gihay-text text-sm md:text-md lg:text-xl"
          side="left"
        >
          Held a transformative Menstrual Health Seminar in Sitio Paglaum,
          fostering discussions on menstrual health and hygiene. This event
          furthered our goal of reducing period poverty and promoting health
          education.
        </TimelineContent>
        <TimelineContent side="right">
          <Image
            src={gihay_umapad_distribution}
            class="h-[20vh] shadow-xl object-cover rounded-xl"
            alt="Gihay Ramon distribution picture"
          />
        </TimelineContent>
      </TimelineItem>
      <TimelineItem status="done">
        <TimelineHeading
          className="text-gihay-dark-pink text-lg md:text-xl lg:text-2xl font-semibold"
          side="right">January 19, 2024</TimelineHeading
        >
        <TimelineDot status="done" />
        <TimelineContent
          className="text-gihay-text text-sm md:text-md lg:text-xl"
          side="right"
        >
          Successfully facilitated the turnover of 'With Thought of Twin Hearts'
          and 'Priyanka Annuncia' projects to My Refuge House, marking a
          significant collaboration. This partnership aims to amplify our
          efforts and reach more beneficiaries.
        </TimelineContent>
        <TimelineContent side="left">
          <Image
            src={gihay_my_refuge}
            class="h-[20vh] shadow-xl object-cover rounded-xl"
            alt="Gihay Ramon distribution picture"
          />
        </TimelineContent>
      </TimelineItem>
    </Timeline>
  </div>
</section>

timeline.tsx

import React from "react";
import { type VariantProps, cva } from "class-variance-authority";
import { Check, Circle, X } from "lucide-react";

import { cn } from "@/lib/utils";

const timelineVariants = cva("flex flex-col items-stretch", {
  variants: {
    positions: {
      left: "[&>li]:grid-cols-[0_min-content_1fr]",
      right: "[&>li]:grid-cols-[1fr_min-content]",
      center: "[&>li]:grid-cols-[1fr_min-content_1fr]",
    },
  },
  defaultVariants: {
    positions: "left",
  },
});

interface TimelineProps
  extends React.HTMLAttributes<HTMLUListElement>,
    VariantProps<typeof timelineVariants> {}

const Timeline = React.forwardRef<HTMLUListElement, TimelineProps>(
  ({ children, className, positions, ...props }, ref) => {
    return (
      <ul
        className={cn(timelineVariants({ positions }), className)}
        ref={ref}
        {...props}
      >
        {children}
      </ul>
    );
  }
);
Timeline.displayName = "Timeline";

const timelineItemVariants = cva("grid gap-x-2", {
  variants: {
    status: {
      done: "text-primary",
      default: "text-muted-foreground",
    },
  },
  defaultVariants: {
    status: "default",
  },
});

interface TimelineItemProps
  extends React.HTMLAttributes<HTMLLIElement>,
    VariantProps<typeof timelineItemVariants> {}

const TimelineItem = React.forwardRef<HTMLLIElement, TimelineItemProps>(
  ({ className, status, ...props }, ref) => (
    <li
      className={cn(timelineItemVariants({ status }), className)}
      ref={ref}
      {...props}
    />
  )
);
TimelineItem.displayName = "TimelineItem";

const timelineDotVariants = cva(
  "col-start-2 col-end-3 row-start-1 row-end-1 flex size-4 items-center justify-center rounded-full border border-current",
  {
    variants: {
      status: {
        default: "[&>*]:hidden",
        current:
          "[&>*:not(.lucide-circle)]:hidden [&>.lucide-circle]:fill-current [&>.lucide-circle]:text-current",
        done: "bg-primary [&>*:not(.lucide-check)]:hidden [&>.lucide-check]:text-background",
        error:
          "border-destructive bg-destructive [&>*:not(.lucide-x)]:hidden [&>.lucide-x]:text-background",
        custom: "[&>*:not(:nth-child(4))]:hidden [&>*:nth-child(4)]:block",
      },
    },
    defaultVariants: {
      status: "default",
    },
  }
);

interface TimelineDotProps
  extends React.HTMLAttributes<HTMLDivElement>,
    VariantProps<typeof timelineDotVariants> {
  customIcon?: React.ReactNode;
}

const TimelineDot = React.forwardRef<HTMLDivElement, TimelineDotProps>(
  ({ className, status, customIcon, ...props }, ref) => (
    <div
      role="status"
      className={cn("m-auto h-fit", timelineDotVariants({ status }), className)}
      ref={ref}
      {...props}
    >
      <Circle className="size-2.5" />
      <Check className="size-3" />
      <X className="size-3" />
      {customIcon}
    </div>
  )
);
TimelineDot.displayName = "TimelineDot";

const timelineContentVariants = cva(
  "row-start-2 row-end-2 pb-8 text-muted-foreground",
  {
    variants: {
      side: {
        right: "col-start-3 col-end-4 mr-auto text-left",
        left: "col-start-1 col-end-2 ml-auto text-right",
      },
    },
    defaultVariants: {
      side: "right",
    },
  }
);

interface TimelineContentProps
  extends React.HTMLAttributes<HTMLParagraphElement>,
    VariantProps<typeof timelineContentVariants> {}

const TimelineContent = React.forwardRef<
  HTMLParagraphElement,
  TimelineContentProps
>(({ className, side, ...props }, ref) => (
  <p
    className={cn(timelineContentVariants({ side }), className)}
    ref={ref}
    {...props}
  />
));
TimelineContent.displayName = "TimelineContent";

const timelineHeadingVariants = cva(
  "row-start-1 row-end-1 line-clamp-1 max-w-full truncate h-fit",
  {
    variants: {
      side: {
        right: "col-start-3 col-end-4 mr-auto text-left",
        left: "col-start-1 col-end-2 ml-auto text-right",
      },
      variant: {
        primary: "text-base font-medium text-primary",
        secondary: "text-sm font-light text-muted-foreground",
      },
    },
    defaultVariants: {
      side: "right",
      variant: "primary",
    },
  }
);

interface TimelineHeadingProps
  extends React.HTMLAttributes<HTMLParagraphElement>,
    VariantProps<typeof timelineHeadingVariants> {}

const TimelineHeading = React.forwardRef<
  HTMLParagraphElement,
  TimelineHeadingProps
>(({ className, side, variant, ...props }, ref) => (
  <p
    role="heading"
    aria-level={variant === "primary" ? 2 : 3}
    className={cn(timelineHeadingVariants({ side, variant }), className)}
    ref={ref}
    {...props}
  />
));
TimelineHeading.displayName = "TimelineHeading";

interface TimelineLineProps extends React.HTMLAttributes<HTMLHRElement> {
  done?: boolean;
}

const TimelineLine = React.forwardRef<HTMLHRElement, TimelineLineProps>(
  ({ className, done = false, ...props }, ref) => {
    return (
      <hr
        role="separator"
        aria-orientation="vertical"
        className={cn(
          "col-start-2 col-end-3 row-start-2 row-end-2 mx-auto flex h-full min-h-16 w-0.5 justify-center rounded-full",
          done ? "bg-primary" : "bg-muted",
          className
        )}
        ref={ref}
        {...props}
      />
    );
  }
);
TimelineLine.displayName = "TimelineLine";

export {
  Timeline,
  TimelineDot,
  TimelineItem,
  TimelineContent,
  TimelineHeading,
  TimelineLine,
};
css reactjs astrojs shadcnui
1个回答
0
投票

自己解决了!

Mac 上的 Safari 和移动设备上的任何浏览器似乎都会破坏布局。我首先通过 Safari Web Inspector 检查网格以了解问题所在,并发现尽管 CSS 相同,但 Chrome 和 Safari 之间使用的行高不同。

我在 here 阅读了它,它说在 Safari 中,CSS 网格行高可能会出现问题,因为 Safari 对百分比高度的解释有点不同。为了解决这个问题,一个技巧是用另一个设置为

display: grid
的 div 来包装网格容器。这个小小的调整为 Safari 提供了它所需的额外上下文,使其在处理高度方面更像 Chrome 和 Firefox。

我设法通过将整个时间线组件放入一个带有

display: grid
的 div 中来修复它。

<div class="w-11/12 md:w-9/12 grid">

© www.soinside.com 2019 - 2024. All rights reserved.