RichStyle: The Angel is in The Detail.

كل ما تود معرفته حولخاصية CSS will-change

مقدمة

إن كنت قد قمت يوماً بعملية تحريك لعنصر ما على صفحة معينة ولاحظت أن العنصر لا يتحرك بالسلاسة التي كنت تتوقعها في المتصفحات المبنية على المكتبة WebKit خلال أداءها لعمليات CSS معينة، خصوصاً عمليات التحويل transforms والتحريك animations، فلابد أنك صادفت مصطلح التسريع من خلال العتاد ”hardware acceleration“ من قبل.

وحدة المعالجة المركزية CPU، ووحدة معالجة الرسوميات GPU، والتسريع بواسطة العتاد Hardware Acceleration

بعبارات موجزة، يعني مصطلح التسريع بواسطة العتاد Hardware Acceleration أن وحدة معالجة الرسوميات GPU ستساعد المتصفح لديك في عرض صفحة ما من خلال أداء بعض المهام ذات الأعباء الثقيلة بدلاً من إلقاءها كلها على كاهل وحدة المعالجة المركزية CPU. عندما يتم تسريع عملية CSS معينة من خلال العتاد، تحظى هذه العملية بدفعة قوية من حيث السرعة مما يؤدي لعرض الصفحة بصورة أسرع.

كما تُظهِر تسمية كل من CPU و GPU، تمثل كلاهما وحدة معالجة. تتوضع وحدة المعالجة المركزية CPU على اللوحة الأم للحاسوب، وتعالج كل شيء تقريباً، وتُعرَف بوصفها دماغ الحاسوب. تتوضع وحدة معالجة الرسوميات GPU على بطاقة الرسوميات في الحاسوب، وهي مسؤولة عن معالجة الرسوميات وعرضها. علاوة على ذلك، تم تصميم وحدة معالجة الرسوميات GPU تحديداً لأداء العمليات الحسابية والهندسية المعقدة اللازمة لعرض الرسوميات. وبالتالي، يمكن أن يؤدي تفريغ العمليات على GPU إلى تحقيق مكاسب هائلة على صعيد الأداء كما يمكنها أيضاً الحد من متاعب وحدة المعالجة المركزية CPU على الأجهزة المحمولة.

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

لا يتم عادة تسريع عمليات التحريك والتحويل والنقل في CSS تلقائياً بواسطة GPU، وإنما يتم تنفيذها بواسطة برنامج محرك العرض الأبطأ والتابع للمتصفح. ومع ذلك، توفر بعض المتصفحات تسريعاً عتادياً من خلال خصائص معينة لتوفير أداء أفضل في العرض. على سبيل المثال، تُعد خاصية الشفافية opacity إحدى خصائص CSS المعدودة التي يمكن تسريعها بنجاح تام لأن وحدة معالجة الرسوميات GPU يمكنها معالجتها بسهولة. بصورة رئيسية، فإن أي طبقة تود أنت تطبيق تأثير التلاشي fade على الشفافية فيها بواسطة عملية نقل أو تحريك من CSS، سيكون المتصفح عملياً ذكياً بما فيه الكفاية لتحميلها على كاهل وحدة معالجة الرسوميات GPU ومعالجتها هناك، وستكون سريعة جداً. (من بين كل الأشياء في CSS)، تعد الشفافية الأكثرَ فعالية ولن تواجه أي مشاكل في استخدامها. من العمليات الأخرى الشائعة على صعيد التسريع بواسطة العتاد عمليات التحويل ثلاثية الأبعاد CSS 3D transforms.

قديماً: الحيلة translateZ() (أو translate3d())

منذ مدة ونحن لا نزال حتى الآن نستخدم ما بات يعرف بحيلة translateZ() (أو translate3d())، (تدعى أيضاً حيلة التحويل الفارغ null transform hack) لـ خداع المتصفح وإرغامه على دفع عمليات التحريك والتحويل التي نريدها للاستعانة بالتسريع بواسطة العتاد. كنا نقوم بذلك من خلال إضافة عملية تحويل ثلاثية الأبعاد بسيطة إلى عنصر لن يتم تحويله في الفضاء ثلاثي الأبعاد. على سبيل المثال، يمكن تسريع عنصر يتحرك في مساحة ثنائية الأبعاد تسريعاً عتادياً بإضافة القاعدة البسيطة التالية إليه:

