Houdini – הסרת מסתורי CSS

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

הזן את הודיני!

כוח המשימה של Houdini מורכב ממהנדסים ממוזילה, אפל, אופרה, Microsoft, HP, Intel ו-Google פועלות יחד כדי לחשוף חלקים מסוימים מנוע CSS למפתחי אתרים. צוות המשימה עובד על אוסף של טיוטות, במטרה לגרום ל-W3C לאשר אותן להפוך לטיוטות אינטרנט רגילים. הם הציבו לעצמם כמה יעדים כלליים, והפכו אותם טיוטות מפרט, שבתוכה נולדה קבוצה של תומכים, טיוטות מפרטים ברמה נמוכה יותר.

האוסף של הטיוטות האלה הוא מה שהכוונה בדרך כלל כשמישהו מדבר על "Houdini". נכון למועד הכתיבה, רשימת הטיוטות לא הושלמה, וחלק מהטיוטות הן רק placeholders.

המפרט

worklet (מפרט)

קובצי worklet כשלעצמם לא ממש שימושיים. הם קונספט של להפוך רבות מהטיוטות המאוחרות יותר. אם חשבתם על Web Workers לקרוא את המילה "worklet", אתם לא טועים. יש הרבה חפיפה בין מושגים. אז למה משהו חדש כשיש לנו כבר עובדים?

המטרה של Houdini היא לחשוף ממשקי API חדשים לאפשר למפתחי אתרים לחבר את הקוד שלהם למנוע ה-CSS המערכות סביבו. קשה להניח שלא מציאותי להניח שכמה יהיה צריך להריץ כל שקטעי קוד. אחת. מסגרת. חלק מהם צריכים מהגדרתו. יצירת ציטוט של המפרט של Web Worker:

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

CSS Paint API (מפרט)

ממשק ה-API של Paint מופעל כברירת מחדל ב-Chrome 65. לקריאת מבוא מפורט.

worklet של קומפוזיציה

ה-API שמתואר כאן יצא משימוש. worklet של המרכיב יש עוצב מחדש, ועכשיו הוא מוצע כ'עבודה של אנימציה'. מידע נוסף זמין באיטרציה הנוכחית של ה-API.

למרות שמפרט ה-worklet של הקומפוזיטור הועבר ל-WICG, כמה דברים שחשוב לזכור, זה המפרט שהכי מרגש אותי. במידה מסוימת הפעולות מתבצעות במיקור חוץ לכרטיס המסך של המחשב על ידי שירות ה-CSS למרות שתלוי בכרטיס הגרפי ובמכשיר שלך באופן כללי.

בדרך כלל דפדפן לוקח את עץ ה-DOM, ובהתאם לקריטריונים ספציפיים, מחליט לתת לכמה הסתעפויות ותתי-עצים שכבה משלהם. תתי-העצים האלה צובעים את עצמם (אולי הם משתמשים בחוברת צבע) העתידי). בשלב האחרון, השכבות הבודדות האלה מופיעות במקבצים ומוצבים זה על גבי זה, תוך ציות למדדי Z, לטרנספורמציות תלת-ממדיות כך שתתקבל התמונה הסופית שמוצגת במסך. התהליך הזה שנקראת compositing, והוא מופעל על ידי המחבר.

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

worklet של קומפוזיציה.

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

כדי לקבל קצת יותר תוכלו לומר לדפדפן שאתם רוצים להתחבר לצומת DOM מסוים ויכול לבקש גישה למאפיינים מסוימים, מעבר למיקום הגלילה, transform או opacity. הפעולה הזאת מאלצת את הרכיב שכבה נפרדת ובכל פריים, הקוד מקבל קריאה. אפשר להזיז את השכבה על ידי מניפולציה של השכבות שמתמרות ומשנה את המאפיינים שלהן (למשל opacity) שמאפשרת לעשות דברים מיוחדים בקצב מסחרר של 60fps.

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

// 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 עבור worklet של קומפוזיטור, כדי שתוכלו לנסות אותו - כמובן שעם השפעה גבוהה יותר על הביצועים.

worklet של הפריסה (מפרט)

הוצעה טיוטת מפרט אמיתי ראשונה. יישום זה זמן טוב.

שוב, המפרט הזה כמעט ריק, אבל העיקרון מעניין: כתבו פריסה משלכם! ה-worklet של הפריסה אמור לאפשר לכם כדי לעשות display: layout('myLayout') ולהריץ את ה-JavaScript כדי לארגן את הצאצאים בתיבה של הצומת.

כמובן, להפעיל הטמעה מלאה של JavaScript בפריסת flex-box של שירות ה-CSS. איטי יותר מהפעלה של יישום מקורי מקביל, אבל קל מאוד דמיינו תרחיש שבו הסרת הפינות יכולה להניב שיפור בביצועים. נחשוב על אתר שמכיל רק אריחים, כמו 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 יפעל כמובן להוסיף עוד תקורה חישובית. הנקודה היא להראות עד כמה נוח API).

במקום מחרוזות, עובדים על 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 API כדי להשפיע על התנהגות הירושה. מבחינה טכנית, תאפשר גם למאפיינים מותאמים אישית ליצור אנימציה עם מעברים רגילים של CSS ואנימציות, ומביאה בחשבון גם אותן.

["--scale-x", "--scale-y"].forEach(function(name) {
document.registerProperty({
    name: name,
    syntax: "<number>",
    inherits: false,
    initialValue: "1"
    });
});

מדדי הגופן

מדדי הגופן פועלים בדיוק כמו שהם נשמעים. מהי התיבה התוחמת ( תיבות תוחמות) כשמעבדים את מחרוזת X עם גופן Y בגודל Z? מה יקרה אם אשתמש להערות Ruby? התבקשנו הרבה בקשות, ועכשיו הודיני להגשים את המשאלות האלה.

רגע, יש עוד!

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

הדגמות

יצרתי קוד פתוח לקוד של ההדגמה (הדגמה פעילה באמצעות polyfill).