هودینی - رمزگشایی CSS

آیا تا به حال به میزان کاری که CSS انجام می دهد فکر کرده اید؟ شما یک ویژگی واحد را تغییر می‌دهید و ناگهان کل وب‌سایت شما در یک طرح‌بندی متفاوت ظاهر می‌شود. این یک نوع جادو است. تا کنون، ما - جامعه توسعه دهندگان وب - فقط توانسته ایم شاهد جادو و مشاهده آن باشیم. اگر بخواهیم جادوی خودمان را بسازیم چه؟ اگر بخواهیم شعبده باز شویم چه؟

وارد هودینی شوید!

گروه کاری هودینی متشکل از مهندسانی از موزیلا، اپل، اپرا، مایکروسافت، اچ پی، اینتل و گوگل است که با هم کار می کنند تا بخش های خاصی از موتور CSS را در معرض دید توسعه دهندگان وب قرار دهند. کارگروه در حال کار بر روی مجموعه ای از پیش نویس ها با هدف پذیرش آنها توسط W3C برای تبدیل شدن به استانداردهای واقعی وب است. آنها برای خود چند هدف سطح بالا تعیین کردند، آنها را به پیش نویس مشخصات تبدیل کردند که به نوبه خود مجموعه ای از پیش نویس های مشخصات پشتیبانی و سطح پایین را به وجود آورد.

مجموعه این پیش نویس ها همان چیزی است که معمولاً وقتی کسی در مورد «هودینی» صحبت می کند، منظور می شود. در زمان نگارش، فهرست پیش‌نویس‌ها ناقص است و برخی از پیش‌نویس‌ها صرفاً جایگاه‌دار هستند.

مشخصات

Worklets ( مشخصات )

Worklet ها به خودی خود واقعاً مفید نیستند. آنها مفهومی هستند که برای امکان پذیر ساختن بسیاری از پیش نویس های بعدی معرفی شده اند. اگر هنگام خواندن «worklet» به Web Workers فکر کردید، اشتباه نمی کنید. آنها همپوشانی مفهومی زیادی دارند. پس چرا یک چیز جدید در حالی که از قبل کارگر داریم؟

هدف هودینی افشای API های جدید است تا به توسعه دهندگان وب اجازه دهد تا کد خود را به موتور CSS و سیستم های اطراف متصل کنند. احتمالاً غیرواقعی نیست که فرض کنیم برخی از این قطعات کد باید هر بار اجرا شوند. مجرد قاب . برخی از آنها طبق تعریف مجبورند. به نقل از مشخصات Web Worker :

این بدان معناست که کارگران وب برای کارهایی که هودینی در نظر دارد انجام دهد، قابل دوام نیستند. بنابراین، ورکلت ها اختراع شدند. Worklet ها از کلاس های ES2015 برای تعریف مجموعه ای از متدها استفاده می کنند که امضاهای آنها بر اساس نوع Worklet از پیش تعریف شده اند. آنها سبک وزن و عمر کوتاهی دارند.

CSS Paint API ( مشخصات )

Paint API به طور پیش‌فرض در Chrome 65 فعال است. مقدمه مفصل را بخوانید.

کارنامه آهنگساز

API توضیح داده شده در اینجا منسوخ شده است. Worklet Compositor دوباره طراحی شده است و اکنون به عنوان "کارنامه انیمیشن" پیشنهاد شده است. در مورد تکرار فعلی API بیشتر بخوانید.

اگرچه مشخصات Worklet compositor به WICG منتقل شده است و در آن تکرار خواهد شد، این یکی از مشخصات است که من را بیشتر هیجان زده می کند. برخی از عملیات توسط موتور CSS به کارت گرافیک رایانه شما برون سپاری می شود، اگرچه این به کارت گرافیک و دستگاه شما به طور کلی بستگی دارد.

یک مرورگر معمولاً درخت DOM را می گیرد و بر اساس معیارهای خاص، تصمیم می گیرد به برخی از شاخه ها و زیردرخت ها لایه خاص خود را بدهد. این زیردرخت‌ها خود را روی آن نقاشی می‌کنند (شاید در آینده از یک برگه رنگ استفاده کنند). به عنوان آخرین مرحله، تمام این لایه‌های فردی که اکنون رنگ‌شده‌اند، با رعایت شاخص‌های z، تبدیل‌های سه‌بعدی و مواردی از این دست، روی هم چیده و روی هم قرار می‌گیرند تا تصویر نهایی قابل مشاهده در صفحه نمایش شما به دست آید. این فرآیند ترکیبی نامیده می شود و توسط کامپوزیتور اجرا می شود.