transform: translate3d(0, 0, 0);

يسفر التسريع العتادي لعملية ما عن إنشاء ما يُعرف بطبقة تنضيد compositor layer يتم رفعها إلى وحدة معالجة الرسوميات GPU وتكوينها عليها. ومع ذلك، قد لا تكون حيلة إرغام المتصفح على إنشاء طبقة تنضيد حلاً لاختناقات معينة في الأداء في صفحة معينة. تستطيع أساليب إنشاء الطبقات تعزيز سرعة الصفحة، لكنها تكون مصحوبة بتكلفة: فهي تستهلك من ذاكرة النظام RAM ومن معالج الرسوميات GPU (المحدود في الأجهزة المحمولة تحديداً) واستهلاك الكثير منها يمكن أن يعطي تأثيراً سلبياً (خاصة في الأجهزة المحمولة)، لذا يجب استخدامها بحكمة، وينبغي أن تكون واثقاً أن التسريع العتادي لعملياتك سيعزز فعلاً من أداء صفحتك، وأن مشكلة عنق الزجاجة في الأداء لن تتسبب بها عملية أخرى على صفحتك.

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

الحل الجديد: الخاصية will-change الرائعة

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

على سبيل المثال، عند تطبيق عمليات التحويل ثلاثية الأبعاد في CSS على عنصر ما، قد يتم تعزيز العنصر ومكوناته في طبقة معينة، كما ذكرنا آنفاً، قبل أن يتم تكوينها (رسمها على الشاشة) لاحقاً. ومع ذلك، فإن وضع عنصر ما في طبقة جديدة يعد إجراءً مكلفاً نسبياً، الأمر قد يؤخِر الشروع في عملية التحريك في جزء ملحوظ من الثانية، مسبباً ذلك ”الأداء المتقطع“ الملحوظ.

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

باستخدام will-change، يمكن للتلميح للمتصفح بشأن عملية تحويل قادمة أن يكون ببساطةِ عملية إضافة القاعدة التالية إلى العنصر الذي تتوقع أن يخضع للتحويل:

will-change: transform;

يمكنك أيضاً التصريح للمتصفح بنيتك تغيير موضع تمرير عنصر ما (موضع العنصر في نافذة التمرير المرئية ومقدار ما سيكون مرئياً منه ضمن هذه النافذة)، أو محتوياته، أو واحدة أو أكثر من قيم خصائص CSS من خلال تحديد أسماء الخصائص التي تتوقع تغيرها. إن كنت تتوقع أو تعتزم تغيير عدة قيم/جوانب في عنصر ما، يمكنك توفير لائحة بقيم مفصولة بفواصل. على سبيل المثال، إذا كنت تتوقع أن يتم تحريك العنصر ونقله (تغيير موضعه) أو أن يتم تغيير خاصية التلاشي opacity، يمكنك التصريح بذلك للمتصفح على النحو التالي:

will-change: transform, opacity;

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

هل يمتد أثر الخاصية will-change على العنصر المطبقة عليه إلى ما وراء التلميح للمتصفح بشأن التغييرات على العنصر؟

الجواب نعم ولا — يعتمد ذلك على الخصائص التي تحددها أنت وتُبلِغ المتصفح بشأنها. إن كانت أي قيمة أولية (افتراضية) لخاصية ما ستنشئ سياقاً تجميعياً على العنصر، فإن تعيين تلك الخاصية في will-change سوف ينشئ سياقاً تجميعياً على العنصر.

