هل فكرت يومًا في مقدار العمل الذي يؤديه CSS؟ تغيّر سمة واحدة ويظهر موقعك الإلكتروني بأكمله فجأة بتنسيق مختلف. إنه نوع من السحر. حتى الآن، لم نتمكّن نحن، منتدى مطوّري الويب، سوى من مشاهدة هذا السحر ورصده. ماذا لو أردنا الخروج بسحرنا؟ ماذا لو أردنا أن نصبح ساحرين؟
مرحبًا بك في Houdini.
تتألف مجموعة العمل Houdini من مهندسين من Mozilla وApple وOpera وMicrosoft وHP وIntel وGoogle يعملون معًا لعرض أجزاء معيّنة من محرّك CSS لمطوّري الويب. تعمل المجموعة المعنيّة على مجموعة من مشاريع التطوير بهدف أن تقبلها W3C لتصبح معايير ويب فعلية. وقد وضعوا بأنفسهم بعض الأهداف عالية المستوى، وحوّلوها إلى مسودات للمواصفات، ما أدى بدوره إلى إنشاء مجموعة من المسودات الداعمة ذات المستوى الأدنى.
والهدف من جمع هذه المسودات هو عادةً عندما يتحدث شخص ما عن "هوديني". في وقت كتابة هذه المقالة، كانت قائمة المسودات غير مكتملة وكانت بعض المسودات مجرد عناصر نائبة.
المواصفات
وحدات العمل (المواصفات)
إنّ وحدات العمل ليست مفيدة بحد ذاتها. وهي مفهوم تم تقديمه لتوفير إمكانية استخدام العديد من المسودات اللاحقة. إذا فكّرت في Web Workers عند قراءة "worklet"، فأنت على صواب. هناك تداخل كبير بين المفهومَين. فلماذا نحتاج إلى شيء جديد عندما لدينا عمال؟
يهدف Houdini إلى توفير واجهات برمجة تطبيقات جديدة للسماح لمطوّري الويب بربط رموزهم البرمجية بمحرك CSS والأنظمة المحيطة. من المرجّح أن يكون من المنطقي افتراض أنّه يجب تنفيذ بعض مقتطفات الرمز البرمجي هذه في كل لقطة فردية. ويجب أن يكون بعضها محدّدًا بحكم التعريف. مقتطف من مواصفات Web Worker:
وهذا يعني أنّ عمال الويب غير فعّالين لتنفيذ الإجراءات التي تخطّط Houdini لتنفيذها. لذلك، تمّ اختراع وحدات العمل. تستخدِم وحدات العمل فئات ES2015 لتحديد مجموعة من الطرق التي يتم تحديد توقيعاتها مسبقًا من خلال نوع وحدة العمل. وهي خفيفة وقصيرة الأجل.
CSS Paint API (المواصفات)
يتم تفعيل واجهة برمجة التطبيقات Paint API تلقائيًا في الإصدار Chrome 65. اقرأ المقدمة التفصيلية.
أداة تركيب الصور
واجهة برمجة التطبيقات الموضّحة هنا قديمة. تمّت إعادة تصميم وحدات عمل أداة "المركّب"، ويتمّ الآن اقتراح اسم "وحدة عمل الرسوم المتحركة" لها. يمكنك الاطّلاع على مزيد من المعلومات حول الإصدار الحالي من واجهة برمجة التطبيقات.
على الرغم من أنّه تم نقل مواصفات وحدات عمل أداة الدمج إلى WICG وسيتم تطويرها، إلا أنّها المواصفات التي تهمّني أكثر من غيرها. يُفوِّض محرّك CSS بعض العمليات إلى بطاقة الرسومات في جهاز الكمبيوتر، إلا أنّ ذلك يعتمد على كلّ من بطاقة الرسومات وجهازك بشكل عام.
يأخذ المتصفّح عادةً شجرة DOM، واستنادًا إلى معايير محدّدة، يقرّر منح بعض الفروع والشُجَيرات الفرعية طبقتها الخاصة. ترسم هذه الأشجار الفرعية نفسها عليها (ربما باستخدام أوراق الطلاء في المستقبل). وكخطوة أخيرة، يتم تكديس كل هذه الطبقات الفردية المرسومة الآن ووضعها فوق بعضها البعض، مع مراعاة الفهارس z والتحولات ثلاثية الأبعاد وهكذا، لتقديم الصورة النهائية التي تظهر على شاشتك. تُعرف هذه العملية باسم التركيب، ويقوم بها أداة التركيب.
تتمثل ميزة عملية التركيب في أنك لست مضطرًا إلى إعادة طلاء جميع العناصر نفسها عندما يتم تمرير الصفحة قليلاً. بدلاً من ذلك، يمكنك إعادة استخدام الطبقات من اللقطة السابقة وإعادة تشغيل أداة الدمج باستخدام موضع التمرير المعدَّل. وهذا يجعل الأمور سريعة. يساعدنا ذلك في الوصول إلى معدل 60 لقطة في الثانية.
وكما يوحي الاسم، تتيح لك الوظيفة المصغّرة للمكوّن الإضافي الوصول إلى المُنشئ والتأثير في طريقة وضع طبقة العنصر، التي تم رسمها بالفعل، ووضعها فوق الطبقات الأخرى.
للحصول على مزيد من تحديد
، يمكنك إخبار المتصفّح بأنّك تريد الربط بعملية compositing
لعقدة DOM معيّنة، ويمكنك طلب الوصول إلى سمات معيّنة مثل
موضع التمرير أو transform
أو opacity
. يؤدي ذلك إلى فرض هذا العنصر على
طبقته الخاصة وفي كل إطار يتم استدعاء الرمز. يمكنك نقل الطبقة
من خلال التلاعب بتحويل الطبقات وتغيير سماتها (مثل opacity
)
ما يتيح لك تنفيذ إجراءات رائعة بمعدّل 60 لقطة في الثانية.
في ما يلي عملية تنفيذ كاملة لميزة التمرير البانورامي باستخدام ملف معالجة الصور المصغرة.
// main.js
window.compositorWorklet.import('worklet.js')
.then(function() {
var animator = new CompositorAnimator('parallax');
animator.postMessage([
new CompositorProxy($('.scroller'), ['scrollTop']),
new CompositorProxy($('.parallax'), ['transform']),
]);
});
// worklet.js
registerCompositorAnimator('parallax', class {
tick(timestamp) {
var t = self.parallax.transform;
t.m42 = -0.1 * self.scroller.scrollTop;
self.parallax.transform = t;
}
onmessage(e) {
self.scroller = e.data[0];
self.parallax = e.data[1];
};
});
لقد كتب روبرت فلاك polyfill لوظيفة التركيب المصغّرة حتى تتمكن من تجربتها - من الواضح أنّها ذات تأثير أعلى بكثير في الأداء.
أداة عمل التنسيق (المواصفات)
تم اقتراح أول مسودة حقيقية للمواصفات. لن يتم تنفيذ هذه الميزة إلا بعد فترة طويلة.
مرة أخرى، تكون المواصفات لهذه الميزة فارغة عمليًا، ولكن المفهوم هو
مثير للاهتمام: يمكنك كتابة التنسيق الخاص بك. من المفترض أن تتيح لك أداة تصميم الشبكة
تنفيذ display: layout('myLayout')
وتشغيل JavaScript لترتيب
العناصر التابعة للعقدة في مربّع العقدة.
بالطبع، إنّ تنفيذ تنسيق flex-box
في CSS باستخدام JavaScript بالكامل
يكون أبطأ من تنفيذ تنسيق مكافئ مضمّن، ولكن من السهل
تخيل سيناريو يمكن فيه تحقيق مكاسب في الأداء من خلال تقليل الوقت والمجهود. تخيل
موقعًا إلكترونيًا يتألف من مربّعات فقط، مثل Windows 10 أو تنسيق
مُعدّ على شكل مَعلمة. لا يتم استخدام موضع العنصر المطلق أو الثابت، ولا يتم استخدام z-index
، ولا تتراكب العناصر أبدًا أو يكون لها أي نوع من الحدود أو الفائض. يمكن أن يؤدي التمكّن من تخطّي
كل عمليات التحقّق هذه عند إعادة التنسيق إلى تحسين الأداء.
registerLayout('random-layout', class {
static get inputProperties() {
return [];
}
static get childrenInputProperties() {
return [];
}
layout(children, constraintSpace, styleMap) {
const width = constraintSpace.width;
const height = constraintSpace.height;
for (let child of children) {
const x = Math.random()*width;
const y = Math.random()*height;
const constraintSubSpace = new ConstraintSpace();
constraintSubSpace.width = width-x;
constraintSubSpace.height = height-y;
const childFragment = child.doLayout(constraintSubSpace);
childFragment.x = x;
childFragment.y = y;
}
return {
minContent: 0,
maxContent: 0,
width: width,
height: height,
fragments: [],
unPositionedChildren: [],
breakToken: null
};
}
});
نموذج CSSOM المكتوب (المواصفات)
يعالج نموذج CSSOM (نموذج عنصر CSS أو نموذج عنصر أوراق الأنماط المتتالية) مشكلة ربما واجهناها جميعًا وتعلّمنا التعامل معها. سأوضّح ذلك باستخدام سطر من JavaScript:
$('#someDiv').style.height = getRandomInt() + 'px';
نحن نجري عمليات حسابية، ونحوّل رقمًا إلى سلسلة لإلحاق وحدة به فقط لجعل المتصفّح يفكّك هذه السلسلة ويحوّلها مرة أخرى إلى رقم لمحرك CSS. ويزداد هذا الأمر صعوبات عند معالجة عمليات التحويل باستخدام JavaScript. ليس هناك المزيد خدمة CSS على وشك البدء في الكتابة.
هذه المسودة هي إحدى المسودات الأكثر نضجًا، ويتم حاليًا تطوير polyfill. (بيان إخلاء المسؤولية: سيؤدي استخدام الpolyfill بوضوح إلى زيادة التكلفة الحسابية. والهدف من ذلك هو توضيح مدى سهولة استخدام واجهة برمجة التطبيقات.)
بدلاً من السلاسل، ستتعامل مع StylePropertyMap
العنصر، حيث تمتلك كل سمة CSS مفتاحها الخاص بها ونوع القيمة المقابل. إنّ السمات
مثل width
لها LengthValue
كنوع القيمة. LengthValue
هو
قاموس لجميع وحدات CSS، مثل em
وrem
وpx
وpercent
وما إلى ذلك. سيؤدي ضبط
height: calc(5px + 5%)
إلى الحصول على LengthValue{px: 5, percent: 5}
. لا تقبل بعض
السمات، مثل box-sizing
، سوى كلمات رئيسية معيّنة، وبالتالي يكون لها نوع قيمة
KeywordValue
. ويمكن بعد ذلك التحقّق من صحة هذه السمات
أثناء التشغيل.
<div style="width: 200px;" id="div1"></div>
<div style="width: 300px;" id="div2"></div>
<div id="div3"></div>
<div style="margin-left: calc(5em + 50%);" id="div4"></div>
var w1 = $('#div1').styleMap.get('width');
var w2 = $('#div2').styleMap.get('width');
$('#div3').styleMap.set('background-size',
[new SimpleLength(200, 'px'), w1.add(w2)])
$('#div4')).styleMap.get('margin-left')
// => {em: 5, percent: 50}
السمات والقيم
هل لديك معرفة بـ "السمات المخصّصة لتنسيق CSS" (أو الاسم المعرِّف غير الرسمي لها "متغيّرات CSS")؟ هذا هو ولكن مع أنواع! حتى الآن، كان بإمكان المتغيّرات استخدام قيم سلاسل فقط وكانت تتم معالجة هذه القيم باستخدام أسلوب البحث والاستبدال البسيط. ستسمح لك هذه المسودة ليس فقط بتحديد نوع لمتغيّراتك، ولكن أيضًا بتحديد قيمة تلقائية والتأثير في سلوك اكتساب السمات باستخدام واجهة برمجة تطبيقات JavaScript. من الناحية الفنية، سيسمح هذا أيضًا بإضافة تأثيرات متحركة إلى الخصائص المخصصة باستخدام انتقالات CSS والرسوم المتحركة القياسية، وهو ما يتم تناوله أيضًا.
["--scale-x", "--scale-y"].forEach(function(name) {
document.registerProperty({
name: name,
syntax: "<number>",
inherits: false,
initialValue: "1"
});
});
مقاييس الخطوط
مقاييس الخطوط هي كما يبدو من اسمها. ما هو مربّع الحدود (أو مربّعات الحدود) عند عرض السلسلة X بالخط Y بالحجم Z؟ ماذا يحدث إذا استخدمت تعليقات توضيحية بتنسيق Ruby؟ لقد تلقّينا الكثير من الطلبات بشأن هذا الأمر، ومن المفترض أن يلبّي Houdini هذه الطلبات أخيرًا.
انتظر، فهناك المزيد.
هناك المزيد من المواصفات في قائمة المسودات في Houdini، ولكن مستقبلها غير مؤكد إلى حدٍ ما، وهي ليست أكثر من عناصر نائبة للأفكار. وتشمل الأمثلة على ذلك سلوكيات المحتوى الزائد المخصّصة وواجهة برمجة تطبيقات توسيع نطاق بنية CSS وتوسيع سلوك الانتقال إلى أعلى أو أسفل الصفحة الأصلي وأشياء أخرى مماثلة، وكلّها تتيح إجراء أشياء على منصة الويب لم تكن متاحة من قبل.
إصدارات تجريبية
لقد جعلت رمز العرض التجريبي مفتوح المصدر (العرض التجريبي المباشر باستخدام polyfill).