حافظ على دقة مجموعات أسطر SplitText بإعادة إنشائها عند تغيّر تخطيط النص. استخدم التقسيم التلقائي للمحفزات المدعومة، وأضف عمليات إعادة إنشاء صريحة عند تغيّر الطباعة، وقارن النتيجة بنص المتصفح غير المقسّم في معاينة سطح المكتب على Mac.

هذا الدليل موجّه إلى من يحرّر صفحة في المتصفح باستخدام GSAP SplitText وعنوان مرن. تتمثل المهمة في إبقاء كل غلاف سطر مُنشأ متوافقًا مع الكلمات التي تنتمي حاليًا إلى ذلك السطر المرئي، بما في ذلك الحالات التي يظل فيها عرض العنوان ثابتًا بينما يتغير حجم خطه.

لماذا قد تخلّف الطباعة المرنة مجموعات الأسطر عن النص؟

يحيط غلاف السطر المُنشأ بمجموعة محددة من الكلمات. وبعد تغيّر المساحة المتاحة أو الطباعة، قد يلزم إعادة إنشاء هذه المجموعة. توثّق GSAP استخدام autoSplit: true عند اكتمال تحميل الخطوط وتغيّر العرض، عندما تكون الأسطر ضمن التقسيم. ولا تثبت هذه المحفزات الموثّقة وجود مراقب عام لكل تغيّر في الطباعة. وثائق SplitText

لنفترض وجود عنوان يتضمن font-size: clamp(2rem, 4vw, 4rem) داخل حاوية لا يتجاوز عرضها 42rem. تعرّف MDN الدالة clamp() بأنها قيمة مفضلة تحدّها قيمة دنيا وأخرى قصوى. في هذا المثال، يتبع حجم الخط المفضّل عرض إطار العرض حتى بعد بلوغ الحاوية حدّها الأقصى. دالة CSS ‏clamp()

يستخدم الحساب التالي حجمًا توضيحيًا لخط الجذر يبلغ 16 بكسل CSS، ويفترض توافر مساحة تكفي لبلوغ الحاوية حدّها الأقصى. هذه أبعاد محسوبة، وليست نتائج مقاسة في المتصفح أو أعدادًا متوقعة للأسطر.

عرض إطار العرض عرض الحاوية بعد تطبيق الحد الأقصى حجم الخط المحسوب
900 بكسل CSS 672 بكسل CSS 36 بكسل CSS
1200 بكسل CSS 672 بكسل CSS 48 بكسل CSS
1600 بكسل CSS 672 بكسل CSS 64 بكسل CSS

يظل عرض الحاوية كما هو بينما تكبر الأحرف. والاستنتاج العملي هو أن مراقبة العرض وحدها لا تغطي هذه الحالة. اعتبر تغيّر حجم الخط المحسوب سببًا آخر لإعادة الإنشاء، ثم تحقّق من مواضع الكلمات الناتجة.

حدّد الدقة بمقارنة العرض غير المقسّم في المتصفح عند الأبعاد والأنماط نفسها. لا تشترط بقاء العنوان على عدد أسطره الأصلي؛ إذ يُسمح للتخطيط المرن بإنتاج أسطر مختلفة.

أنشئ مرجعًا غير مقسّم قبل تغيير الحركة

أنشئ نسختين من عنوان اصطناعي قصير في المعاينة المحلية. امنحهما العرض والخط والحجم والسماكة والتباعد وقواعد الالتفاف نفسها. اترك النسخة الأولى كما هي وطبّق SplitText على الثانية. تتيح هذه المقارنة المؤقتة ملاحظة المجموعات القديمة من دون افتراض الموضع الذي ينبغي أن تلتف عنده كلمة بعينها.

