Houdini - CSS'nin Açıklanması

CSS'nin yaptığı iş miktarını hiç düşündünüz mü? Tek bir özelliği değiştirirsiniz ve aniden web sitenizin tamamı farklı bir düzende görünür. Biraz sihir gibi. Web geliştiricileri topluluğu olarak şimdiye kadar sihre tanıklık edip gözlemleyebildik. Kendi sihrimizi bulmak istiyorsak ne olacak? Peki ya sihirbaz olmak istiyorsak?

Houdini'yi girin!

Houdini görev ekibi, CSS motorunun belirli bölümlerini web geliştiricilerine sunmak için birlikte çalışan Mozilla, Apple, Opera, Microsoft, HP, Intel ve Google'dan mühendislerden oluşuyor. Görev ekibi, W3C tarafından kabul edilmelerini sağlayarak gerçek web standartları hâline getirmek amacıyla bir taslak koleksiyonu üzerinde çalışmaktadır. Birkaç üst düzey hedef belirleyip bunları spesifikasyon taslaklarına dönüştürdüler. Bunun sonucunda da bir dizi destekleyici, alt seviyeli spesifikasyon taslağı doğdular.

Birisi "Houdini"den bahsettiğinde genellikle bu taslakların derlenmesi anlamına gelir. Yazıldığı sırada, taslak listesi eksiktir ve taslakların bazıları yalnızca yer tutucudur.

Spesifikasyonlar

İş akışları (spec)

İş akışları tek başlarına pek kullanışlı olmaz. Bunlar, sonraki taslakların çoğunu mümkün kılmak için kullanıma sunulan bir kavramdır. "İş akışını" okurken Web İşçileri aklınıza geldiyse, yanılmazsınız. Kavramsal açıdan çok fazla örtüşüyor. Peki, zaten çalışanlarımız varken neden yeni bir şey olsun?

Houdini'nin hedefi, web geliştiricilerinin kendi kodlarını CSS motoruna ve çevredeki sistemlere bağlamalarına olanak tanımak için yeni API'ler sunmaktır. Bu kod parçalarından bazılarının her. tek bir çerçevede çalıştırılması gerektiğini varsaymak muhtemelen gerçekçi değildir. Bazıları tanımı gereği zorunludur. Web Çalışanı spesifikasyonundan alıntı yapma:

Yani web çalışanları, Houdini'nin yapmayı planladığı şeyler için uygun değil. Dolayısıyla iş araçları icat edildi. İş akışları, imzaları iş akışı türüne göre önceden tanımlanmış yöntemler koleksiyonunu tanımlamak için ES2015 sınıflarından yararlanır. Hafiftir ve kısa ömürlüdür.

CSS Paint API (spec)

Paint API, Chrome 65'te varsayılan olarak etkindir. Ayrıntılı tanıtımı okuyun.

Birleştirici iş uygulaması

Burada açıklanan API artık kullanılmıyor. Birleştirici iş akışı yeniden tasarlandı ve artık "Animasyon İş Akışı" olarak öneriliyor. API'nin mevcut yinelemesi hakkında daha fazla bilgi edinin.

Her ne kadar birleştirici iş akışı spesifikasyonu WICG'ye taşınmış ve tekrar uygulanacak olsa da beni en çok heyecanlandıran teknik spesifikasyon bu. Bazı işlemler, CSS motoru tarafından bilgisayarınızın grafik kartına aktarılır ancak bu, genel olarak hem grafik kartınıza hem de cihazınıza bağlıdır.

Tarayıcı genellikle DOM ağacını alır ve belirli ölçütlere göre bazı dallara ve alt ağaçlara kendi katmanlarını vermeye karar verir. Bu alt ağaçlar kendilerini boyayıp boyarlar (gelecekte bir boya işçisi de kullanabilirler). Son adım olarak, artık boyanmış olan tüm bu ayrı ayrı katmanlar üst üste yığılır ve birbirlerinin üzerine yerleştirilir. Z-endekslerine, 3D dönüşümlerine ve benzer noktalara göre, ekranınızda görünen nihai görüntüyü elde edersiniz. Bu işlem compositing olarak adlandırılır ve birleştirici tarafından yürütülür.

Birleştirme işleminin avantajı, sayfa biraz kaydırıldığında tüm öğelerin kendilerini yeniden boyaması zorunda kalmamanızdır. Bunun yerine, önceki karede bulunan katmanları yeniden kullanabilir ve birleştiriciyi güncellenmiş kaydırma konumuyla yeniden çalıştırabilirsiniz. Böylece işlemler hızlanır. Bu, 60 fps'ye ulaşmamıza yardımcı olur.

Birleştirici iş uygulaması.

Adından da anlaşılacağı gibi, birleştirici iş akışı, birleştiriciye bağlanmanıza ve önceden boyanmış olan bir öğe katmanının, diğer katmanların üzerine yerleştirilme ve katmanlanma şeklini etkilemenize olanak tanır.

Biraz daha ayrıntıya inmek için tarayıcıya, belirli bir DOM düğümü için birleştirme işlemine katılmak istediğinizi söyleyebilir ve kaydırma konumu, transform veya opacity gibi belirli özelliklere erişim isteğinde bulunabilirsiniz. Bu işlem, bu öğeyi kendi katmanına zorlar ve kodunuzun her karede çağrılmasını sağlar. Katmanların dönüşümünü değiştirerek katmanınızı taşıyabilir ve özelliklerini (opacity gibi) değiştirebilirsiniz. Böylece 60 kare/saniyede etkileyici şeyler yapabilirsiniz.