مزیت فرآیند ترکیب این است که مجبور نیستید وقتی صفحه کمی اسکرول می‌شود، همه عناصر را دوباره رنگ کنید. در عوض، می‌توانید از لایه‌های فریم قبلی دوباره استفاده کنید و فقط کامپوزیتور را با موقعیت اسکرول به‌روز شده دوباره اجرا کنید. این کارها را سریع می کند. این به ما کمک می کند تا به سرعت 60 فریم در ثانیه برسیم.

کارنامه آهنگساز.

همانطور که از نام آن پیداست، Worklet Compositor به شما این امکان را می‌دهد که به کامپوزیتور متصل شوید و بر نحوه قرارگیری و لایه‌بندی لایه عنصری که قبلاً رنگ‌شده است، روی لایه‌های دیگر تأثیر بگذارید.

برای کمی دقیق‌تر شدن، می‌توانید به مرورگر بگویید که می‌خواهید به فرآیند ترکیب برای یک گره DOM خاص متصل شوید و می‌توانید درخواست دسترسی به ویژگی‌های خاصی مانند موقعیت اسکرول، transform یا opacity داشته باشید. این عنصر را به لایه خودش وادار می کند و در هر فریم کد شما فراخوانی می شود. می‌توانید لایه‌تان را با دستکاری تبدیل لایه‌ها و تغییر ویژگی‌های آن (مانند opacity ) حرکت دهید که به شما امکان می‌دهد کارهای فانتزی-شمانسی را با سرعت فوق‌العاده ۶۰ فریم در ثانیه انجام دهید.

در اینجا یک پیاده سازی کامل برای پیمایش اختلاف منظر، با استفاده از Worklet Compositor آورده شده است.

// 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 compositor نوشته است تا بتوانید آن را امتحان کنید - بدیهی است که تأثیر عملکرد بسیار بالاتری دارد.

Worklet Layout ( مشخصات )

اولین پیش نویس مشخصات واقعی پیشنهاد شده است. پیاده سازی زمان خوبی است.

باز هم، مشخصات برای این عملا خالی است، اما مفهوم جالب است: طرح خود را بنویسید! قرار است worklet layout به شما امکان می دهد که display: layout('myLayout') را انجام دهید و جاوا اسکریپت خود را اجرا کنید تا فرزندان یک گره را در کادر گره مرتب کنید.

البته اجرای کامل جاوا اسکریپت flex-box CSS کندتر از اجرای یک پیاده سازی بومی معادل است، اما تصور سناریویی که در آن برش گوشه ها می تواند باعث افزایش عملکرد شود، آسان است. وب‌سایتی را تصور کنید که از چیزی جز کاشی‌ها مانند ویندوز 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 Object Model یا Cascading Style Sheets Object Model) به مشکلی می پردازد که احتمالاً همه ما با آن مواجه شده ایم و تازه یاد گرفته ایم که با آن کنار بیاییم. اجازه دهید با یک خط از جاوا اسکریپت توضیح دهم:

    $('#someDiv').style.height = getRandomInt() + 'px';

ما در حال انجام ریاضی هستیم، یک عدد را به رشته تبدیل می کنیم تا یک واحد را اضافه کنیم تا مرورگر آن رشته را تجزیه کند و آن را به یک عدد برای موتور CSS تبدیل کند. وقتی تبدیل ها را با جاوا اسکریپت دستکاری می کنید، این حتی زشت تر می شود. دیگر نه! CSS در آستانه تایپ کردن است.

این پیش نویس یکی از آنهایی است که بالغ تر است و پلی فیل در حال حاضر روی آن کار می شود. (سلب مسئولیت: استفاده از 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 رندر می‌کنم، کادر محدود (یا کادرهای کران‌دار) چیست؟ اگر بروم از حاشیه نویسی یاقوت استفاده کنم چه می شود؟ این خیلی درخواست شده است و هودینی باید بالاخره این آرزوها را محقق کند.

اما صبر کنید، چیزهای بیشتری وجود دارد!

حتی مشخصات بیشتری در فهرست پیش‌نویس‌های هودینی وجود دارد، اما آینده آن‌ها نسبتاً نامشخص است و آنها چیزی بیش از جایگاه‌دار ایده‌ها نیستند. به عنوان مثال می توان به رفتارهای سرریز سفارشی، API پسوند نحوی CSS، گسترش رفتار اسکرول بومی و موارد جاه طلبانه مشابهی اشاره کرد که همگی مواردی را در پلتفرم وب فعال می کنند که قبلاً امکان پذیر نبود.

دموها

من کد نسخه ی نمایشی را منبع باز کرده ام ( نسخه ی نمایشی زنده با استفاده از polyfill).