ابدأ بالمسافات البيضاء والالتفاف المعتادين. تحدد مواصفة W3C لوحدة CSS Text كيفية تحكم white-space في دمج المسافات البيضاء والالتفاف المرن؛ كما تحدد قواعد منفصلة لكسر الأسطر والتباعد. ينبغي لإعادة الإنشاء الحفاظ على القواعد المقصودة بدلًا من استبدالها بفواصل أسطر مُدرجة يدويًا. وحدة CSS Text المستوى 3

إذا كانت الصفحة تستخدم خطوط الويب، فانتظر document.fonts.ready قبل التقسيم الأول. توثّق MDN أن هذا الوعد يُحل بعد اكتمال عمليات تحميل الخطوط والتخطيط ذات الصلة. يوفّر ذلك نقطة قياس أولية، لكنه لا يجمّد تغيّرات التخطيط اللاحقة. FontFaceSet: الخاصية ready

تحقّق أيضًا من الخط المستخدم فعليًا في المتصفح. تميّز MDN بين الخطوط المستخدمة والخطوط المعلنة كلها؛ فقد لا يُستخدم خط اختياري، مثلًا، إذا لم يصل خلال نافذة تحميله. لا ينبغي تفسير انتظار الجاهزية على أنه دليل على أن كل خط معلن أصبح الخط المعروض. Document: الخاصية fonts

نفّذ التقسيم التلقائي مع فحص صريح للحجم المرن

تنشئ وحدة المتصفح الكاملة التالية مرجعًا غير مقسّم ونسخة متحركة وزرًا بعنوان Toggle spacing. استخدم صفحة معاينة مؤقتة ضمن مشروع JavaScript قائم يحلّ فيه المجمّع استيرادات npm، ويدعم await في المستوى الأعلى، ويشغّل نقطة دخول المتصفح بعد وجود متن المستند. ثبّت Node.js وnpm على جهاز Mac.

ثبّت GSAP من مجلد المشروع باستخدام الأمر التالي. استخدم GSAP 3.13 أو إصدارًا أحدث لسير العمل هذا المعتمد على الاستدعاء الراجع. تتناول وثائق تثبيت GSAP التثبيت عبر npm وتسجيل الإضافة صراحةً. التثبيت

npm install gsap

استبدل وحدة نقطة دخول المتصفح في المعاينة المؤقتة بهذا الرمز. تتبع التهيئة نمط SplitText.create() الموثّق. تستخدم حركة التلاشي gsap.from() للتحريك من عتامة صفرية إلى المظهر الحالي. SplitText.create()، gsap.from()

import { gsap } from 'gsap';
import { SplitText } from 'gsap/SplitText';

gsap.registerPlugin(SplitText);

const style = document.createElement('style');
style.textContent = `
.flow-demo {
  width: min(100%, 42rem);
  font-family: system-ui, sans-serif;
}
.flow-demo h2 {
  font-size: clamp(2rem, 4vw, 4rem);
  line-height: 1.15;
  font-weight: 600;
  margin: 1rem 0;
  white-space: normal;
  text-wrap: wrap;
}
.flow-line { outline: 1px solid #aaa; }
`;
document.head.append(style);

const host = document.createElement('section');
host.className = 'flow-demo';
const reference = document.createElement('h2');
reference.textContent =
  'Panel Alpha holds a series of soft shapes beside Panel Beta.';
const target = reference.cloneNode(true);
const button = document.createElement('button');
button.type = 'button';
button.textContent = 'Toggle spacing';
host.append(reference, target, button);
document.body.append(host);

await document.fonts.ready;

const split = SplitText.create(target, {
  type: 'lines',
  linesClass: 'flow-line',
  autoSplit: true,
  onSplit(self) {
    return gsap.from(self.lines, {
      opacity: 0,
      duration: 0.3,
      stagger: 0.04
    });
  }
});

let timer;
let fontSize = getComputedStyle(target).fontSize;

function checkFluidSize() {
  clearTimeout(timer);
  timer = setTimeout(() => {
    const next = getComputedStyle(target).fontSize;
    if (next !== fontSize) {
      fontSize = next;
      split.split();
    }
  }, 150);
}
window.addEventListener('resize', checkFluidSize);

