שימוש ב-shape() לחיתוך רספונסיבי

תאריך פרסום: 8 באפריל 2025

המאפיין clip-path מאפשר לשנות את הצורה של אלמנט על ידי חיתוך שלו לעיגול, לפוליגון או אפילו לנתיב SVG. עם זאת, לפני גרסה Chrome 135 וגרסה Safari 18.4, הייתם צריכים לבחור בין מצולעים רספונסיביים לבין צורות מורכבות יותר שלא רספונסיביות באמצעות נתיבי SVG. בעזרת הפונקציה החדשה shape(), אפשר לחתוך את האלמנט clip-path לצורה לא מצולעת שהיא גם רספונסיבית.

Browser Support

  • Chrome: 135.
  • Edge: 135.
  • Firefox: 148.
  • Safari: 18.4.

Source

יצירת צורה של דגל

לדוגמה, אפשר להשוות בין יצירת צורה של דגל עם clip-path: path() ועם clip-path: shape().

צורה של דגל ירוק עם קווים מעוקלים בחלק העליון והתחתון.

הצורה של דגל היא לא בדיוק מצולע, כי הגבולות העליון והתחתון שלו הם עקומות בזייה קוביות ולא קווים ישרים או פינות מעוגלות.

יצירת הדגל עם clip-path: path()

אפשר לייצג צורה כמו הדגל הזה באמצעות נתיב SVG:

.flag {
  clip-path: path(
    "M 0 20 \
     C 25 0 75 40 100 20 \
     V 80 \
     C 75 100 25 60 0 80 \
     z");
}

כדי להסביר את זה, נציין ש-SVG path הוא סדרה של פקודות נתיב:

  1. העברה למיקום 0, 20.
  2. יוצרים עקומה ל-100, 20 באמצעות נקודות בקרה (25,0 ו-75, 40).
  3. קו אנכי עד 80.
  4. ‫Curve to 0, 80, using control points (75,100 and 25,50).
  5. סוגרים את הנתיב (קו ל-0,20).

הפקודה הזו מציירת צורה של דגל, אבל כל היחידות הן בפיקסלים. אפשר לשנות את הגודל של הפיקסלים האלה ב-SVG לתיבת תצוגה, אבל זה תמיד ייראה כמו שינוי גודל גיאומטרי של הצורה כולה.

לדוגמה, אם רוצים לשנות את הגודל של כל המלבן, אבל לשמור על הגובה והרוחב של העקומות 20px, לא ניתן לעשות זאת באמצעות SVG.

יצירת הדגל עם shape()

השוואה של אותה תוצאה באמצעות shape(). פונקציית הצורה מקבלת סדרה של פקודות, בדומה לפקודות הנתיב של SVG. עם זאת, הפקודות האלה מקבלות אורך וערכים באחוזים של CSS, בכל יחידת CSS.

ה-CSS הבא ממיר את הדגל shape() ליחידות אחוזים:

.flag {
  clip-path: shape(from 0% 20%,
     curve to 100% 20% with 25% 0% / 75% 40%,
     vline to 80%,
     curve to 0% 80% with 75% 100% / 25% 60%,
     close
  );
}

התאמה אוטומטית של התוכן למכשירים שונים

אפשר לבחור אילו יחידות אורך של CSS להשתמש בכל קואורדינטה מתוך מגוון האפשרויות.

לדוגמה, כדי לשנות את הגודל של כל הדגל בהתאם לגודל הרכיב, אבל לשמור על הגובה של העיקול קבוע, אפשר לעשות את הפעולות הבאות:

.flag {
  clip-path: shape(from 0% 20px,
     curve to 100% 20px with 25% 0% / 75% 40px,
     vline to calc(100% - 20px),
     curve to 0% calc(100% - 20px) 
           with 75% 100% / 25% calc(100% - 40px),
     close
  );
}

הוספת מאפיינים מותאמים אישית ואנימציות

אחרי שהגדרתם את הצורה ב-CSS, אתם יכולים להשתמש גם במאפיינים מותאמים אישית כדי לשנות בקלות את הגובה:

.flag {
  --wave-height: 40px;
  clip-path: shape(
    from 0px var(--wave-height),
    curve to 100% var(--wave-height) 
          with 25% 0px / 75% calc(var(--wave-height) * 2),
    vline to calc(100% - var(--wave-height)),
    curve to 0 calc(100% - var(--wave-height))
          with 75% 100% / 25% calc(100% - var(--wave-height) * 2),
    close
  )
}

אפשר אפילו להנפיש את מאפיין ה-CSS באמצעות המתאר @property ולתחום אותו כדי שלא יחרוג מהגבולות:

@property --animated-wave-height {
  syntax: "<length>";
  inherits: false;
  initial-value: 40px;
}

@keyframes curve {
  from { --animated-wave-height: 0px; }
  to { --animated-wave-height: 180px; }
}

.flag {
  width: 600px;
  height: 400px;
  background: green;
  animation: curve 1s infinite alternate;
  --wave-height: calc(min(var(--animated-wave-height, 40px), 40%));
  clip-path: shape(
    from 0px var(--wave-height),
    curve to 100% var(--wave-height)
          with 25% 0px / 75% calc(var(--wave-height) * 2),
    vline to calc(100% - var(--wave-height)),
    curve to 0 calc(100% - var(--wave-height)) 
          with 75% 100% / 25% calc(100% - var(--wave-height) * 2),
    close
  )
}

נסה את ההדגמה

ב-Chrome 135 או ב-Safari 18.4, אפשר לראות את צורת הדגל המונפשת שנוצרה באמצעות clip-path: shape() בהדמו הזה של CodePen.

סיכום

clip-path: shape() מאפשרת לחתוך את הרכיב באמצעות צורות שרירותיות ורספונסיביות, שאפשר היה להשתמש בהן בעבר רק באמצעות טכניקות כמו מעברי צבע קוניים או SVG שנבנה באמצעות JavaScript.

התחביר המלא מופיע במפרט.

בשלב הזה, אפשר להשתמש בה רק ב-clip-path. בעתיד, אנחנו מתכננים להשתמש בצורה כזו כדי להגדיר את הצורה של גבול הרכיב, וכך לאפשר עוד דרכים לא מלבניות להבעה.