على سبيل المثال، كلا الخاصيتين clip-path و opacity تقودان لإنشاء سياق تجميعي على العنصر الخاضع لهما، عندما يتم استخدامهما بقيم غير القيم الأولية (الافتراضية). وبالتالي، فإن استخدام إحدى هاتين الخاصيتين (أو كليهما) كقيم لـ will-change سينشئ سياقاً تجميعياً على العنصر، حتى قبل أن يحدث التغيير فعلياً. ينطبق ذلك على الخصائص الأخرى التي ستنشئ سياقاً تجميعياً على عنصر ما.

أيضاً، يمكن لبعض الخصائص أن تقود لإنشاء كتلةٍ حاوية لعناصر ثابتة الموضع. على سبيل المثال، ينشئ عنصر خاضع لعملية نقل transform كتلة حاوية لكل سلالاتها المتوضعة، حتى تلك التي تم ضبطها كـ position: fixed. لذا، إذا قادت خاصية ما لإنشاء كتلة حاوية، فإن تعيينها كقيمة لـ will-change سيقود أيضاً إلى توليد كتلة حاوية لعناصر ثابتة الموضع.

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

استخدام will-change: المسموح والممنوع

إدراك وظيفة will-change، قد يكون مغرياً جداً للتفكير بأنه: ”بوسع المتصفح الآن تحسين كـــــــل شيء!“. أعني أن ذلك يبدو منطقياً، أليس كذلك؟ من منا لا يريد أن تكون كافة التغييرات لديه مصقولة وجاهزة عند الطلب؟

فبقدر ما تتمتع به will-change من قوة وتميز، فهي لا تختلف عن أي نوع آخر من أنواع القوة، لذا، فكما هي الحال مع مصادر الطاقة الأخرى، لا بد من التحلي بالمسؤولية. يجب استخدام will-change بحكمة، وإلا فقد ينتهي بك المطاف إلى أضرار في الأداء قد تؤدي إلى انهيار الصفحة لديك.

كما هو الحال في أي تلميحات تتعلق بالأداء، ثمة تأثيرات جانبية لـ will-change لا يمكن اكتشافها مباشرة (في نهاية المطاف، هي مجرد وسيلة للتخاطب مع المتصفح خلف الكواليس)، لذا قد تتسبب بمتاعب عند استخدامها. فيما يلي بعض الأشياء التي يتعين أخذها في الاعتبار عند استخدام هذه الخاصية، لتكون واثقاً من أنك حققت من وراءها أفضل ما يمكن من مكاسب دون الوقوع في المتاعب الناجمة عن سوء استخدامها.

لا تستخدم will-change للتصريح بتغييرات موجهة للكثير من الخصائص أو العناصر

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

*,
*::before,
*::after {
    will-change: all;
}

بقدر ما تبدو جيدة (أعلم أنها بدت جيدة ومنطقية بالنسبة لي في بادئ الأمر)، فهي ضارة جداً في الحقيقة، وغير صالحة، ليس فقط أن كافة الكلمات المفتاحية قيم غير صالحة لـ will-change (سنتناول لائحة القيم الصالحة وغير الصالحة لاحقاً ضمن المقالة)، لكن مثل هذه القاعدة الشاملة لن تكون مفيدة. كما ترى، المتصفح يحاول فعلاً تحسين أي شيء وصقله جهد استطاعته (هل تذكر الخاصية opacity وعمليات التحويل ثلاثية الأبعاد؟)، ولذا فالإيعاز له صراحة لا يغير فعلياً أي شيء أو يساعد في عمليات التحسين والصقل بأي شكل من الأشكال. في واقع الأمر، القيام بذلك يفتح الأبواب مُشرَعةً أمام الكثير من الأضرار، وذلك لأن بعض التحسينات الأقوى التي يحتمل أن تكون مرتبطة بالخاصية will-change ينتهي بها المطاف إلى استهلاك الكثير من موارد الجهاز، وحين يُمعِن في ذلك بهذه الطريقة يمكن أن يقود ذلك إلى بطء الصفحة أو حتى انهيارها.