let spaced = false;
button.addEventListener('click', () => {
  spaced = !spaced;
  reference.style.letterSpacing = target.style.letterSpacing =
    spaced ? '0.06em' : 'normal';
  split.split();
});

تُنشأ الحركة داخل onSplit() وتُعاد قيمتها كي يتمكن SplitText من تنظيفها ومزامنتها عبر عمليات إعادة الإنشاء. توثّق GSAP سير العمل هذا في الإصدار 3.13 والإصدارات الأحدث. وثائق SplitText

يتحقق معالج تغيير الحجم المضاف من حجم الخط المحسوب فقط، ويطلب إعادة الإنشاء بعد توقف تغيير الحجم مؤقتًا. التأخير البالغ 150 مللي ثانية خيار توضيحي في التنفيذ. يهدف هذا المثال إلى دقة المجموعات بعد استقرار تغيير الحجم؛ ولا يضمن صحة التجميع في كل إطار وسيط أثناء التغيير.

يوضح زر التباعد محفزًا صريحًا ثانيًا. فهو يغيّر النسختين، ثم يستدعي split.split(). توثّق GSAP أن هذه الطريقة تعيد الحالة السابقة للتقسيم أولًا عند الحاجة. وقد يتسبب تغيّر العرض وحجم الخط في طلبات إعادة إنشاء متداخلة في هذا المثال الصغير؛ فاجمعها إذا كشف تحليل الأداء عن عمل غير ضروري في صفحة أكبر. split()

اجتازت الوحدة فحص صياغة JavaScript، ونُفذت حسابات الأبعاد التوضيحية. لم يُنفّذ تخطيط المتصفح أو الحركة هنا؛ أجرِ الفحوص البصرية التالية في المعاينة المحلية.

اختر محفزات إعادة الإنشاء وفقًا لما يتغير في تخطيطك

يراقب المثال تعبيرًا واحدًا لحجم خط مرن. عند تكييفه، حدّد الشيفرة أو حدث التخطيط الذي يغيّر النص، وضع إعادة الإنشاء عند تلك النقطة. لا تفترض أن المثال يكتشف تغييرات الفئات غير المرتبطة، أو الطباعة المعتمدة على الحاوية، أو خصائص الخط المتحركة باستمرار.

ما الذي يتغير في صفحتك؟ المعالجة المقترحة
عرض عنصر النص فعّل سلوك التقسيم التلقائي الموثّق وتحقق من النتيجة.
حجم خط يتأثر بإطار العرض مع ثبات عرض النص قارن الحجم المحسوب بعد تغيير الحجم، ثم أعد الإنشاء عند تغيّره.
أداة تحكم تغيّر تباعد الأحرف أو السماكة أو إعدادات الخط اطلب إعادة الإنشاء بعد تطبيق الأداة للأنماط الجديدة.
الطباعة معتمدة على حاوية محيطة راقب الحاوية التي توفر مدخل الحجم وتحقق من خصائص الطباعة المحسوبة ذات الصلة.
يصبح المكوّن مرئيًا بعد أن كان مخفيًا هيّئه أو أعد إنشاءه بعد أن تكون له أبعاد العرض المقصودة.

في التخطيطات المعتمدة على الحاوية، يبلّغ ResizeObserver عن تغيّرات حجم العنصر، بمعزل عن تغيّر حجم إطار العرض. راقب الحاوية التي توفّر مدخلات التحجيم. ولا يمكن اعتبار مراقبة صندوق النص وحده إشعارًا بكل تغيّر في الأنماط المحسوبة. ResizeObserver

