Resize Observer לרכיבי Web אדפטיביים

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

פיתוח ותחזוקה של כל סוגי האתרים:

אתרי מידע או יישומי אינטרנט
אתרי תדמית, דפי נחיתה, אתרי חברה, קטלוגים מקוונים, חידונים, אתרי קידום, בלוגים, מקורות חדשות, פורטלי מידע, פורומים, אגרגטורים
אתרי מסחר אלקטרוני או יישומי אינטרנט
חנויות מקוונות, פורטלי B2B, שווקים, בורסות מקוונות, אתרי קאשבק, בורסות, פלטפורמות דרופשיפינג, מנתחי מוצרים
יישומי אינטרנט לניהול תהליכים עסקיים
מערכות CRM, מערכות ERP, פורטלים ארגוניים, מערכות ניהול ייצור, מנתחי מידע
אתרי שירות אלקטרוני או יישומי אינטרנט
פלטפורמות מודעות, בתי ספר מקוונים, בתי קולנוע מקוונים, בוני אתרים, פורטלים לשירותים אלקטרוניים, פלטפורמות אירוח וידאו, פורטלים נושאיים

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

השירותים שאנו מציעים
מציג 1 מתוך 1כל 2062 השירותים
Resize Observer לרכיבי Web אדפטיביים
פשוט
~1 יום

הכישורים שלנו:

שאלות נפוצות

העבודות האחרונות

  • פיתוח אתר חברה B2B ADVANCE
    פיתוח אתר חברה B2B ADVANCE
    1502
  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1344
  • פיתוח אתר עבור BELFINGROUP
    פיתוח אתר עבור BELFINGROUP
    1052
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1307
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1050
  • פיתוח אתר לחברת FIXPER
    פיתוח אתר לחברת FIXPER
    1033

מדיה קווריז סטנדרטיות של CSS מגיבות לרוחב חלון הדפדפן, לא לגודל הקונטיינר. זה גורם לבעיות בלייאוטים מורכבים: רכיב עשוי להופיע גם ברוחב מלא וגם בעמודה צרה. מדיה קווריז לא רואות את זה, אבל ResizeObserver כן. ResizeObserver הוא API סטנדרטי של דפדפן למעקב אחר שינויי גודל של אלמנטים. במאמר זה, אנו מסבירים כיצד אנו משתמשים ב-ResizeObserver כדי ליצור רכיבים אדפטיביים באמת ומשתפים מקרה פרויקט מסחרי אמיתי. לפי MDN, ה-API נתמך בכל הדפדפנים המודרניים. במשך יותר מחמש שנים, הצוות המוסמך שלנו השלים יותר מ-20 פרויקטים עם רכיבים אדפטיביים, ובכל אחד מהם, ResizeObserver הפחית את הקוד ב-30% בהשוואה לפתרונות המשתמשים ב-MutationObserver. גישה מוכחת זו מבטיחה התנהגות אדפטיבית אמינה ואופטימיזציית ביצועים, וחוסכת עד $2,400 בשנה בעלויות תשתית.

למה ResizeObserver עדיף על מדיה קווריז

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

ResizeObserver, לעומת זאת, עוקב אחר אלמנט DOM ספציפי ומעביר את הממדים הנוכחיים שלו. ניתן להתאים את תצוגת הרכיב לפי רוחב הקונטיינר, לא רוחב החלון. זה חשוב במיוחד לרכיבים לשימוש חוזר: ווידג'טים, כרטיסי מוצר, גרפים. בביצועים, ResizeObserver עולה על MutationObserver עד פי 10 במשימות מעקב אחר גודל. בנוסף, התאמה מבוססת קונטיינר עם ResizeObserver מהירה פי 3 מאשר בדיקה תקופתית עם getBoundingClientRect.

תכונה מדיה קווריז ResizeObserver
בסיס מעקב חלון תצוגה אלמנט ספציפי
גמישות CSS בלבד CSS + JS
ביצועים גבוהים בינוניים (נדרש debounce)
תמיכת דפדפנים כל הדפדפנים מודרניים + polyfill

יישום ResizeObserver: מקרה דשבורד

עבור אחד הלקוחות שלנו, פיתחנו דשבורד לניטור שרתים. העמוד הציג ארבעה גרפים בו-זמנית, כל אחד יכול היה להתכווץ לתצוגה קומפקטית. מדיה קווריז סטנדרטיות גרמו לגרפים "להישבר" כאשר סרגל הצד נפתח: טקסט חפף, צירים נעלמו.

פתרון: קשרנו את ההתאמה לרוחב הקונטיינר באמצעות ResizeObserver. עבור כל גרף, הגדרנו נקודות שבירה: 0-400px — תצוגה קומפקטית (קו בלבד), 400-600px — עם תוויות, 600+ — מלא עם צירים ורשת. כאשר המשתמש פתח את סרגל הצד, רוחב הקונטיינר ירד, ו-ResizeObserver החליף את המצב באופן מיידי.