بعبارة أخرى، فإن مسألة وضع المتصفح على أهبة الاستعداد من أجل تغييرات قد تحدث أو لا يحدث هي ​​فكرة سيئة، وستضر أكثر من أن تنفع. فلا تُقدِم على ذلك.

امنح المتصفح وقتاً كافياً للعمل

لقد أُطلق على الخاصية will-change هذا الاسم لسبب واضح: إبلاغ المتصفح بالتغييرات التي سوف تحدث، وليس بالتغييرات التي تجري حالياً. فباستخدام will-change، نحن نطلب من المتصفح إجراء تحسينات معينة للتغييرات التي نصرح بها، ولوضعها موضع التنفيذ، يحتاج المتصفح لبعض الوقت لتنفيذ هذه التحسينات، بحيث أنه حالَ حدوث التغييرات، يمكن تطبيق التحسينات دون أي تأخير.

ضبط will-change على عنصر معين مباشرة قبل تغيره ليس له تأثير تقريباً. (قد يكون ذلك في الواقع أسوأ من عدم ضبطها على الإطلاق. فقد تتكبد أعباءَ طبقة جديدة عندما لا يكون ما تقوم بتحريكه مهيأً مسبقاً للطبقة الجديدة!) على سبيل المثال، إذا كان التغيير سيَحدُث استجابة لحدثِ وضع مؤشر الماوس على العنصر hover، فإن ما يلي:

.element:hover {
    will-change: transform;
    transition: transform 2s;
    transform: rotate(30deg) scale(1.5);
}

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

على سبيل المثال، إذا كان عنصر ما سيتغير عند النقر عليه، فإن إعداد will-change عند وضع مؤشر الماوس على ذلك العنصر يمنح المتصفح وقتاً كافياً لتحسين هذا التغيير. الزمن الفاصل بين وضع مؤشر الماوس على العنصر والنقر عليه فعلياً من قبل المستخدم كافٍ للمتصفح من أجل ضبط التحسينات، لأن زمن ردة الفعل البشرية بطيئة نسبياً، لذلك فإن ذلك يمنح المتصفح حوالي ٢٠٠ ميلي ثانية كإطار زمني قبل أن يحدث التغيير فعلياً، وهذا كافٍ بالنسبة له لضبط التحسينات.

.element {
    /* style rules */
    transition: transform 1s ease-out;
}
.element:hover {
    will-change: transform;
}
.element:active {
    transform: rotateY(180deg);
}

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

.element {
    transition: opacity .3s linear;
}
/* declare changes on the element when the mouse enters / hovers its ancestor */
.ancestor:hover .element {
    will-change: opacity;
}
/* apply change when element is hovered */
.element:hover {
    opacity: .5;
}

ومع ذلك، فإن وضع مؤشر الماوس على العنصر الأب لا يشير دائماً إلى أن العنصر سيتفاعل بالتأكيد، لذا يمكنك أن تعمد لشيء من قبيل ضبط will-change حين يصبح مشهد ما نشطاً ضمن التطبيق لديك، أو إذا بات العنصر متوضعاً داخل الجزء المرئي من منفذ العرض viewport، مما يزيد من احتمال أن يتم التفاعل معه.

أزل will-change بعد إنجاز التغييرات

التحسينات التي يجريها المتصفح على التغييرات التي تكون على وشك الحدوث عادة ما تكون مكلفة، وكما ذكرنا سابقاً، يمكن أن تستهلك الكثير من موارد الجهاز. السلوك المعتاد للمتصفح حيال التحسينات التي يجريها هو إزالة هذه التحسينات والعودة إلى السلوك العادي في أسرع وقت ممكن. ومع ذلك، فالخاصية will-change تقمع هذا السلوك بغية الاحتفاظ بالتحسينات لمدة أطول مما يفعل المتصفح.

وعلى هذا المنوال، يجب أن تتذكر دائماً إزالة will-change بعد إنجاز التغييرات على العنصر، بحيث يتمكن المتصفح من استرداد الموارد التي تستدعيها التحسينات.