تجنّب إعادة الإنشاء بلا تمييز عند كل تغيير ملحوظ في الارتفاع. فقد تؤثر إعادة الإنشاء نفسها في التخطيط. توثّق MDN دورات مراقب تغيير الحجم وتشرح أن تجنّب حلقة التغذية الراجعة يتطلب ضبط التبعية؛ فتأجيل العمل إلى إطار آخر لا يزيل دورة لا نهائية كامنة. قارن المدخلات ذات الصلة قبل طلب إعادة إنشاء أخرى. أخطاء المراقبة في ResizeObserver

إذا تغيّر نص العنوان، فأعِد التقسيم القديم قبل استبدال المحتوى، ثم هيّئ نسخة جديدة انطلاقًا من النص المصدر الجديد. توثّق GSAP أن revert() يعيد المحتوى الأصلي قبل التقسيم. وقد يؤدي تعديل الأغلفة المُنشأة ثم التراجع إلى فقدان تلك التعديلات. revert()

تحقّق من الالتفاف من دون تغيير تشكيل النص في المتصفح

افتح المعاينة المحلية في متصفح Mac وغيّر حجم النافذة ببطء، ثم أفلته. بعد استقرار إعادة الإنشاء والتلاشي، قارن آخر كلمة في كل سطر من النسختين. كرر ذلك عندما تكون الحاوية قد بلغت حدها الأقصى، وعندما يكون عرضها ضيقًا بما يكفي لتصغر. انقر على Toggle spacing عند كل حجم.

استخدم تسلسل التشخيص هذا عند اختلاف النسختين:

  1. تأكد من أن النسختين لهما العرض المتاح والطباعة المحسوبة نفسيهما.
  2. أعد الإنشاء عند الحجم الحالي. إذا زال الاختلاف، فتحرّ عن المحفز المفقود.
  3. إذا استمر الاختلاف، أزل التنسيق من أغلفة الأسطر المُنشأة واختبر مجددًا.
  4. أعد النص غير المقسّم وتحقق من أن CSS الأساسي ينتج الالتفاف المقصود.
  5. غيّر مدخل تخطيط واحدًا في كل مرة حتى تتمكن من إعادة إنتاج الاختلاف.

أبقِ تشكيل الأحرف ضمن محرك النص في المتصفح. تحدد W3C الظروف التي يجب فيها أن يستمر التشكيل عبر حدود العناصر المضمّنة والظروف التي يجب فيها أن ينقطع، بما في ذلك فصل الحشو أو الحدود أو الهوامش للعناصر المضمّنة. وهذا يعني أن تنسيق الأغلفة قد يؤثر في الشيء الذي يجري قياسه. تجنّب إضافة تباعد بين صناديق الأحرف المفردة لمجرد إعادة إنتاج لقطة شاشة سابقة. التشكيل عبر حدود العناصر

لا تحسب الأسطر المرئية بتقسيم innerText عند أحرف السطر الجديد. يعرّف WHATWG innerText بأنه نص معروض له قواعد جمع تشمل النص وفواصل الأسطر الصريحة والحدود البنيوية؛ ولا يوفر مصفوفة بالأسطر المرئية الملتفة تلقائيًا. أبقِ العرض غير المقسّم في المتصفح مرجعًا للمقارنة. الخاصيتان innerText وouterText

التزم بالحدود الموثّقة للمكتبة: تنصح GSAP بتجنب text-wrap: balance مع التقسيم، وتذكر أن SplitText غير مصمم لعُقد نص SVG. للعناوين المتوازنة، أبقِ النص غير مقسّم وحرّك العنصر كله؛ أما أغلفة الأسطر فاستخدم معها الالتفاف المعتاد على عنصر نص HTML. نصائح SplitText وقيوده

أكمل العمل عندما تتبع النسخة المقسّمة النسخة غير المقسّمة عبر تغيّرات العرض والطباعة الفعلية لديك. أبقِ عمليات إعادة الإنشاء الصريحة قريبة من التغييرات التي تستلزمها، واحتفظ بالمرجع أثناء التشخيص، ثم أزل النسخة المكررة المؤقتة وحدود الأسطر قبل دمج العنوان في الصفحة النهائية.

المصادر