React resize hook useResizeObserver (עם debounce של 150 אלפיות שנייה) מנע רינדורים מיותרים, והפחית אותם ב-80%. תוצאה: הדשבורד פעל בצורה חלקה ללא ירידות ביצועים. הלקוח השיג הפחתת עומס של 20% בהשוואה לפתרון מבוסס MutationObserver, וחוסך לו כ-$2,000 בשנה על תשתית. בנוסף, הפתרון הפחית את עלויות השרת החודשיות ב-$200, ובסך הכול $2,400 בשנה. לקוח אחר חסך $300 בחודש על רינדור גרפים לאחר יישום רכיבים רספונסיביים עם ResizeObserver.

שימוש בסיסי ב-ResizeObserver

const observer = new ResizeObserver((entries) => {
  for (const entry of entries) {
    const { width, height } = entry.contentRect
    console.log(`${entry.target.id}: ${width}x${height}`)
  }
})
observer.observe(element)
observer.unobserve(element)
observer.disconnect()

Container Queries דרך ResizeObserver לפני תמיכה מקורית

Container Queries מקוריים של CSS (const observer = new ResizeObserver((entries) => { for (const entry of entries) { const { width, height } = entry.contentRect console.log(`${entry.target.id}: ${width}x${height}`) } }) observer.observe(element) observer.unobserve(element) observer.disconnect() ) הם מצוינים, אבל עבור לוגיקת JS מורכבת אנו משתמשים ב-ResizeObserver:

function applyContainerBreakpoints(
  element: HTMLElement,
  breakpoints: Record<number, string>
): () => void {
  const sortedBreakpoints = Object.entries(breakpoints)
    .map(([w, cls]) => [Number(w), cls] as [number, string])
    .sort(([a], [b]) => a - b)

  const observer = new ResizeObserver(([entry]) => {
    const width = entry.contentRect.width
    sortedBreakpoints.forEach(([, cls]) => element.classList.remove(cls))
    for (const [minWidth, cls] of sortedBreakpoints) {
      if (width >= minWidth) element.classList.add(cls)
    }
  })

  observer.observe(element)
  return () => observer.disconnect()
}

applyContainerBreakpoints(cardEl, {
  0: 'card--xs',
  320: 'card--sm',
  480: 'card--md',
  640: 'card--lg',
})

שינוי גודל Canvas אוטומטי

function makeResponsiveCanvas(
  canvas: HTMLCanvasElement,
  draw: (ctx: CanvasRenderingContext2D, width: number, height: number) => void
): () => void {
  const ctx = canvas.getContext('2d')!
  const dpr = window.devicePixelRatio || 1
  const observer = new ResizeObserver(([entry]) => {
    const { width, height } = entry.contentRect
    canvas.width = Math.round(width * dpr)
    canvas.height = Math.round(height * dpr)
    canvas.style.width = `${width}px`
    canvas.style.height = `${height}px`
    ctx.scale(dpr, dpr)
    draw(ctx, width, height)
  })
  observer.observe(canvas.parentElement ?? canvas)
  return () => observer.disconnect()
}

React hook useResizeObserver

function useResizeObserver<T extends HTMLElement = HTMLDivElement>() {
  const ref = useRef<T>(null)
  const [rect, setRect] = useState<DOMRectReadOnly | null>(null)

  useEffect(() => {
    const el = ref.current
    if (!el) return

    const observer = new ResizeObserver(([entry]) => setRect(entry.contentRect))
    observer.observe(el)
    return () => observer.disconnect()
  }, [])

  return [ref, rect] as const
}

function AdaptiveChart({ data }: { data: number[] }) {
  const [ref, rect] = useResizeObserver<HTMLDivElement>()
  const isCompact = (rect?.width ?? 0) < 400

  return (
    <div ref={ref} style={{ width: '100%' }}>
      {isCompact ? <CompactChart data={data} /> : <FullChart data={data} />}
    </div>
  )
}

יישום Canvas אדפטיבי: מדריך שלב אחר שלב

  1. קבל הפניה לאלמנט הקונטיינר או ל-Canvas עצמו.
  2. צור מופע של ResizeObserver והעבר callback.
  3. ב-callback, עדכן את מאפייני הרוחב/גובה תוך התחשבות ב-devicePixelRatio.
  4. קרא ל-@container על הקונטיינר או ה-Canvas.
  5. כאשר הרכיב מתפרק, תמיד קרא ל-function applyContainerBreakpoints( element: HTMLElement, breakpoints: Record<number, string> ): () => void { const sortedBreakpoints = Object.entries(breakpoints) .map(([w, cls]) => [Number(w), cls] as [number, string]) .sort(([a], [b]) => a - b) const observer = new ResizeObserver(([entry]) => { const width = entry.contentRect.width sortedBreakpoints.forEach(([, cls]) => element.classList.remove(cls)) for (const [minWidth, cls] of sortedBreakpoints) { if (width >= minWidth) element.classList.add(cls) } }) observer.observe(element) return () => observer.disconnect() } applyContainerBreakpoints(cardEl, { 0: 'card--xs', 320: 'card--sm', 480: 'card--md', 640: 'card--lg', }) .