لا يمكن إزالة will-change إن تم التصريح بها ضمن ورقة الأنماط، وهو ما يبرر دائماً التوصية بتفعيلها وتعطيلها باستخدام جافاسكريبت. فمن خلال البرمجة النصية، يمكنك التصريح بالمتغيرات للمتصفح، ثم إزالة will-change بعد إنجاز التغييرات، وذلك بالإصغاء للحظة توقف التغييرات. على سبيل المثال، تماماً كما فعلنا في قواعد الأنماط style rules في المقطع السابق، يمكنك الإصغاء لللحظة التي يتم فيها وضع مؤشر الماوس على العنصر (أو سلفه)، ثم ضبط will-change على mouseenter. إن كان العنصر لديك يخضع لعملية تحريك animation، يمكنك الإصغاء لمعرفة اللحظة التي انتهت فيها عملية التحريك ياستخدام حدث DOM ـ animationEnd، ثم إزالة will-change حال إطلاق الحدث animationEnd.

// Rough generic example
// Get the element that is going to be animated on click, for example
var el = document.getElementById('element');

// Set will-change when the element is hovered
el.addEventListener('mouseenter', hintBrowser);
el.addEventListener('animationEnd', removeHint);

function hintBrowser() {
    // The optimizable properties that are going to change
    // in the animation’s keyframes block
    this.style.willChange = 'transform, opacity';
}

function removeHint() {
    this.style.willChange = 'auto';
}

كان Craig Buckler قد كتب مقالة حول التقاط أحداث التحريك في CSS باستخدام جافاسكريبت يتعين عليك الاطلاع عليها إن لم تكن متآلفاً مع هذه القضية. ثمة أيضاً مقال حول التحكم بعمليات التحريك والنقل في CSS على موقع CSS-Tricks الذي يستحق نظرة أيضاً.

استخدم will-change باعتدال في أوراق الأنماط

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

أحد الأمثلة هو ضبط will-change على عدد محدود من العناصر التي من المحتمل أن تكون قد شهدت تفاعلاً من قبل المستخدم مراراً وتكراراً، وأنه ينبغي أن تستجيب لتفاعل المستخدم بصورة خاطفة. العدد المحدود من العناصر يعني أن التحسينات التي تمت من قبل المتصفح لن تتم المبالغة في استخدامها وبالتالي لن تضر كثيراً. على سبيل المثال، نقل الشريط الجانبي عن طريق تحريكه خارجاً حين يطلبه المستخدم. القاعدة التالية ستكون مناسبة:

.sidebar {
    will-change: transform;
}

مثال آخر يستخدم will-change على عنصر يتغير باستمرار تقريباً، مثل العنصر الذي يستجيب لحركة الماوس التي يؤديها المستخدم ويتم تحريكها حول الشاشة مع حركة الماوس. في هذه الحالة، يكفي مجرد التصريح بقيمة will-change في ورقة الأنماط، لأنه يصف بدقة أن العنصر سوف يتغير بانتظام/باستمرار، ولذا يجب أن يظل مصقولاً.

.annoying-element-stuck-to-the-mouse-cursor {
    will-change: left, top;
}

قِيَم الخاصية will-change

تتخذ الخاصية will-change واحدة من أربع قيم محتملة: auto و scroll-position و contents و custom-ident.

تُستخدم القيمة custom-ident لتحديد اسم (أو أسماء) خاصية واحدة أو أكثر تتوقع تغيرها. تُفصل الخصائص المتعددة بفواصل. فيما يلي أمثلة لتصريحات will-change مع أسماء لخصائص محددة:

will-change: transform;
will-change: opacity;
will-change: top, left, bottom, right;

تَستبعد قيمة custom-ident الكلمات الرئيسية will-change و none و all و auto و scroll-position و contents، بالإضافة إلى الكلمات الرئيسية المستثناة عادة من <custom-ident>. لذا، وكما ذكرنا في بداية المقال، فإن التصريح will-change: all غير صالح، وبالتالي سيتم تجاهله من قبل المتصفح.

