Retour au catalogue

Split Content Diagonal

Split diagonal avec CSS clip-path. Chaque moitie porte du contenu independant avec animation d'entree decalee.

split-contentmedium Both Responsive a11y
boldeditorialagencyportfoliouniversalsplitasymmetric
Theme
"use client";

import { motion } from "framer-motion";

interface SplitContentDiagonalProps {
  leftTitle?: string;
  leftDescription?: string;
  leftImageSrc?: string;
  rightTitle?: string;
  rightDescription?: string;
  rightImageSrc?: string;
}

const EASE = [0.16, 1, 0.3, 1] as const;

export default function SplitContentDiagonal({
  leftTitle = "Design",
  leftDescription = "Nous creons des experiences visuelles memorables.",
  leftImageSrc = "",
  rightTitle = "Technologie",
  rightDescription = "Nous construisons des solutions robustes et scalables.",
  rightImageSrc = "",
}: SplitContentDiagonalProps) {
  return (
    <section
      style={{
        padding: "var(--section-padding-y-lg) 0",
        background: "var(--color-background)",
        overflow: "hidden",
      }}
    >
      <div
        style={{
          maxWidth: "var(--container-max-width)",
          margin: "0 auto",
          padding: "0 var(--container-padding-x)",
        }}
      >
        <div
          style={{
            display: "grid",
            gridTemplateColumns: "1fr",
            minHeight: "500px",
            position: "relative",
          }}
          className="md:!grid-cols-2"
        >
          {/* Left half */}
          <motion.div
            initial={{ opacity: 0, x: -40 }}
            whileInView={{ opacity: 1, x: 0 }}
            viewport={{ once: true }}
            transition={{ duration: 0.7, ease: EASE }}
            style={{
              clipPath: "polygon(0 0, 100% 0, 85% 100%, 0% 100%)",
              background: "var(--color-background-alt)",
              padding: "4rem 3rem 4rem 2rem",
              display: "flex",
              flexDirection: "column",
              justifyContent: "center",
              position: "relative",
            }}
          >
            {leftImageSrc && (
              <div
                style={{
                  position: "absolute",
                  inset: 0,
                  clipPath: "inherit",
                  overflow: "hidden",
                }}
              >
                <img
                  src={leftImageSrc}
                  alt={leftTitle}
                  style={{
                    width: "100%",
                    height: "100%",
                    objectFit: "cover",
                    opacity: 0.15,
                  }}
                />
              </div>
            )}
            <div style={{ position: "relative", zIndex: 1, maxWidth: "400px" }}>
              <h3
                style={{
                  fontFamily: "var(--font-sans)",
                  fontSize: "clamp(1.75rem, 3vw, 2.5rem)",
                  fontWeight: 800,
                  letterSpacing: "-0.03em",
                  color: "var(--color-foreground)",
                  marginBottom: "1rem",
                }}
              >
                {leftTitle}
              </h3>
              <p
                style={{
                  fontSize: "1.0625rem",
                  lineHeight: 1.7,
                  color: "var(--color-foreground-muted)",
                }}
              >
                {leftDescription}
              </p>
            </div>
          </motion.div>

          {/* Right half */}
          <motion.div
            initial={{ opacity: 0, x: 40 }}
            whileInView={{ opacity: 1, x: 0 }}
            viewport={{ once: true }}
            transition={{ duration: 0.7, delay: 0.15, ease: EASE }}
            style={{
              clipPath: "polygon(15% 0, 100% 0, 100% 100%, 0% 100%)",
              background: "var(--color-background-card)",
              padding: "4rem 2rem 4rem 3.5rem",
              display: "flex",
              flexDirection: "column",
              justifyContent: "center",
              alignItems: "flex-end",
              position: "relative",
            }}
          >
            {rightImageSrc && (
              <div
                style={{
                  position: "absolute",
                  inset: 0,
                  clipPath: "inherit",
                  overflow: "hidden",
                }}
              >
                <img
                  src={rightImageSrc}
                  alt={rightTitle}
                  style={{
                    width: "100%",
                    height: "100%",
                    objectFit: "cover",
                    opacity: 0.15,
                  }}
                />
              </div>
            )}
            <div style={{ position: "relative", zIndex: 1, maxWidth: "400px", textAlign: "right" }}>
              <h3
                style={{
                  fontFamily: "var(--font-sans)",
                  fontSize: "clamp(1.75rem, 3vw, 2.5rem)",
                  fontWeight: 800,
                  letterSpacing: "-0.03em",
                  color: "var(--color-foreground)",
                  marginBottom: "1rem",
                }}
              >
                {rightTitle}
              </h3>
              <p
                style={{
                  fontSize: "1.0625rem",
                  lineHeight: 1.7,
                  color: "var(--color-foreground-muted)",
                }}
              >
                {rightDescription}
              </p>
            </div>
          </motion.div>
        </div>
      </div>
    </section>
  );
}

Avis

Split Content Diagonal — React Split-content Section — Incubator