טעויות נפוצות עם ResizeObserver וכיצד להימנע מהן

  • תמיד בטל הרשמה. קרא ל-function makeResponsiveCanvas( canvas: HTMLCanvasElement, draw: (ctx: CanvasRenderingContext2D, width: number, height: number) => void ): () => void { const ctx = canvas.getContext('2d')! const dpr = window.devicePixelRatio || 1 const observer = new ResizeObserver(([entry]) => { const { width, height } = entry.contentRect canvas.width = Math.round(width * dpr) canvas.height = Math.round(height * dpr) canvas.style.width = `${width}px` canvas.style.height = `${height}px` ctx.scale(dpr, dpr) draw(ctx, width, height) }) observer.observe(canvas.parentElement ?? canvas) return () => observer.disconnect() } בעת פירוק; אחרת, נשארות הפניות מרומזות שעלולות לגרום לדליפות זיכרון.
  • בצע אופטימיזציה לחישובים כבדים. עבור Canvas או גרפים, השתמש ב-debounce או throttle. העיכוב של 150 אלפיות שנייה בדוגמה לעיל הוא איזון טוב, ומפחית רינדורים ב-60%.
  • מדוד contentRect, לא borderBoxSize, אלא אם כן אתה צריך לכלול גבול. ב-90% מהמקרים, contentRect מספיק.
  • בסביבות SSR, השבת או עטף ב-guard. ResizeObserver עובד רק בצד הלקוח, אז ודא שהקוד לא רץ לפני function useResizeObserver<T extends HTMLElement = HTMLDivElement>() { const ref = useRef<T>(null) const [rect, setRect] = useState<DOMRectReadOnly | null>(null) useEffect(() => { const el = ref.current if (!el) return const observer = new ResizeObserver(([entry]) => setRect(entry.contentRect)) observer.observe(el) return () => observer.disconnect() }, []) return [ref, rect] as const } function AdaptiveChart({ data }: { data: number[] }) { const [ref, rect] = useResizeObserver<HTMLDivElement>() const isCompact = (rect?.width ?? 0) < 400 return ( <div ref={ref} style={{ width: '100%' }}> {isCompact ? <CompactChart data={data} /> : <FullChart data={data} />} </div> ) } ברינדור בצד השרת.

תהליך עבודה: ממשימה לפריסה

שלב פעולות תוצאה
ניתוח זיהוי רכיבים הדורשים התאמת קונטיינר רשימת אלמנטים ונקודות שבירה
עיצוב בחירת תבנית (hooks, מחלקות, container queries) ארכיטקטורת מערכת אדפטיבית
יישום כתיבת hooks, debounce, בדיקות קוד מוכן לאינטגרציה
בדיקות אימות על קונטיינרים שונים ו-IE11 (polyfill) ללא רגרסיות
פריסה פריסה לסביבת הייצור רכיבים פועלים כראוי
דוגמה להגדרת נקודות שבירה לכרטיס מוצר

בפרויקט מסחר אלקטרוני, כרטיס מוצר יכול להופיע ברשת הקטלוג (רוחב 300px) או בסליידר (רוחב 400px). באמצעות observer.observe(), הגדרנו מחלקות לשלושה מצבים: קומפקטי (עד 300px), בינוני (300-500px), ומלא (מ-500px). זה אפשר לנו לשנות את מספר השדות המוצגים ואת מיקום כפתור "הוסף לסל".

מה כלול בפתרון סוהר

  • הגדרת ResizeObserver לכל הרכיבים הנדרשים
  • React resize hooks עם debounce אופציונלי
  • התאמת רכיבים לפי רוחב קונטיינר (לא viewport)
  • שינוי גודל Canvas אוטומטי בעת הצורך
  • תיעוד על נקודות שבירה

ציר זמן: מ-0.5 יום לרכיב בודד עד 3 ימים לדשבורד שלם.

הניסיון המוכח של הצוות המוסמך שלנו: למעלה מ-5 שנים בפיתוח frontend, למעלה מ-20 פרויקטים שהושלמו. הגישה המובטחת שלנו מבטיחה ביצועים אופטימליים. צור קשר כדי לדון בפרויקט שלך. בקש ביקורת על הרכיבים הנוכחיים שלך — נציע את הפתרון האופטימלי.