لا تشير القيمة auto لأي هدف أو غاية معينة، وهذا يعني أن المتصفح لن يضبط أي تحسينات خاصة غير تلك التي يقوم بها عادة.

تشير القيمة scroll-position، كما يوحي اسمها، إلى أنك تتوقع تغير موضع تمرير عنصر ما في أي لحظة في المستقبل القريب. هذه القيمة مفيدة لأنه، عند استخدامها، سيعمد المتصفح لتهيئة المحتوى وعرضه بصورة تتجاوز مسألة ما هو مرئي في إطار التمرير على عنصر قابل للتمرير. المتصفحات غالباً ما تعرض المحتوى داخل إطار التمرير، وبعض المحتوى يتخطى ذلك الإطار، محققاً التوازن بين الذاكرة وتوفير الوقت من خلال العرض الذي تم تخطيه مقابل جعل التمرير يبدو سلساً. باستخدام will-change: scroll-position: يمكن تحقيق المزيد من تحسينات العرض بحيث يتم إنجاز عمليات التمرير الأطول و/أو الأسرع للمحتوى بسلاسة.

تشير القيمة contents إلى أن محتوى العنصر يُتوقع أن يتغير . تعمد المتصفحات عادة لـ ”التخزين المؤقت“ للعناصر مع مرور الوقت، وذلك لأن معظم الأشياء لا تتغير بتلك الصورة المتكررة، أو أنها تغير موضعها فقط. ستتم قراءة هذه القيمة من قبل المتصفح كإشارة للحد من عمليات التخزين المؤقت على العنصر، أو تجنب التخزين المؤقت للعنصر كلياً، لأنه إذا كان محتوى العنصر يتغير بانتظام، فإن الحفاظ على ذاكرة التخزين المؤقت للمحتوى سيكون عديم الجدوى ومضيعة للوقت، وبالتالي سيوقف المتصفحُ التخزينَ المؤقت وسيواصل عرض العنصر من الصفر كلما تغير محتواه.

كما تمت الإشارة من قبل، فإن بعض الخصائص لن يكون لها أي تأثير عند تحديدها في will-change، لأن المتصفح لا يؤدي أي تحسينات خاصة للتغيرات في معظم الخصائص. لا يزال تحديدها آمناً، على الرغم من أنها ببساطة عديمة التأثير. قد تؤدي خصائص أخرى إلى خلق سياقات تجميع (opacity ،clip-path، الخ) و/أو كتل حاوية.

دعم المتصفحات

عند كتابة هذه المقالة، لم يكن يدعم الخاصية will-change إلا المتصفحات Chrome Canary 36+ و Opera Developer 23+ و Firefox Nightly. ثمة نية لتوفيرها في القناة المستقرة أيضاً. ويعتقَد إنه لن يمضيَ وقت طويل قبل أن تصبح متوفرة في في كافة المتصفحات الحديثة.

كلمة أخيرة

ستساعدنا الخاصية will-change في كتابة شيفرة برمجية نظيفة (دون أساليب التفافية) وبأداء أمثل، وفي التأكيد على أهمية السرعة والأداء لعمليات CSS التي نلجأ إليها. ولكن، كما هو الحال دائماً، القوة الكبيرة تحمل المرء مسؤولية كبيرة، والخاصية will-change هي واحدة من بين تلك الخصائص التي لا ينبغي أن تؤخذ على محمل الجد، وإنما يتعين استخدامها بحكمة. وهنا، سأقتبس كلام Tab Atkins Jr.، محرر مواصفات الخاصية will-change:

استخدم الخاصية will-change مع الخصائص التي سوف تغيرها فعلاً، في العناصر التي تشهد تغيراً فعلاً. وأزلها عندما تتوقف تلك العناصر عن التغير.

شكراً لكم على قراءتكم لهذه المقالة!

جزيل الشكر لـ Paul Lewis لمراجعته وتقييمه، ولـ Tab Atkins لدعمه وإجاباته، ولكل من Bruce Lawson و Mathias Bynens لمراجعتهما المقالة.