Aşağıda, birleştirici iş uygulamasını kullanarak paralaks kaydırmanın eksiksiz bir uygulamasını görebilirsiniz.

// 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];
    };
});

Robert Flack, deneyebileceğiniz birleştirici iş akışı için bir polyfill hazırladı. Bu, kesinlikle çok daha yüksek performans etkisine sahiptir.

Düzen iş akışı (spec)

İlk gerçek spesifikasyon taslağı önerildi. Uygulamanın uygulanması epey uzakta.

Bunun için teknik özellikler neredeyse boştur, ancak konsept ilgi çekicidir: Kendi düzeninizi yazın! Düzen iş uygulamasının, düğüm kutusunda bir düğümün alt öğelerini düzenlemek için display: layout('myLayout') işlemini yapmanızı ve JavaScript'inizi çalıştırmanızı sağlaması gerekir.

Elbette CSS'nin flex-box düzeninin tam JavaScript uygulamasını çalıştırmak eşdeğer bir yerel uygulamayı çalıştırmaktan daha yavaştır. Ancak köşeleri kesmenin performans kazancı sağlayabileceği bir senaryo düşünmek kolaydır. Windows 10 veya duvar tarzı bir düzen gibi çinilerden başka hiçbir şeyden oluşan bir web sitesi düşünün. Mutlak ve sabit konumlandırma kullanılmaz, z-index, öğeler de çakışmaz veya herhangi bir sınır ya da taşma içermez. Yeniden düzende tüm bu kontrolleri atlayabilmek performans kazancı sağlayabilir.

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
        };
    }
});

Yazılan CSSOM (spec)

Yazılan CSSOM (CSS Nesne Modeli veya Geçişli Stil Sayfaları Nesne Modeli), muhtemelen hepimizin karşılaştığı ve yeni öğrendiği bir sorunu ele alır. Bir JavaScript satırıyla örnekleyeyim:

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

Matematikle ilgili bir işlem yapıyoruz. Bunu, tarayıcının dizeyi ayrıştırıp CSS motoru için tekrar sayıya dönüştürmesini sağlamak üzere bir birimi eklemek için sayıyı dizeye dönüştürüyoruz. Dönüşümleri JavaScript ile değiştirdiğinizde bu durum daha da kötüleşir. Artık yok! CSS biraz yazacak.

Bu taslak, en olgun taslaklardan biridir ve şu anda bir polyfill üzerinde çalışılmaktadır. (Sorumluluk reddi beyanı: Çoklu dolgunun kullanılması açık bir şekilde daha da işlem ek yüküne neden olur. Amaç, API'nin ne kadar kullanışlı olduğunu göstermektir.)

Dize yerine, bir öğenin StylePropertyMap özelliği üzerinde çalışırsınız. Burada her CSS özelliği kendi anahtarı ve karşılık gelen değer türüne sahiptir. width gibi özelliklerin değer türü LengthValue. LengthValue; em, rem, px, percent vb. tüm CSS birimlerini içeren bir sözlüktür. height: calc(5px + 5%) ayarını yapmak LengthValue{px: 5, percent: 5} sonucunu verir. box-sizing gibi bazı mülkler, yalnızca belirli anahtar kelimeleri kabul eder ve bu nedenle KeywordValue değer türüne sahiptir. Daha sonra, bu özelliklerin geçerliliği çalışma zamanında kontrol edilebilir.

<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}

Özellikler ve değerler

(spec)

CSS Özel Mülklerini (veya bunların resmi olmayan takma adları "CSS Değişkenleri") biliyor musunuz? Bu onlar ancak türlerle! Şimdiye kadar değişkenler yalnızca dize değerlerine sahipti ve basit bir ara ve değiştir yaklaşımı kullanıyordu. Bu taslak hem değişkenleriniz için bir tür belirtmenize hem de bir JavaScript API kullanarak varsayılan bir değer tanımlamanıza ve devralma davranışını etkilemenize olanak tanır. Teknik olarak bu durum, özel özelliklerin standart CSS geçişleri ve animasyonlarla canlandırılmasına da olanak tanır. Bu geçişler, değerlendirilir.

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

Yazı tipi metrikleri

Yazı tipi metrikleri tam olarak adından anlaşıldığı gibidir. X dizesini Z boyutunda Y yazı tipiyle oluşturduğumda sınırlayıcı kutu (veya sınırlayıcı kutular) nedir? Ruby ek açıklamalarını kullanırsam ne olur? Bu çok talep edildi ve Houdini'nin nihayet bu dileklerini gerçekleştirmesi gerekiyor.

Bir saniye, hepsi bu kadar da değil!

Houdini'nin taslak listesinde daha da fazla özellik var, ancak bunların geleceği belirsiz ve bunlar yalnızca fikir için bir yer tutucudan ibaret değil. Örnekler arasında özel taşma davranışları, CSS söz dizimi uzantı API'si, yerel kaydırma davranışının uzantısı ve web platformunda daha önce mümkün olmayan özellikleri etkinleştiren benzer şekilde iddialı özellikler yer alır.

Demolar

Demonun kodunu açık kaynaklı yaptım (polyfill kullanarak canlı demo).